diff --git a/.github/workflows/stale_bot.yml b/.github/workflows/stale_bot.yml
index 411a70a463..df222a8483 100644
--- a/.github/workflows/stale_bot.yml
+++ b/.github/workflows/stale_bot.yml
@@ -8,41 +8,15 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- - uses: actions/stale@v8
- with:
- days-before-stale: 330
- operations-per-run: 1
- # stale rules for PRs
- days-before-pr-stale: 7
- stale-issue-label: stale
- exempt-pr-labels: pinned,security,roadmap
- days-before-pr-close: 7
- days-before-issue-close: 30
-
- - uses: actions/stale@v8
- with:
- operations-per-run: 3
- # stale rules for high priority bugs
- days-before-stale: 30
- only-issue-labels: bug,High priority
- stale-issue-label: warn
- days-before-close: 30
-
- - uses: actions/stale@v8
- with:
- operations-per-run: 3
- # stale rules for medium priority bugs
- days-before-stale: 90
- only-issue-labels: bug,Medium priority
- stale-issue-label: warn
- days-before-close: 30
-
- - uses: actions/stale@v8
- with:
- operations-per-run: 3
- # stale rules for all bugs
- days-before-stale: 180
- stale-issue-label: stale
- only-issue-labels: bug
- stale-issue-message: "This issue has been automatically marked as stale because it has not had any activity for six months."
- days-before-close: 30
+ - uses: actions/stale@v8
+ with:
+ # Issues
+ days-before-stale: 180
+ stale-issue-label: stale
+ days-before-close: 30
+ stale-issue-message: "This issue has been automatically marked as stale as there has been no activity for 6 months."
+ # Pull requests
+ days-before-pr-stale: 7
+ days-before-pr-close: 14
+ exempt-pr-labels: pinned,security,roadmap
+ operations-per-run: 100
diff --git a/lerna.json b/lerna.json
index d0f0bd23c5..50582f0a95 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,6 +1,6 @@
{
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
- "version": "3.2.42",
+ "version": "3.2.47",
"npmClient": "yarn",
"concurrency": 20,
"command": {
diff --git a/packages/backend-core/src/db/couch/connections.ts b/packages/backend-core/src/db/couch/connections.ts
index 5c7d7ec81d..9692b095a8 100644
--- a/packages/backend-core/src/db/couch/connections.ts
+++ b/packages/backend-core/src/db/couch/connections.ts
@@ -1,6 +1,6 @@
import env from "../../environment"
-export const getCouchInfo = (connection?: string) => {
+export const getCouchInfo = (connection?: string | null) => {
// clean out any auth credentials
const urlInfo = getUrlInfo(connection)
let username
@@ -45,7 +45,7 @@ export const getCouchInfo = (connection?: string) => {
}
}
-export const getUrlInfo = (url = env.COUCH_DB_URL) => {
+export const getUrlInfo = (url: string | null = env.COUCH_DB_URL) => {
let cleanUrl, username, password, host
if (url) {
// Ensure the URL starts with a protocol
diff --git a/packages/backend-core/src/db/tests/pouch.spec.js b/packages/backend-core/src/db/tests/pouch.spec.ts
similarity index 98%
rename from packages/backend-core/src/db/tests/pouch.spec.js
rename to packages/backend-core/src/db/tests/pouch.spec.ts
index f0abc82240..21632cff88 100644
--- a/packages/backend-core/src/db/tests/pouch.spec.js
+++ b/packages/backend-core/src/db/tests/pouch.spec.ts
@@ -1,5 +1,6 @@
require("../../../tests")
-const getUrlInfo = require("../couch").getUrlInfo
+
+import { getUrlInfo } from "../couch"
describe("pouch", () => {
describe("Couch DB URL parsing", () => {
diff --git a/packages/backend-core/src/index.ts b/packages/backend-core/src/index.ts
index dbdce51c50..d4e6e9a1ec 100644
--- a/packages/backend-core/src/index.ts
+++ b/packages/backend-core/src/index.ts
@@ -1,6 +1,5 @@
export * as configs from "./configs"
export * as events from "./events"
-export * as migrations from "./migrations"
export * as users from "./users"
export * as userUtils from "./users/utils"
export * as roles from "./security/roles"
diff --git a/packages/backend-core/src/migrations/definitions.ts b/packages/backend-core/src/migrations/definitions.ts
deleted file mode 100644
index 0dd57fe639..0000000000
--- a/packages/backend-core/src/migrations/definitions.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import {
- MigrationType,
- MigrationName,
- MigrationDefinition,
-} from "@budibase/types"
-
-export const DEFINITIONS: MigrationDefinition[] = [
- {
- type: MigrationType.GLOBAL,
- name: MigrationName.USER_EMAIL_VIEW_CASING,
- },
- {
- type: MigrationType.GLOBAL,
- name: MigrationName.SYNC_QUOTAS,
- },
- {
- type: MigrationType.APP,
- name: MigrationName.APP_URLS,
- },
- {
- type: MigrationType.APP,
- name: MigrationName.EVENT_APP_BACKFILL,
- },
- {
- type: MigrationType.APP,
- name: MigrationName.TABLE_SETTINGS_LINKS_TO_ACTIONS,
- },
- {
- type: MigrationType.GLOBAL,
- name: MigrationName.EVENT_GLOBAL_BACKFILL,
- },
- {
- type: MigrationType.INSTALLATION,
- name: MigrationName.EVENT_INSTALLATION_BACKFILL,
- },
- {
- type: MigrationType.GLOBAL,
- name: MigrationName.GLOBAL_INFO_SYNC_USERS,
- },
-]
diff --git a/packages/backend-core/src/migrations/index.ts b/packages/backend-core/src/migrations/index.ts
deleted file mode 100644
index bce0cfc75c..0000000000
--- a/packages/backend-core/src/migrations/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from "./migrations"
-export * from "./definitions"
diff --git a/packages/backend-core/src/migrations/migrations.ts b/packages/backend-core/src/migrations/migrations.ts
deleted file mode 100644
index c8320b5724..0000000000
--- a/packages/backend-core/src/migrations/migrations.ts
+++ /dev/null
@@ -1,186 +0,0 @@
-import { DEFAULT_TENANT_ID } from "../constants"
-import {
- DocumentType,
- StaticDatabases,
- getAllApps,
- getGlobalDBName,
- getDB,
-} from "../db"
-import environment from "../environment"
-import * as platform from "../platform"
-import * as context from "../context"
-import { DEFINITIONS } from "."
-import {
- Migration,
- MigrationOptions,
- MigrationType,
- MigrationNoOpOptions,
- App,
-} from "@budibase/types"
-
-export const getMigrationsDoc = async (db: any) => {
- // get the migrations doc
- try {
- return await db.get(DocumentType.MIGRATIONS)
- } catch (err: any) {
- if (err.status && err.status === 404) {
- return { _id: DocumentType.MIGRATIONS }
- } else {
- throw err
- }
- }
-}
-
-export const backPopulateMigrations = async (opts: MigrationNoOpOptions) => {
- // filter migrations to the type and populate a no-op migration
- const migrations: Migration[] = DEFINITIONS.filter(
- def => def.type === opts.type
- ).map(d => ({ ...d, fn: async () => {} }))
- await runMigrations(migrations, { noOp: opts })
-}
-
-export const runMigration = async (
- migration: Migration,
- options: MigrationOptions = {}
-) => {
- const migrationType = migration.type
- const migrationName = migration.name
- const silent = migration.silent
-
- const log = (message: string) => {
- if (!silent) {
- console.log(message)
- }
- }
-
- // get the db to store the migration in
- let dbNames: string[]
- if (migrationType === MigrationType.GLOBAL) {
- dbNames = [getGlobalDBName()]
- } else if (migrationType === MigrationType.APP) {
- if (options.noOp) {
- if (!options.noOp.appId) {
- throw new Error("appId is required for noOp app migration")
- }
- dbNames = [options.noOp.appId]
- } else {
- const apps = (await getAllApps(migration.appOpts)) as App[]
- dbNames = apps.map(app => app.appId)
- }
- } else if (migrationType === MigrationType.INSTALLATION) {
- dbNames = [StaticDatabases.PLATFORM_INFO.name]
- } else {
- throw new Error(`Unrecognised migration type [${migrationType}]`)
- }
-
- const length = dbNames.length
- let count = 0
-
- // run the migration against each db
- for (const dbName of dbNames) {
- count++
- const lengthStatement = length > 1 ? `[${count}/${length}]` : ""
-
- const db = getDB(dbName)
-
- try {
- const doc = await getMigrationsDoc(db)
-
- // the migration has already been run
- if (doc[migrationName]) {
- // check for force
- if (
- options.force &&
- options.force[migrationType] &&
- options.force[migrationType].includes(migrationName)
- ) {
- log(`[Migration: ${migrationName}] [DB: ${dbName}] Forcing`)
- } else {
- // no force, exit
- return
- }
- }
-
- // check if the migration is not a no-op
- if (!options.noOp) {
- log(
- `[Migration: ${migrationName}] [DB: ${dbName}] Running ${lengthStatement}`
- )
-
- if (migration.preventRetry) {
- // eagerly set the completion date
- // so that we never run this migration twice even upon failure
- doc[migrationName] = Date.now()
- const response = await db.put(doc)
- doc._rev = response.rev
- }
-
- // run the migration
- if (migrationType === MigrationType.APP) {
- await context.doInAppContext(db.name, async () => {
- await migration.fn(db)
- })
- } else {
- await migration.fn(db)
- }
-
- log(`[Migration: ${migrationName}] [DB: ${dbName}] Complete`)
- }
-
- // mark as complete
- doc[migrationName] = Date.now()
- await db.put(doc)
- } catch (err) {
- console.error(
- `[Migration: ${migrationName}] [DB: ${dbName}] Error: `,
- err
- )
- throw err
- }
- }
-}
-
-export const runMigrations = async (
- migrations: Migration[],
- options: MigrationOptions = {}
-) => {
- let tenantIds
-
- if (environment.MULTI_TENANCY) {
- if (options.noOp) {
- tenantIds = [options.noOp.tenantId]
- } else if (!options.tenantIds || !options.tenantIds.length) {
- // run for all tenants
- tenantIds = await platform.tenants.getTenantIds()
- } else {
- tenantIds = options.tenantIds
- }
- } else {
- // single tenancy
- tenantIds = [DEFAULT_TENANT_ID]
- }
-
- if (tenantIds.length > 1) {
- console.log(`Checking migrations for ${tenantIds.length} tenants`)
- } else {
- console.log("Checking migrations")
- }
-
- let count = 0
- // for all tenants
- for (const tenantId of tenantIds) {
- count++
- if (tenantIds.length > 1) {
- console.log(`Progress [${count}/${tenantIds.length}]`)
- }
- // for all migrations
- for (const migration of migrations) {
- // run the migration
- await context.doInTenant(
- tenantId,
- async () => await runMigration(migration, options)
- )
- }
- }
- console.log("Migrations complete")
-}
diff --git a/packages/backend-core/src/migrations/tests/__snapshots__/migrations.spec.ts.snap b/packages/backend-core/src/migrations/tests/__snapshots__/migrations.spec.ts.snap
deleted file mode 100644
index 377900b5d5..0000000000
--- a/packages/backend-core/src/migrations/tests/__snapshots__/migrations.spec.ts.snap
+++ /dev/null
@@ -1,11 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`migrations should match snapshot 1`] = `
-{
- "_id": "migrations",
- "_rev": "1-2f64479842a0513aa8b97f356b0b9127",
- "createdAt": "2020-01-01T00:00:00.000Z",
- "test": 1577836800000,
- "updatedAt": "2020-01-01T00:00:00.000Z",
-}
-`;
diff --git a/packages/backend-core/src/migrations/tests/migrations.spec.ts b/packages/backend-core/src/migrations/tests/migrations.spec.ts
deleted file mode 100644
index af2eb33cf5..0000000000
--- a/packages/backend-core/src/migrations/tests/migrations.spec.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-import { testEnv, DBTestConfiguration } from "../../../tests/extra"
-import * as migrations from "../index"
-import * as context from "../../context"
-import { MigrationType } from "@budibase/types"
-
-testEnv.multiTenant()
-
-describe("migrations", () => {
- const config = new DBTestConfiguration()
-
- const migrationFunction = jest.fn()
-
- const MIGRATIONS = [
- {
- type: MigrationType.GLOBAL,
- name: "test" as any,
- fn: migrationFunction,
- },
- ]
-
- beforeEach(() => {
- config.newTenant()
- })
-
- afterEach(async () => {
- jest.clearAllMocks()
- })
-
- const migrate = () => {
- return migrations.runMigrations(MIGRATIONS, {
- tenantIds: [config.tenantId],
- })
- }
-
- it("should run a new migration", async () => {
- await config.doInTenant(async () => {
- await migrate()
- expect(migrationFunction).toHaveBeenCalled()
- const db = context.getGlobalDB()
- const doc = await migrations.getMigrationsDoc(db)
- expect(doc.test).toBeDefined()
- })
- })
-
- it("should match snapshot", async () => {
- await config.doInTenant(async () => {
- await migrate()
- const doc = await migrations.getMigrationsDoc(context.getGlobalDB())
- expect(doc).toMatchSnapshot()
- })
- })
-
- it("should skip a previously run migration", async () => {
- await config.doInTenant(async () => {
- const db = context.getGlobalDB()
- await migrate()
- const previousDoc = await migrations.getMigrationsDoc(db)
- await migrate()
- const currentDoc = await migrations.getMigrationsDoc(db)
- expect(migrationFunction).toHaveBeenCalledTimes(1)
- expect(currentDoc.test).toBe(previousDoc.test)
- })
- })
-})
diff --git a/packages/backend-core/src/sql/sql.ts b/packages/backend-core/src/sql/sql.ts
index 5a6907faa0..334f1efdd4 100644
--- a/packages/backend-core/src/sql/sql.ts
+++ b/packages/backend-core/src/sql/sql.ts
@@ -1172,20 +1172,22 @@ class InternalBuilder {
nulls = value.direction === SortOrder.ASCENDING ? "first" : "last"
}
+ const composite = `${aliased}.${key}`
+ let identifier
+
if (this.isAggregateField(key)) {
- query = query.orderBy(key, direction, nulls)
+ identifier = this.rawQuotedIdentifier(key)
+ } else if (this.client === SqlClient.ORACLE) {
+ identifier = this.convertClobs(composite)
} else {
- let composite = `${aliased}.${key}`
- if (this.client === SqlClient.ORACLE) {
- query = query.orderByRaw(`?? ?? nulls ??`, [
- this.convertClobs(composite),
- this.knex.raw(direction),
- this.knex.raw(nulls as string),
- ])
- } else {
- query = query.orderBy(composite, direction, nulls)
- }
+ identifier = this.rawQuotedIdentifier(composite)
}
+
+ query = query.orderByRaw(`?? ?? ${nulls ? "nulls ??" : ""}`, [
+ identifier,
+ this.knex.raw(direction),
+ ...(nulls ? [this.knex.raw(nulls as string)] : []),
+ ])
}
}
@@ -1344,14 +1346,16 @@ class InternalBuilder {
// add the correlation to the overall query
subQuery = subQuery.where(
- correlatedTo,
+ this.rawQuotedIdentifier(correlatedTo),
"=",
this.rawQuotedIdentifier(correlatedFrom)
)
const standardWrap = (select: Knex.Raw): Knex.QueryBuilder => {
subQuery = subQuery
- .select(relationshipFields)
+ .select(
+ relationshipFields.map(field => this.rawQuotedIdentifier(field))
+ )
.limit(getRelationshipLimit())
// @ts-ignore - the from alias syntax isn't in Knex typing
return knex.select(select).from({
diff --git a/packages/backend-core/tests/core/users/users.spec.js b/packages/backend-core/tests/core/users/users.spec.ts
similarity index 67%
rename from packages/backend-core/tests/core/users/users.spec.js
rename to packages/backend-core/tests/core/users/users.spec.ts
index dde0d87fb7..b14f553266 100644
--- a/packages/backend-core/tests/core/users/users.spec.js
+++ b/packages/backend-core/tests/core/users/users.spec.ts
@@ -1,17 +1,17 @@
-const _ = require("lodash/fp")
-const { structures } = require("../../../tests")
+import { range } from "lodash/fp"
+import { structures } from "../.."
jest.mock("../../../src/context")
jest.mock("../../../src/db")
-const context = require("../../../src/context")
-const db = require("../../../src/db")
+import * as context from "../../../src/context"
+import * as db from "../../../src/db"
-const { getCreatorCount } = require("../../../src/users/users")
+import { getCreatorCount } from "../../../src/users/users"
describe("Users", () => {
- let getGlobalDBMock
- let paginationMock
+ let getGlobalDBMock: jest.SpyInstance
+ let paginationMock: jest.SpyInstance
beforeEach(() => {
jest.resetAllMocks()
@@ -22,11 +22,10 @@ describe("Users", () => {
jest.spyOn(db, "getGlobalUserParams")
})
- it("Retrieves the number of creators", async () => {
- const getUsers = (offset, limit, creators = false) => {
- const range = _.range(offset, limit)
+ it("retrieves the number of creators", async () => {
+ const getUsers = (offset: number, limit: number, creators = false) => {
const opts = creators ? { builder: { global: true } } : undefined
- return range.map(() => structures.users.user(opts))
+ return range(offset, limit).map(() => structures.users.user(opts))
}
const page1Data = getUsers(0, 8)
const page2Data = getUsers(8, 12, true)
diff --git a/packages/bbui/package.json b/packages/bbui/package.json
index 89f72bc46d..2caad20bf6 100644
--- a/packages/bbui/package.json
+++ b/packages/bbui/package.json
@@ -3,7 +3,7 @@
"description": "A UI solution used in the different Budibase projects.",
"version": "0.0.0",
"license": "MPL-2.0",
- "svelte": "src/index.js",
+ "svelte": "src/index.ts",
"module": "dist/bbui.mjs",
"exports": {
".": {
@@ -14,7 +14,8 @@
"./spectrum-icons-vite.js": "./src/spectrum-icons-vite.js"
},
"scripts": {
- "build": "vite build"
+ "build": "vite build",
+ "dev": "vite build --watch --mode=dev"
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "1.4.0",
diff --git a/packages/bbui/src/Icon/Icon.svelte b/packages/bbui/src/Icon/Icon.svelte
index 73ad8edd10..7438fab5fd 100644
--- a/packages/bbui/src/Icon/Icon.svelte
+++ b/packages/bbui/src/Icon/Icon.svelte
@@ -1,23 +1,23 @@
-
diff --git a/packages/bbui/src/Tooltip/AbsTooltip.svelte b/packages/bbui/src/Tooltip/AbsTooltip.svelte
index b85f4e1c03..a887db4102 100644
--- a/packages/bbui/src/Tooltip/AbsTooltip.svelte
+++ b/packages/bbui/src/Tooltip/AbsTooltip.svelte
@@ -23,7 +23,7 @@
export let type = TooltipType.Default
export let text = ""
export let fixed = false
- export let color = null
+ export let color = ""
export let noWrap = false
let wrapper
diff --git a/packages/bbui/src/Typography/Heading.svelte b/packages/bbui/src/Typography/Heading.svelte
index 90d53fb208..f48d5d958e 100644
--- a/packages/bbui/src/Typography/Heading.svelte
+++ b/packages/bbui/src/Typography/Heading.svelte
@@ -2,10 +2,10 @@
import "@spectrum-css/typography/dist/index-vars.css"
// Sizes
- export let size = "M"
- export let textAlign = undefined
- export let noPadding = false
- export let weight = "default" // light, heavy, default
+ export let size: "XS" | "S" | "M" | "L" = "M"
+ export let textAlign: string | undefined = undefined
+ export let noPadding: boolean = false
+ export let weight: "light" | "heavy" | "default" = "default"
(obj: T) => T
-}
diff --git a/packages/bbui/src/helpers.js b/packages/bbui/src/helpers.ts
similarity index 86%
rename from packages/bbui/src/helpers.js
rename to packages/bbui/src/helpers.ts
index 246587af44..330f381d53 100644
--- a/packages/bbui/src/helpers.js
+++ b/packages/bbui/src/helpers.ts
@@ -6,9 +6,8 @@ export const deepGet = helpers.deepGet
/**
* Generates a DOM safe UUID.
* Starting with a letter is important to make it DOM safe.
- * @return {string} a random DOM safe UUID
*/
-export function uuid() {
+export function uuid(): string {
return "cxxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx".replace(/[xy]/g, c => {
const r = (Math.random() * 16) | 0
const v = c === "x" ? r : (r & 0x3) | 0x8
@@ -18,22 +17,18 @@ export function uuid() {
/**
* Capitalises a string
- * @param string the string to capitalise
- * @return {string} the capitalised string
*/
-export const capitalise = string => {
+export const capitalise = (string?: string | null): string => {
if (!string) {
- return string
+ return ""
}
return string.substring(0, 1).toUpperCase() + string.substring(1)
}
/**
* Computes a short hash of a string
- * @param string the string to compute a hash of
- * @return {string} the hash string
*/
-export const hashString = string => {
+export const hashString = (string?: string | null): string => {
if (!string) {
return "0"
}
@@ -54,11 +49,12 @@ export const hashString = string => {
* will override the value "foo" rather than "bar".
* If a deep path is specified and the parent keys don't exist then these will
* be created.
- * @param obj the object
- * @param key the key
- * @param value the value
*/
-export const deepSet = (obj, key, value) => {
+export const deepSet = (
+ obj: Record | null,
+ key: string | null,
+ value: any
+): void => {
if (!obj || !key) {
return
}
@@ -82,9 +78,8 @@ export const deepSet = (obj, key, value) => {
/**
* Deeply clones an object. Functions are not supported.
- * @param obj the object to clone
*/
-export const cloneDeep = obj => {
+export const cloneDeep = (obj: T): T => {
if (!obj) {
return obj
}
@@ -93,9 +88,8 @@ export const cloneDeep = obj => {
/**
* Copies a value to the clipboard
- * @param value the value to copy
*/
-export const copyToClipboard = value => {
+export const copyToClipboard = (value: any): Promise => {
return new Promise(res => {
if (navigator.clipboard && window.isSecureContext) {
// Try using the clipboard API first
@@ -117,9 +111,12 @@ export const copyToClipboard = value => {
})
}
-// Parsed a date value. This is usually an ISO string, but can be a
+// Parse a date value. This is usually an ISO string, but can be a
// bunch of different formats and shapes depending on schema flags.
-export const parseDate = (value, { enableTime = true }) => {
+export const parseDate = (
+ value: string | dayjs.Dayjs | null,
+ { enableTime = true }
+): dayjs.Dayjs | null => {
// If empty then invalid
if (!value) {
return null
@@ -128,7 +125,7 @@ export const parseDate = (value, { enableTime = true }) => {
// Certain string values need transformed
if (typeof value === "string") {
// Check for time only values
- if (!isNaN(new Date(`0-${value}`))) {
+ if (!isNaN(new Date(`0-${value}`).valueOf())) {
value = `0-${value}`
}
@@ -153,9 +150,9 @@ export const parseDate = (value, { enableTime = true }) => {
// Stringifies a dayjs object to create an ISO string that respects the various
// schema flags
export const stringifyDate = (
- value,
+ value: null | dayjs.Dayjs,
{ enableTime = true, timeOnly = false, ignoreTimezones = false } = {}
-) => {
+): string | null => {
if (!value) {
return null
}
@@ -192,7 +189,7 @@ export const stringifyDate = (
}
// Determine the dayjs-compatible format of the browser's default locale
-const getPatternForPart = part => {
+const getPatternForPart = (part: Intl.DateTimeFormatPart): string => {
switch (part.type) {
case "day":
return "D".repeat(part.value.length)
@@ -214,9 +211,9 @@ const localeDateFormat = new Intl.DateTimeFormat()
// Formats a dayjs date according to schema flags
export const getDateDisplayValue = (
- value,
+ value: dayjs.Dayjs | null,
{ enableTime = true, timeOnly = false } = {}
-) => {
+): string => {
if (!value?.isValid()) {
return ""
}
@@ -229,7 +226,7 @@ export const getDateDisplayValue = (
}
}
-export const hexToRGBA = (color, opacity) => {
+export const hexToRGBA = (color: string, opacity: number): string => {
if (color.includes("#")) {
color = color.replace("#", "")
}
diff --git a/packages/bbui/src/index.js b/packages/bbui/src/index.ts
similarity index 100%
rename from packages/bbui/src/index.js
rename to packages/bbui/src/index.ts
diff --git a/packages/bbui/svelte.config.js b/packages/bbui/svelte.config.js
new file mode 100644
index 0000000000..7d908c15d5
--- /dev/null
+++ b/packages/bbui/svelte.config.js
@@ -0,0 +1,7 @@
+const { vitePreprocess } = require("@sveltejs/vite-plugin-svelte")
+
+const config = {
+ preprocess: vitePreprocess(),
+}
+
+module.exports = config
diff --git a/packages/bbui/tsconfig.json b/packages/bbui/tsconfig.json
new file mode 100644
index 0000000000..2fe17da42e
--- /dev/null
+++ b/packages/bbui/tsconfig.json
@@ -0,0 +1,19 @@
+{
+ "extends": "../../tsconfig.build.json",
+ "compilerOptions": {
+ "allowJs": true,
+ "outDir": "./dist",
+ "lib": ["ESNext"],
+ "baseUrl": ".",
+ "paths": {
+ "@budibase/*": [
+ "../*/src/index.ts",
+ "../*/src/index.js",
+ "../*",
+ "../../node_modules/@budibase/*"
+ ]
+ }
+ },
+ "include": ["./src/**/*"],
+ "exclude": ["node_modules", "**/*.json", "**/*.spec.ts", "**/*.spec.js"]
+}
\ No newline at end of file
diff --git a/packages/bbui/vite.config.js b/packages/bbui/vite.config.js
index bf0f9fc26d..bccca20e43 100644
--- a/packages/bbui/vite.config.js
+++ b/packages/bbui/vite.config.js
@@ -9,7 +9,7 @@ export default defineConfig(({ mode }) => {
build: {
sourcemap: !isProduction,
lib: {
- entry: "src/index.js",
+ entry: "src/index.ts",
formats: ["es"],
},
},
diff --git a/packages/builder/package.json b/packages/builder/package.json
index 71d1c32008..6fcf72c5fb 100644
--- a/packages/builder/package.json
+++ b/packages/builder/package.json
@@ -74,7 +74,6 @@
"dayjs": "^1.10.8",
"downloadjs": "1.4.7",
"fast-json-patch": "^3.1.1",
- "json-format-highlight": "^1.0.4",
"lodash": "4.17.21",
"posthog-js": "^1.118.0",
"remixicon": "2.5.0",
@@ -94,6 +93,7 @@
"@sveltejs/vite-plugin-svelte": "1.4.0",
"@testing-library/jest-dom": "6.4.2",
"@testing-library/svelte": "^4.1.0",
+ "@types/sanitize-html": "^2.13.0",
"@types/shortid": "^2.2.0",
"babel-jest": "^29.6.2",
"identity-obj-proxy": "^3.0.0",
diff --git a/packages/builder/src/components/automation/SetupPanel/CronBuilder.svelte b/packages/builder/src/components/automation/SetupPanel/CronBuilder.svelte
index f04c5454ea..1490baa602 100644
--- a/packages/builder/src/components/automation/SetupPanel/CronBuilder.svelte
+++ b/packages/builder/src/components/automation/SetupPanel/CronBuilder.svelte
@@ -9,7 +9,7 @@
} from "@budibase/bbui"
import { onMount, createEventDispatcher } from "svelte"
import { flags } from "@/stores/builder"
- import { featureFlags, licensing } from "@/stores/portal"
+ import { licensing } from "@/stores/portal"
import { API } from "@/api"
import MagicWand from "../../../../assets/MagicWand.svelte"
@@ -27,8 +27,7 @@
let loadingAICronExpression = false
$: aiEnabled =
- ($featureFlags.AI_CUSTOM_CONFIGS && $licensing.customAIConfigsEnabled) ||
- ($featureFlags.BUDIBASE_AI && $licensing.budibaseAIEnabled)
+ $licensing.customAIConfigsEnabled || $licensing.budibaseAIEnabled
$: {
if (cronExpression) {
try {
diff --git a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte
index 55ac8474a6..4af1dcc0ee 100644
--- a/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte
+++ b/packages/builder/src/components/backend/DataTable/modals/CreateEditColumn.svelte
@@ -26,7 +26,7 @@
import { createEventDispatcher, getContext, onMount } from "svelte"
import { cloneDeep } from "lodash/fp"
import { tables, datasources } from "@/stores/builder"
- import { featureFlags } from "@/stores/portal"
+ import { licensing } from "@/stores/portal"
import { TableNames, UNEDITABLE_USER_FIELDS } from "@/constants"
import {
FIELDS,
@@ -100,7 +100,8 @@
let optionsValid = true
$: rowGoldenSample = RowUtils.generateGoldenSample($rows)
- $: aiEnabled = $featureFlags.BUDIBASE_AI || $featureFlags.AI_CUSTOM_CONFIGS
+ $: aiEnabled =
+ $licensing.customAIConfigsEnabled || $licensing.budibaseAiEnabled
$: if (primaryDisplay) {
editableColumn.constraints.presence = { allowEmpty: false }
}
diff --git a/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte b/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte
index f94d26603d..bc88f0f981 100644
--- a/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte
+++ b/packages/builder/src/components/common/CodeEditor/CodeEditor.svelte
@@ -1,4 +1,4 @@
-
@@ -58,7 +68,7 @@