From 5f353a85f7f9668d59e6cd9fa1e01a0a8e7891ff Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Wed, 8 Jan 2025 10:55:11 +0000 Subject: [PATCH 01/29] permissions store --- .../builder/src/stores/builder/permissions.js | 27 ----------- .../builder/src/stores/builder/permissions.ts | 47 +++++++++++++++++++ 2 files changed, 47 insertions(+), 27 deletions(-) delete mode 100644 packages/builder/src/stores/builder/permissions.js create mode 100644 packages/builder/src/stores/builder/permissions.ts diff --git a/packages/builder/src/stores/builder/permissions.js b/packages/builder/src/stores/builder/permissions.js deleted file mode 100644 index a303cd713b..0000000000 --- a/packages/builder/src/stores/builder/permissions.js +++ /dev/null @@ -1,27 +0,0 @@ -import { writable } from "svelte/store" -import { API } from "@/api" - -export function createPermissionStore() { - const { subscribe } = writable([]) - - return { - subscribe, - save: async ({ level, role, resource }) => { - return await API.updatePermissionForResource(resource, role, level) - }, - remove: async ({ level, role, resource }) => { - return await API.removePermissionFromResource(resource, role, level) - }, - forResource: async resourceId => { - return (await API.getPermissionForResource(resourceId)).permissions - }, - forResourceDetailed: async resourceId => { - return await API.getPermissionForResource(resourceId) - }, - getDependantsInfo: async resourceId => { - return await API.getDependants(resourceId) - }, - } -} - -export const permissions = createPermissionStore() diff --git a/packages/builder/src/stores/builder/permissions.ts b/packages/builder/src/stores/builder/permissions.ts new file mode 100644 index 0000000000..002b73893e --- /dev/null +++ b/packages/builder/src/stores/builder/permissions.ts @@ -0,0 +1,47 @@ +import { BudiStore } from "../BudiStore" +import { API } from "@/api" +import { + PermissionLevel, + GetResourcePermsResponse, + GetDependantResourcesResponse, +} from "@budibase/types" + +interface Permission { + level: PermissionLevel + role: string + resource: string +} + +export class PermissionStore extends BudiStore { + constructor() { + super([]) + } + + save = async (permission: Permission) => { + const { level, role, resource } = permission + return await API.updatePermissionForResource(resource, role, level) + } + + remove = async (permission: Permission) => { + const { level, role, resource } = permission + return await API.removePermissionFromResource(resource, role, level) + } + + forResource = async (resourceId: string): Promise => { + return (await API.getPermissionForResource(resourceId)).permissions + } + + forResourceDetailed = async ( + resourceId: string + ): Promise => { + return await API.getPermissionForResource(resourceId) + } + + getDependantsInfo = async ( + resourceId: string + ): Promise => { + return await API.getDependants(resourceId) + } +} + +export const permissions = new PermissionStore() From a983292865fee9980342d23af16a8d9ed20c6a64 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Wed, 8 Jan 2025 11:14:56 +0000 Subject: [PATCH 02/29] fix return type --- packages/builder/src/stores/builder/permissions.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/builder/src/stores/builder/permissions.ts b/packages/builder/src/stores/builder/permissions.ts index 002b73893e..6056449150 100644 --- a/packages/builder/src/stores/builder/permissions.ts +++ b/packages/builder/src/stores/builder/permissions.ts @@ -4,6 +4,7 @@ import { PermissionLevel, GetResourcePermsResponse, GetDependantResourcesResponse, + ResourcePermissionInfo, } from "@budibase/types" interface Permission { @@ -27,7 +28,9 @@ export class PermissionStore extends BudiStore { return await API.removePermissionFromResource(resource, role, level) } - forResource = async (resourceId: string): Promise => { + forResource = async ( + resourceId: string + ): Promise> => { return (await API.getPermissionForResource(resourceId)).permissions } From b6418c333cf422857f64db84f963f96e12a061d4 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Thu, 9 Jan 2025 09:20:16 +0000 Subject: [PATCH 03/29] views v1 --- packages/builder/src/stores/builder/views.js | 67 -------------- packages/builder/src/stores/builder/views.ts | 94 ++++++++++++++++++++ 2 files changed, 94 insertions(+), 67 deletions(-) delete mode 100644 packages/builder/src/stores/builder/views.js create mode 100644 packages/builder/src/stores/builder/views.ts diff --git a/packages/builder/src/stores/builder/views.js b/packages/builder/src/stores/builder/views.js deleted file mode 100644 index 07c356f56d..0000000000 --- a/packages/builder/src/stores/builder/views.js +++ /dev/null @@ -1,67 +0,0 @@ -import { writable, derived } from "svelte/store" -import { tables } from "./tables" -import { API } from "@/api" - -export function createViewsStore() { - const store = writable({ - selectedViewName: null, - }) - const derivedStore = derived([store, tables], ([$store, $tables]) => { - let list = [] - $tables.list?.forEach(table => { - const views = Object.values(table?.views || {}).filter(view => { - return view.version !== 2 - }) - list = list.concat(views) - }) - return { - ...$store, - list, - selected: list.find(view => view.name === $store.selectedViewName), - } - }) - - const select = name => { - store.update(state => ({ - ...state, - selectedViewName: name, - })) - } - - const deleteView = async view => { - await API.deleteView(view.name) - - // Update tables - tables.update(state => { - const table = state.list.find(table => table._id === view.tableId) - delete table.views[view.name] - return { ...state } - }) - } - - const save = async view => { - const savedView = await API.saveView(view) - select(view.name) - - // Update tables - tables.update(state => { - const table = state.list.find(table => table._id === view.tableId) - if (table) { - if (view.originalName) { - delete table.views[view.originalName] - } - table.views[view.name] = savedView - } - return { ...state } - }) - } - - return { - subscribe: derivedStore.subscribe, - select, - delete: deleteView, - save, - } -} - -export const views = createViewsStore() diff --git a/packages/builder/src/stores/builder/views.ts b/packages/builder/src/stores/builder/views.ts new file mode 100644 index 0000000000..4e309e180d --- /dev/null +++ b/packages/builder/src/stores/builder/views.ts @@ -0,0 +1,94 @@ +import { DerivedBudiStore } from "../BudiStore" +import { tables } from "./tables" +import { API } from "@/api" +import { View } from "@budibase/types" +import { helpers } from "@budibase/shared-core" +import { derived, Writable } from "svelte/store" + +interface BuilderViewStore { + selectedViewName: string | null +} + +interface DerivedViewStore extends BuilderViewStore { + list: View[] + selected?: View +} + +export class ViewsStore extends DerivedBudiStore< + BuilderViewStore, + DerivedViewStore +> { + constructor() { + const makeDerivedStore = (store: Writable) => { + return derived([store, tables], ([$store, $tables]): DerivedViewStore => { + let list: View[] = [] + $tables.list?.forEach(table => { + const views = Object.values(table?.views || {}).filter( + (view): view is View => !helpers.views.isV2(view) + ) + list = list.concat(views) + }) + return { + selectedViewName: $store.selectedViewName, + list, + selected: list.find(view => view.name === $store.selectedViewName), + } + }) + } + + super( + { + selectedViewName: null, + }, + makeDerivedStore + ) + + this.select = this.select.bind(this) + } + + select = (name: string) => { + this.store.update(state => ({ + ...state, + selectedViewName: name, + })) + } + + delete = async (view: View) => { + if (!view.name) { + return + } + await API.deleteView(view.name) + + // Update tables + tables.update(state => { + const table = state.list.find(table => table._id === view.tableId) + if (table?.views && view.name) { + delete table.views[view.name] + } + return { ...state } + }) + } + + save = async (view: View & { originalName?: string }) => { + if (!view.name) { + return + } + + const savedView = await API.saveView(view) + this.select(view.name) + + // Update tables + tables.update(state => { + const table = state.list.find(table => table._id === view.tableId) + if (table?.views && view.name) { + if (view.originalName) { + delete table.views[view.originalName] + } + table.views[view.name] = savedView + } + return { ...state } + }) + } +} + +export const views = new ViewsStore() From 0bc1e33ef3e79c3edc9485c0017674f87e2f6d16 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Mon, 13 Jan 2025 18:20:22 +0000 Subject: [PATCH 04/29] pr comments --- packages/builder/src/stores/builder/views.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/builder/src/stores/builder/views.ts b/packages/builder/src/stores/builder/views.ts index 4e309e180d..81085fcb42 100644 --- a/packages/builder/src/stores/builder/views.ts +++ b/packages/builder/src/stores/builder/views.ts @@ -55,7 +55,7 @@ export class ViewsStore extends DerivedBudiStore< delete = async (view: View) => { if (!view.name) { - return + throw new Error("View name is required") } await API.deleteView(view.name) @@ -71,7 +71,7 @@ export class ViewsStore extends DerivedBudiStore< save = async (view: View & { originalName?: string }) => { if (!view.name) { - return + throw new Error("View name is required") } const savedView = await API.saveView(view) From d9eb7eaa552523a46d09c38f6fc379dcec347a5c Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 13 Jan 2025 13:34:09 +0100 Subject: [PATCH 05/29] Type constants --- .../src/constants/backend/{automations.js => automations.ts} | 0 .../builder/src/constants/backend/{backups.js => backups.ts} | 0 packages/builder/src/constants/backend/{index.js => index.ts} | 3 ++- 3 files changed, 2 insertions(+), 1 deletion(-) rename packages/builder/src/constants/backend/{automations.js => automations.ts} (100%) rename packages/builder/src/constants/backend/{backups.js => backups.ts} (100%) rename packages/builder/src/constants/backend/{index.js => index.ts} (98%) diff --git a/packages/builder/src/constants/backend/automations.js b/packages/builder/src/constants/backend/automations.ts similarity index 100% rename from packages/builder/src/constants/backend/automations.js rename to packages/builder/src/constants/backend/automations.ts diff --git a/packages/builder/src/constants/backend/backups.js b/packages/builder/src/constants/backend/backups.ts similarity index 100% rename from packages/builder/src/constants/backend/backups.js rename to packages/builder/src/constants/backend/backups.ts diff --git a/packages/builder/src/constants/backend/index.js b/packages/builder/src/constants/backend/index.ts similarity index 98% rename from packages/builder/src/constants/backend/index.js rename to packages/builder/src/constants/backend/index.ts index 6ddf4c2138..c28416ac3e 100644 --- a/packages/builder/src/constants/backend/index.js +++ b/packages/builder/src/constants/backend/index.ts @@ -4,6 +4,7 @@ import { INTERNAL_TABLE_SOURCE_ID, AutoFieldSubType, Hosting, + FieldSubType, } from "@budibase/types" import { Constants } from "@budibase/frontend-core" @@ -209,7 +210,7 @@ export const Roles = { BUILDER: "BUILDER", } -export function isAutoColumnUserRelationship(subtype) { +export function isAutoColumnUserRelationship(subtype: FieldSubType) { return ( subtype === AUTO_COLUMN_SUB_TYPES.CREATED_BY || subtype === AUTO_COLUMN_SUB_TYPES.UPDATED_BY From 1bf99d31de180ac35479b1b3866eb781c836207c Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 13 Jan 2025 13:34:46 +0100 Subject: [PATCH 06/29] Type constants --- packages/builder/src/constants/{index.js => index.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/builder/src/constants/{index.js => index.ts} (100%) diff --git a/packages/builder/src/constants/index.js b/packages/builder/src/constants/index.ts similarity index 100% rename from packages/builder/src/constants/index.js rename to packages/builder/src/constants/index.ts From 2fd120c656e6d605a69b186b174b2e50d66156c8 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 13 Jan 2025 13:36:25 +0100 Subject: [PATCH 07/29] Convert utils --- packages/builder/src/helpers/keyUtils.js | 7 ------- packages/builder/src/helpers/keyUtils.ts | 7 +++++++ packages/builder/src/helpers/{utils.js => utils.ts} | 0 3 files changed, 7 insertions(+), 7 deletions(-) delete mode 100644 packages/builder/src/helpers/keyUtils.js create mode 100644 packages/builder/src/helpers/keyUtils.ts rename packages/builder/src/helpers/{utils.js => utils.ts} (100%) diff --git a/packages/builder/src/helpers/keyUtils.js b/packages/builder/src/helpers/keyUtils.js deleted file mode 100644 index 8d6dfb06dc..0000000000 --- a/packages/builder/src/helpers/keyUtils.js +++ /dev/null @@ -1,7 +0,0 @@ -function handleEnter(fnc) { - return e => e.key === "Enter" && fnc() -} - -export const keyUtils = { - handleEnter, -} diff --git a/packages/builder/src/helpers/keyUtils.ts b/packages/builder/src/helpers/keyUtils.ts new file mode 100644 index 0000000000..f78b05ec2b --- /dev/null +++ b/packages/builder/src/helpers/keyUtils.ts @@ -0,0 +1,7 @@ +function handleEnter(fnc: () => void) { + return (e: KeyboardEvent) => e.key === "Enter" && fnc() +} + +export const keyUtils = { + handleEnter, +} diff --git a/packages/builder/src/helpers/utils.js b/packages/builder/src/helpers/utils.ts similarity index 100% rename from packages/builder/src/helpers/utils.js rename to packages/builder/src/helpers/utils.ts From 819f6f52e3cbb71a3e90ff0f07a4699ca14ff7dd Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 13 Jan 2025 13:48:20 +0100 Subject: [PATCH 08/29] Typings --- .../builder/src/constants/backend/index.ts | 5 +++- packages/builder/src/helpers/utils.ts | 27 ++++++++++++++----- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/packages/builder/src/constants/backend/index.ts b/packages/builder/src/constants/backend/index.ts index c28416ac3e..910823a553 100644 --- a/packages/builder/src/constants/backend/index.ts +++ b/packages/builder/src/constants/backend/index.ts @@ -17,7 +17,10 @@ export { export const AUTO_COLUMN_SUB_TYPES = AutoFieldSubType -export const AUTO_COLUMN_DISPLAY_NAMES = { +export const AUTO_COLUMN_DISPLAY_NAMES: Record< + keyof typeof AUTO_COLUMN_SUB_TYPES, + string +> = { AUTO_ID: "Auto ID", CREATED_BY: "Created By", CREATED_AT: "Created At", diff --git a/packages/builder/src/helpers/utils.ts b/packages/builder/src/helpers/utils.ts index 7af7d4ad22..988f4cbb99 100644 --- a/packages/builder/src/helpers/utils.ts +++ b/packages/builder/src/helpers/utils.ts @@ -1,4 +1,4 @@ -import { FieldType } from "@budibase/types" +import { AutoFieldSubType, Automation, FieldType } from "@budibase/types" import { ActionStepID } from "@/constants/backend/automations" import { TableNames } from "@/constants" import { @@ -8,8 +8,14 @@ import { isAutoColumnUserRelationship, } from "@/constants/backend" -export function getAutoColumnInformation(enabled = true) { - let info = {} +type AutoColumnInformation = Partial< + Record +> + +export function getAutoColumnInformation( + enabled = true +): AutoColumnInformation { + const info: AutoColumnInformation = {} for (const [key, subtype] of Object.entries(AUTO_COLUMN_SUB_TYPES)) { // Because it's possible to replicate the functionality of CREATED_AT and // CREATED_BY columns with user column default values, we disable their creation @@ -19,13 +25,20 @@ export function getAutoColumnInformation(enabled = true) { ) { continue } - - info[subtype] = { enabled, name: AUTO_COLUMN_DISPLAY_NAMES[key] } + const typedKey = key as keyof typeof AUTO_COLUMN_SUB_TYPES + info[subtype] = { + enabled, + name: AUTO_COLUMN_DISPLAY_NAMES[typedKey], + } } return info } -export function buildAutoColumn(tableName, name, subtype) { +export function buildAutoColumn( + tableName: string, + name: string, + subtype: AutoFieldSubType +) { let type, constraints switch (subtype) { case AUTO_COLUMN_SUB_TYPES.UPDATED_BY: @@ -65,7 +78,7 @@ export function buildAutoColumn(tableName, name, subtype) { return base } -export function checkForCollectStep(automation) { +export function checkForCollectStep(automation: Automation) { return automation.definition.steps.some( step => step.stepId === ActionStepID.COLLECT ) From d97c492d36bac6004b92ce29f0eaa59e5b16345e Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 13 Jan 2025 14:06:24 +0100 Subject: [PATCH 09/29] Typing utils --- .../builder/src/constants/backend/index.ts | 8 -- packages/builder/src/helpers/utils.ts | 75 +++++++++++-------- .../types/src/documents/app/table/schema.ts | 1 + 3 files changed, 44 insertions(+), 40 deletions(-) diff --git a/packages/builder/src/constants/backend/index.ts b/packages/builder/src/constants/backend/index.ts index 910823a553..b7d3f584be 100644 --- a/packages/builder/src/constants/backend/index.ts +++ b/packages/builder/src/constants/backend/index.ts @@ -4,7 +4,6 @@ import { INTERNAL_TABLE_SOURCE_ID, AutoFieldSubType, Hosting, - FieldSubType, } from "@budibase/types" import { Constants } from "@budibase/frontend-core" @@ -213,13 +212,6 @@ export const Roles = { BUILDER: "BUILDER", } -export function isAutoColumnUserRelationship(subtype: FieldSubType) { - return ( - subtype === AUTO_COLUMN_SUB_TYPES.CREATED_BY || - subtype === AUTO_COLUMN_SUB_TYPES.UPDATED_BY - ) -} - export const PrettyRelationshipDefinitions = { MANY: "Many rows", ONE: "One row", diff --git a/packages/builder/src/helpers/utils.ts b/packages/builder/src/helpers/utils.ts index 988f4cbb99..140daaef3b 100644 --- a/packages/builder/src/helpers/utils.ts +++ b/packages/builder/src/helpers/utils.ts @@ -1,12 +1,20 @@ -import { AutoFieldSubType, Automation, FieldType } from "@budibase/types" +import { + AutoFieldSubType, + Automation, + DateFieldMetadata, + FieldType, + NumberFieldMetadata, + RelationshipFieldMetadata, + RelationshipType, +} from "@budibase/types" import { ActionStepID } from "@/constants/backend/automations" import { TableNames } from "@/constants" import { AUTO_COLUMN_DISPLAY_NAMES, AUTO_COLUMN_SUB_TYPES, FIELDS, - isAutoColumnUserRelationship, } from "@/constants/backend" +import { utils } from "@budibase/shared-core" type AutoColumnInformation = Partial< Record @@ -38,44 +46,47 @@ export function buildAutoColumn( tableName: string, name: string, subtype: AutoFieldSubType -) { - let type, constraints +): RelationshipFieldMetadata | NumberFieldMetadata | DateFieldMetadata { + const base = { + name, + icon: "ri-magic-line", + autocolumn: true, + } + switch (subtype) { case AUTO_COLUMN_SUB_TYPES.UPDATED_BY: case AUTO_COLUMN_SUB_TYPES.CREATED_BY: - type = FieldType.LINK - constraints = FIELDS.LINK.constraints - break + return { + ...base, + type: FieldType.LINK, + subtype, + constraints: FIELDS.LINK.constraints, + tableId: TableNames.USERS, + fieldName: `${tableName}-${name}`, + relationshipType: RelationshipType.MANY_TO_ONE, + } + case AUTO_COLUMN_SUB_TYPES.AUTO_ID: - type = FieldType.NUMBER - constraints = FIELDS.NUMBER.constraints - break + return { + ...base, + type: FieldType.NUMBER, + subtype, + constraints: FIELDS.NUMBER.constraints, + } case AUTO_COLUMN_SUB_TYPES.UPDATED_AT: case AUTO_COLUMN_SUB_TYPES.CREATED_AT: - type = FieldType.DATETIME - constraints = FIELDS.DATETIME.constraints - break + return { + ...base, + type: FieldType.DATETIME, + subtype, + constraints: FIELDS.DATETIME.constraints, + } + default: - type = FieldType.STRING - constraints = FIELDS.STRING.constraints - break + throw utils.unreachable(subtype, { + message: "Cannot build auto column with supplied subtype", + }) } - if (Object.values(AUTO_COLUMN_SUB_TYPES).indexOf(subtype) === -1) { - throw "Cannot build auto column with supplied subtype" - } - const base = { - name, - type, - subtype, - icon: "ri-magic-line", - autocolumn: true, - constraints, - } - if (isAutoColumnUserRelationship(subtype)) { - base.tableId = TableNames.USERS - base.fieldName = `${tableName}-${name}` - } - return base } export function checkForCollectStep(automation: Automation) { diff --git a/packages/types/src/documents/app/table/schema.ts b/packages/types/src/documents/app/table/schema.ts index 551b1f16a8..13eecec3a4 100644 --- a/packages/types/src/documents/app/table/schema.ts +++ b/packages/types/src/documents/app/table/schema.ts @@ -109,6 +109,7 @@ export interface LongFormFieldMetadata extends BaseFieldSchema { export interface StringFieldMetadata extends BaseFieldSchema { type: FieldType.STRING default?: string + subtype?: never } export interface FormulaFieldMetadata extends BaseFieldSchema { From bdd0d10d0d5af482ab7de2a5b1cf2fdc28c761c8 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 13 Jan 2025 14:07:54 +0100 Subject: [PATCH 10/29] Extra typings --- packages/builder/src/helpers/{planTitle.js => planTitle.ts} | 4 ++-- .../builder/src/helpers/{sanitizeUrl.js => sanitizeUrl.ts} | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename packages/builder/src/helpers/{planTitle.js => planTitle.ts} (86%) rename packages/builder/src/helpers/{sanitizeUrl.js => sanitizeUrl.ts} (88%) diff --git a/packages/builder/src/helpers/planTitle.js b/packages/builder/src/helpers/planTitle.ts similarity index 86% rename from packages/builder/src/helpers/planTitle.js rename to packages/builder/src/helpers/planTitle.ts index c08b8bf3fe..ab342b4d93 100644 --- a/packages/builder/src/helpers/planTitle.js +++ b/packages/builder/src/helpers/planTitle.ts @@ -1,6 +1,6 @@ import { PlanType } from "@budibase/types" -export function getFormattedPlanName(userPlanType) { +export function getFormattedPlanName(userPlanType: PlanType) { let planName switch (userPlanType) { case PlanType.PRO: @@ -29,6 +29,6 @@ export function getFormattedPlanName(userPlanType) { return `${planName} Plan` } -export function isPremiumOrAbove(userPlanType) { +export function isPremiumOrAbove(userPlanType: PlanType) { return ![PlanType.PRO, PlanType.TEAM, PlanType.FREE].includes(userPlanType) } diff --git a/packages/builder/src/helpers/sanitizeUrl.js b/packages/builder/src/helpers/sanitizeUrl.ts similarity index 88% rename from packages/builder/src/helpers/sanitizeUrl.js rename to packages/builder/src/helpers/sanitizeUrl.ts index 4d00c503fb..5b76930037 100644 --- a/packages/builder/src/helpers/sanitizeUrl.js +++ b/packages/builder/src/helpers/sanitizeUrl.ts @@ -1,4 +1,4 @@ -export default function (url) { +export default function (url: string) { return url .split("/") .map(part => { From b3d18b16cf5841b24452d3a5d0d8b97d412b59de Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 13 Jan 2025 14:11:39 +0100 Subject: [PATCH 11/29] Type pagination --- .../src/helpers/{pagination.js => pagination.ts} | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) rename packages/builder/src/helpers/{pagination.js => pagination.ts} (76%) diff --git a/packages/builder/src/helpers/pagination.js b/packages/builder/src/helpers/pagination.ts similarity index 76% rename from packages/builder/src/helpers/pagination.js rename to packages/builder/src/helpers/pagination.ts index 122973f1a1..0280cd1052 100644 --- a/packages/builder/src/helpers/pagination.js +++ b/packages/builder/src/helpers/pagination.ts @@ -1,6 +1,16 @@ import { writable } from "svelte/store" -function defaultValue() { +interface PaginationStore { + nextPage: string | null | undefined + page: string | null | undefined + hasPrevPage: boolean + hasNextPage: boolean + loading: boolean + pageNumber: number + pages: string[] +} + +function defaultValue(): PaginationStore { return { nextPage: null, page: undefined, @@ -29,13 +39,13 @@ export function createPaginationStore() { update(state => { state.pageNumber++ state.page = state.nextPage - state.pages.push(state.page) + state.pages.push(state.page!) state.hasPrevPage = state.pageNumber > 1 return state }) } - function fetched(hasNextPage, nextPage) { + function fetched(hasNextPage: boolean, nextPage: string) { update(state => { state.hasNextPage = hasNextPage state.nextPage = nextPage From 8f282d54d2830e268d80ae27a12b49da60d64553 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 13 Jan 2025 14:13:20 +0100 Subject: [PATCH 12/29] Type duplicates --- .../builder/src/helpers/{duplicate.js => duplicate.ts} | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) rename packages/builder/src/helpers/{duplicate.js => duplicate.ts} (92%) diff --git a/packages/builder/src/helpers/duplicate.js b/packages/builder/src/helpers/duplicate.ts similarity index 92% rename from packages/builder/src/helpers/duplicate.js rename to packages/builder/src/helpers/duplicate.ts index 361e1faa25..4816bcfd7b 100644 --- a/packages/builder/src/helpers/duplicate.js +++ b/packages/builder/src/helpers/duplicate.ts @@ -10,13 +10,13 @@ * * Repl */ -export const duplicateName = (name, allNames) => { +export const duplicateName = (name: string, allNames: string[]) => { const duplicatePattern = new RegExp(`\\s(\\d+)$`) const baseName = name.split(duplicatePattern)[0] const isDuplicate = new RegExp(`${baseName}\\s(\\d+)$`) // get the sequence from matched names - const sequence = [] + const sequence: number[] = [] allNames.filter(n => { if (n === baseName) { return true @@ -71,9 +71,9 @@ export const duplicateName = (name, allNames) => { * flat array of strings */ export const getSequentialName = ( - items, - prefix, - { getName = x => x, numberFirstItem = false } = {} + items: string[], + prefix: string, + { getName = (x: string) => x, numberFirstItem = false } = {} ) => { if (!prefix?.length || !getName) { return null From 2a853d3992c67e59ba00fbc3c083051080e4b2c1 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 13 Jan 2025 14:20:10 +0100 Subject: [PATCH 13/29] Type helpers --- packages/builder/src/helpers/helpers.js | 46 ----------------- packages/builder/src/helpers/helpers.ts | 50 +++++++++++++++++++ .../src/helpers/{index.js => index.ts} | 0 3 files changed, 50 insertions(+), 46 deletions(-) delete mode 100644 packages/builder/src/helpers/helpers.js create mode 100644 packages/builder/src/helpers/helpers.ts rename packages/builder/src/helpers/{index.js => index.ts} (100%) diff --git a/packages/builder/src/helpers/helpers.js b/packages/builder/src/helpers/helpers.js deleted file mode 100644 index 99483d40e2..0000000000 --- a/packages/builder/src/helpers/helpers.js +++ /dev/null @@ -1,46 +0,0 @@ -import { last, flow } from "lodash/fp" - -export const buildStyle = styles => { - let str = "" - for (let s in styles) { - if (styles[s]) { - let key = convertCamel(s) - str += `${key}: ${styles[s]}; ` - } - } - return str -} - -export const convertCamel = str => { - return str.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`) -} - -export const pipe = (arg, funcs) => flow(funcs)(arg) - -export const capitalise = s => { - if (!s) { - return s - } - return s.substring(0, 1).toUpperCase() + s.substring(1) -} - -export const lowercase = s => s.substring(0, 1).toLowerCase() + s.substring(1) - -export const lowercaseExceptFirst = s => - s.charAt(0) + s.substring(1).toLowerCase() - -export const get_name = s => (!s ? "" : last(s.split("/"))) - -export const get_capitalised_name = name => pipe(name, [get_name, capitalise]) - -export const isBuilderInputFocused = e => { - const activeTag = document.activeElement?.tagName.toLowerCase() - const inCodeEditor = document.activeElement?.classList?.contains("cm-content") - if ( - (inCodeEditor || ["input", "textarea"].indexOf(activeTag) !== -1) && - e.key !== "Escape" - ) { - return true - } - return false -} diff --git a/packages/builder/src/helpers/helpers.ts b/packages/builder/src/helpers/helpers.ts new file mode 100644 index 0000000000..f767e6f59f --- /dev/null +++ b/packages/builder/src/helpers/helpers.ts @@ -0,0 +1,50 @@ +import type { Many } from "lodash" +import { last, flow } from "lodash/fp" + +export const buildStyle = (styles: Record) => { + let str = "" + for (let s in styles) { + if (styles[s]) { + let key = convertCamel(s) + str += `${key}: ${styles[s]}; ` + } + } + return str +} + +export const convertCamel = (str: string) => { + return str.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`) +} + +export const pipe = (arg: string, funcs: Many<(...args: any[]) => any>) => + flow(funcs)(arg) + +export const capitalise = (s: string) => { + if (!s) { + return s + } + return s.substring(0, 1).toUpperCase() + s.substring(1) +} + +export const lowercase = (s: string) => + s.substring(0, 1).toLowerCase() + s.substring(1) + +export const lowercaseExceptFirst = (s: string) => + s.charAt(0) + s.substring(1).toLowerCase() + +export const get_name = (s: string) => (!s ? "" : last(s.split("/"))) + +export const get_capitalised_name = (name: string) => + pipe(name, [get_name, capitalise]) + +export const isBuilderInputFocused = (e: KeyboardEvent) => { + const activeTag = document.activeElement?.tagName.toLowerCase() + const inCodeEditor = document.activeElement?.classList?.contains("cm-content") + if ( + (inCodeEditor || ["input", "textarea"].indexOf(activeTag!) !== -1) && + e.key !== "Escape" + ) { + return true + } + return false +} diff --git a/packages/builder/src/helpers/index.js b/packages/builder/src/helpers/index.ts similarity index 100% rename from packages/builder/src/helpers/index.js rename to packages/builder/src/helpers/index.ts From a8d7a97bd678d73621d65e2fd9c69082d7ea52a7 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 13 Jan 2025 17:08:37 +0100 Subject: [PATCH 14/29] Type warnings --- packages/builder/src/helpers/{warnings.js => warnings.ts} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename packages/builder/src/helpers/{warnings.js => warnings.ts} (85%) diff --git a/packages/builder/src/helpers/warnings.js b/packages/builder/src/helpers/warnings.ts similarity index 85% rename from packages/builder/src/helpers/warnings.js rename to packages/builder/src/helpers/warnings.ts index ad943a8578..ae6c65666c 100644 --- a/packages/builder/src/helpers/warnings.js +++ b/packages/builder/src/helpers/warnings.ts @@ -1,4 +1,4 @@ -export const suppressWarnings = warnings => { +export const suppressWarnings = (warnings: string[]) => { if (!warnings?.length) { return } From d912e95849295e03e4b363423e792cc9b42eb580 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 13 Jan 2025 17:10:40 +0100 Subject: [PATCH 15/29] Type fetchData --- .../src/helpers/{fetchData.js => fetchData.ts} | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) rename packages/builder/src/helpers/{fetchData.js => fetchData.ts} (57%) diff --git a/packages/builder/src/helpers/fetchData.js b/packages/builder/src/helpers/fetchData.ts similarity index 57% rename from packages/builder/src/helpers/fetchData.js rename to packages/builder/src/helpers/fetchData.ts index 085d0ae5b4..22b82c070e 100644 --- a/packages/builder/src/helpers/fetchData.js +++ b/packages/builder/src/helpers/fetchData.ts @@ -1,13 +1,21 @@ import { writable } from "svelte/store" import { API } from "@/api" -export default function (url) { - const store = writable({ status: "LOADING", data: {}, error: {} }) +export default function (url: string) { + const store = writable<{ + status: "LOADING" | "SUCCESS" | "ERROR" + data: object + error?: unknown + }>({ + status: "LOADING", + data: {}, + error: {}, + }) async function get() { store.update(u => ({ ...u, status: "LOADING" })) try { - const data = await API.get({ url }) + const data = await API.get({ url }) store.set({ data, status: "SUCCESS" }) } catch (e) { store.set({ data: {}, error: e, status: "ERROR" }) From 2558bd3e6ad2e71bb355ac1c97c2dbc25287a6c2 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 13 Jan 2025 17:12:20 +0100 Subject: [PATCH 16/29] Type feature flags --- .../builder/src/helpers/{featureFlags.js => featureFlags.ts} | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) rename packages/builder/src/helpers/{featureFlags.js => featureFlags.ts} (58%) diff --git a/packages/builder/src/helpers/featureFlags.js b/packages/builder/src/helpers/featureFlags.ts similarity index 58% rename from packages/builder/src/helpers/featureFlags.js rename to packages/builder/src/helpers/featureFlags.ts index e9054e8a9c..625468f06b 100644 --- a/packages/builder/src/helpers/featureFlags.js +++ b/packages/builder/src/helpers/featureFlags.ts @@ -1,7 +1,8 @@ +import { FeatureFlag } from "@budibase/types" import { auth } from "../stores/portal" import { get } from "svelte/store" -export const isEnabled = featureFlag => { +export const isEnabled = (featureFlag: FeatureFlag) => { const user = get(auth).user return !!user?.flags?.[featureFlag] } From 8281ec4e3ee5f47293e3cba7c49c01a2178b0d5c Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 13 Jan 2025 17:13:50 +0100 Subject: [PATCH 17/29] Allow feature flags as strings --- packages/builder/src/helpers/featureFlags.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/helpers/featureFlags.ts b/packages/builder/src/helpers/featureFlags.ts index 625468f06b..faa57892e8 100644 --- a/packages/builder/src/helpers/featureFlags.ts +++ b/packages/builder/src/helpers/featureFlags.ts @@ -2,7 +2,7 @@ import { FeatureFlag } from "@budibase/types" import { auth } from "../stores/portal" import { get } from "svelte/store" -export const isEnabled = (featureFlag: FeatureFlag) => { +export const isEnabled = (featureFlag: FeatureFlag | `${FeatureFlag}`) => { const user = get(auth).user return !!user?.flags?.[featureFlag] } From ca1015baf6b6bc5942c7a5cbd0caf4cd499665ee Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 14 Jan 2025 10:07:50 +0100 Subject: [PATCH 18/29] Remove unexpected never field --- packages/types/src/documents/app/table/schema.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/types/src/documents/app/table/schema.ts b/packages/types/src/documents/app/table/schema.ts index 13eecec3a4..551b1f16a8 100644 --- a/packages/types/src/documents/app/table/schema.ts +++ b/packages/types/src/documents/app/table/schema.ts @@ -109,7 +109,6 @@ export interface LongFormFieldMetadata extends BaseFieldSchema { export interface StringFieldMetadata extends BaseFieldSchema { type: FieldType.STRING default?: string - subtype?: never } export interface FormulaFieldMetadata extends BaseFieldSchema { From 41c8ab976fd4c30661b4e75927c5bdbe4ec7a74e Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 14 Jan 2025 10:09:10 +0100 Subject: [PATCH 19/29] Type --- packages/builder/src/helpers/fetchData.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/helpers/fetchData.ts b/packages/builder/src/helpers/fetchData.ts index 22b82c070e..cffb8f4d7d 100644 --- a/packages/builder/src/helpers/fetchData.ts +++ b/packages/builder/src/helpers/fetchData.ts @@ -15,7 +15,7 @@ export default function (url: string) { async function get() { store.update(u => ({ ...u, status: "LOADING" })) try { - const data = await API.get({ url }) + const data = await API.get({ url }) store.set({ data, status: "SUCCESS" }) } catch (e) { store.set({ data: {}, error: e, status: "ERROR" }) From 8624997f4c371fb853159605a5fc81a4289baa99 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 14 Jan 2025 11:14:30 +0100 Subject: [PATCH 20/29] Fix types --- packages/builder/src/helpers/duplicate.ts | 12 +++++++++--- packages/builder/src/stores/builder/rowActions.ts | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/builder/src/helpers/duplicate.ts b/packages/builder/src/helpers/duplicate.ts index 4816bcfd7b..35beb4df38 100644 --- a/packages/builder/src/helpers/duplicate.ts +++ b/packages/builder/src/helpers/duplicate.ts @@ -70,10 +70,16 @@ export const duplicateName = (name: string, allNames: string[]) => { * @param getName optional function to extract the name for an item, if not a * flat array of strings */ -export const getSequentialName = ( - items: string[], +export const getSequentialName = ( + items: T[], prefix: string, - { getName = (x: string) => x, numberFirstItem = false } = {} + { + getName, + numberFirstItem, + }: { + getName: (item: T) => string + numberFirstItem?: boolean + } ) => { if (!prefix?.length || !getName) { return null diff --git a/packages/builder/src/stores/builder/rowActions.ts b/packages/builder/src/stores/builder/rowActions.ts index 9576eccd1b..2b3077926e 100644 --- a/packages/builder/src/stores/builder/rowActions.ts +++ b/packages/builder/src/stores/builder/rowActions.ts @@ -62,7 +62,7 @@ export class RowActionStore extends BudiStore { const existingRowActions = get(this)[tableId] || [] name = getSequentialName(existingRowActions, "New row action ", { getName: x => x.name, - }) + })! } if (!name) { From 06013929e44cd822cc19c146f944303fa2a36e90 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 14 Jan 2025 11:14:34 +0100 Subject: [PATCH 21/29] Fix usage --- .../src/components/common/bindings/SnippetDrawer.svelte | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/builder/src/components/common/bindings/SnippetDrawer.svelte b/packages/builder/src/components/common/bindings/SnippetDrawer.svelte index 90ca6ffd9f..f10c44f81f 100644 --- a/packages/builder/src/components/common/bindings/SnippetDrawer.svelte +++ b/packages/builder/src/components/common/bindings/SnippetDrawer.svelte @@ -28,7 +28,9 @@ let loading = false let deleteConfirmationDialog - $: defaultName = getSequentialName($snippets, "MySnippet", x => x.name) + $: defaultName = getSequentialName($snippets, "MySnippet", { + getName: x => x.name, + }) $: key = snippet?.name $: name = snippet?.name || defaultName $: code = snippet?.code ? encodeJSBinding(snippet.code) : "" From 35d5e51898a94054284239b5e061557dfdc8c9b9 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 14 Jan 2025 11:35:43 +0100 Subject: [PATCH 22/29] Convert and fix tests --- packages/builder/src/helpers/duplicate.ts | 14 +++++++------- .../tests/{duplicate.test.js => duplicate.test.ts} | 0 2 files changed, 7 insertions(+), 7 deletions(-) rename packages/builder/src/helpers/tests/{duplicate.test.js => duplicate.test.ts} (100%) diff --git a/packages/builder/src/helpers/duplicate.ts b/packages/builder/src/helpers/duplicate.ts index 35beb4df38..b4740b3e52 100644 --- a/packages/builder/src/helpers/duplicate.ts +++ b/packages/builder/src/helpers/duplicate.ts @@ -70,18 +70,18 @@ export const duplicateName = (name: string, allNames: string[]) => { * @param getName optional function to extract the name for an item, if not a * flat array of strings */ -export const getSequentialName = ( - items: T[], - prefix: string, +export const getSequentialName = ( + items: T[] | null, + prefix: string | null, { getName, numberFirstItem, }: { - getName: (item: T) => string + getName?: (item: T) => string numberFirstItem?: boolean - } + } = {} ) => { - if (!prefix?.length || !getName) { + if (!prefix?.length) { return null } const trimmedPrefix = prefix.trim() @@ -91,7 +91,7 @@ export const getSequentialName = ( } let max = 0 items.forEach(item => { - const name = getName(item) + const name = getName?.(item) ?? item if (typeof name !== "string" || !name.startsWith(trimmedPrefix)) { return } diff --git a/packages/builder/src/helpers/tests/duplicate.test.js b/packages/builder/src/helpers/tests/duplicate.test.ts similarity index 100% rename from packages/builder/src/helpers/tests/duplicate.test.js rename to packages/builder/src/helpers/tests/duplicate.test.ts From 0665ff1307a95d6e5b5dd0c50a4b3ab13f206771 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 14 Jan 2025 11:37:14 +0100 Subject: [PATCH 23/29] Convert test --- .../helpers/tests/{nameHelpers.spec.js => nameHelpers.spec.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/builder/src/helpers/tests/{nameHelpers.spec.js => nameHelpers.spec.ts} (100%) diff --git a/packages/builder/src/helpers/tests/nameHelpers.spec.js b/packages/builder/src/helpers/tests/nameHelpers.spec.ts similarity index 100% rename from packages/builder/src/helpers/tests/nameHelpers.spec.js rename to packages/builder/src/helpers/tests/nameHelpers.spec.ts From a3bcaddabbca7d02f5ba306b9b98ebf34e61dfa9 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 14 Jan 2025 16:05:14 +0100 Subject: [PATCH 24/29] Re-add tests files in backend-core/dist --- packages/backend-core/package.json | 2 +- packages/backend-core/tsconfig.test.json | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 packages/backend-core/tsconfig.test.json diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index 3e1b5f324b..1ab05cd14b 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -21,7 +21,7 @@ "scripts": { "prebuild": "rimraf dist/", "prepack": "cp package.json dist", - "build": "node ./scripts/build.js && tsc -p tsconfig.build.json --emitDeclarationOnly --paths null", + "build": "node ./scripts/build.js && tsc -p tsconfig.build.json --emitDeclarationOnly --paths null && tsc -p tsconfig.test.json --paths null", "build:dev": "yarn prebuild && tsc --build --watch --preserveWatchOutput", "build:oss": "node ./scripts/build.js", "check:types": "tsc -p tsconfig.json --noEmit --paths null", diff --git a/packages/backend-core/tsconfig.test.json b/packages/backend-core/tsconfig.test.json new file mode 100644 index 0000000000..48322b7a94 --- /dev/null +++ b/packages/backend-core/tsconfig.test.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.build.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": ["tests/**/*.js", "tests/**/*.ts"], + "exclude": ["node_modules", "dist"] +} From bc1e95b012aa357fa646ccecffd1bb65cc0624fb Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 14 Jan 2025 16:15:24 +0100 Subject: [PATCH 25/29] Add sourcemap --- packages/backend-core/tsconfig.test.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/backend-core/tsconfig.test.json b/packages/backend-core/tsconfig.test.json index 48322b7a94..0e3e7a79b2 100644 --- a/packages/backend-core/tsconfig.test.json +++ b/packages/backend-core/tsconfig.test.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig.build.json", "compilerOptions": { - "outDir": "dist" + "outDir": "dist", + "sourceMap": true }, "include": ["tests/**/*.js", "tests/**/*.ts"], "exclude": ["node_modules", "dist"] From 3715bd0bed58432a13657126e69b222df6762a86 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 14 Jan 2025 16:51:31 +0100 Subject: [PATCH 26/29] Update pro submodule --- packages/pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pro b/packages/pro index 193476cdfa..19295c7e4d 160000 --- a/packages/pro +++ b/packages/pro @@ -1 +1 @@ -Subproject commit 193476cdfade6d3c613e6972f16ee0c527e01ff6 +Subproject commit 19295c7e4d223bec493a108a905c110d5f024258 From 2acbf29e625f60452adb3a8f2f696b05641f1939 Mon Sep 17 00:00:00 2001 From: Budibase Staging Release Bot <> Date: Tue, 14 Jan 2025 16:20:54 +0000 Subject: [PATCH 27/29] Bump version to 3.2.42 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index e8cd581c98..d0f0bd23c5 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", - "version": "3.2.41", + "version": "3.2.42", "npmClient": "yarn", "concurrency": 20, "command": { From ccf3e787011ff11838f48fa9b569d50345b2d5cf Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 14 Jan 2025 23:35:18 +0100 Subject: [PATCH 28/29] Update pro submodule --- packages/pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pro b/packages/pro index 19295c7e4d..a4f63b2267 160000 --- a/packages/pro +++ b/packages/pro @@ -1 +1 @@ -Subproject commit 19295c7e4d223bec493a108a905c110d5f024258 +Subproject commit a4f63b22675e16dcdcaa4d9e83b298eee6466a07 From 4c1013e4d37c070eeb8ffb2b71fbd03f81b2c79d Mon Sep 17 00:00:00 2001 From: Budibase Staging Release Bot <> Date: Wed, 15 Jan 2025 09:04:44 +0000 Subject: [PATCH 29/29] Bump version to 3.2.43 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index d0f0bd23c5..1aa1705d19 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.43", "npmClient": "yarn", "concurrency": 20, "command": {