From f8f9c4da8efc6ec94e1dd52fe525fd9cbfdeb7af Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 25 Oct 2024 17:32:42 +0100 Subject: [PATCH 01/88] Work in progress - this is the scaffolding for views to be added to the public API. --- packages/server/specs/resources/view.ts | 193 ++++++++++++++++++ .../src/api/controllers/public/views.ts | 56 +++++ .../server/src/api/routes/public/views.ts | 165 +++++++++++++++ .../server/src/api/routes/utils/validators.ts | 4 + 4 files changed, 418 insertions(+) create mode 100644 packages/server/specs/resources/view.ts create mode 100644 packages/server/src/api/controllers/public/views.ts create mode 100644 packages/server/src/api/routes/public/views.ts diff --git a/packages/server/specs/resources/view.ts b/packages/server/specs/resources/view.ts new file mode 100644 index 0000000000..6458af15fc --- /dev/null +++ b/packages/server/specs/resources/view.ts @@ -0,0 +1,193 @@ +import { FieldType, FormulaType, RelationshipType } from "@budibase/types" +import { object } from "./utils" +import Resource from "./utils/Resource" + +const view = { + _id: "ta_5b1649e42a5b41dea4ef7742a36a7a70", + name: "People", + schema: { + name: { + type: "string", + name: "name", + }, + age: { + type: "number", + name: "age", + }, + relationship: { + type: "link", + name: "relationship", + tableId: "ta_...", + fieldName: "relatedColumn", + relationshipType: "many-to-many", + }, + }, +} + +const baseColumnDef = { + type: { + type: "string", + enum: Object.values(FieldType), + description: + "Defines the type of the column, most explain themselves, a link column is a relationship.", + }, + constraints: { + type: "object", + description: + "A constraint can be applied to the column which will be validated against when a row is saved.", + properties: { + type: { + type: "string", + enum: ["string", "number", "object", "boolean"], + }, + presence: { + type: "boolean", + description: "Defines whether the column is required or not.", + }, + }, + }, + name: { + type: "string", + description: "The name of the column.", + }, + autocolumn: { + type: "boolean", + description: "Defines whether the column is automatically generated.", + }, +} + +const viewSchema = { + description: "The table to be created/updated.", + type: "object", + required: ["name", "schema"], + properties: { + name: { + description: "The name of the table.", + type: "string", + }, + primaryDisplay: { + type: "string", + description: + "The name of the column which should be used in relationship tags when relating to this table.", + }, + schema: { + type: "object", + additionalProperties: { + oneOf: [ + // relationship + { + type: "object", + properties: { + ...baseColumnDef, + type: { + type: "string", + enum: [FieldType.LINK], + description: "A relationship column.", + }, + fieldName: { + type: "string", + description: + "The name of the column which a relationship column is related to in another table.", + }, + tableId: { + type: "string", + description: + "The ID of the table which a relationship column is related to.", + }, + relationshipType: { + type: "string", + enum: Object.values(RelationshipType), + description: + "Defines the type of relationship that this column will be used for.", + }, + through: { + type: "string", + description: + "When using a SQL table that contains many to many relationships this defines the table the relationships are linked through.", + }, + foreignKey: { + type: "string", + description: + "When using a SQL table that contains a one to many relationship this defines the foreign key.", + }, + throughFrom: { + type: "string", + description: + "When using a SQL table that utilises a through table, this defines the primary key in the through table for this table.", + }, + throughTo: { + type: "string", + description: + "When using a SQL table that utilises a through table, this defines the primary key in the through table for the related table.", + }, + }, + }, + { + type: "object", + properties: { + ...baseColumnDef, + type: { + type: "string", + enum: [FieldType.FORMULA], + description: "A formula column.", + }, + formula: { + type: "string", + description: + "Defines a Handlebars or JavaScript formula to use, note that Javascript formulas are expected to be provided in the base64 format.", + }, + formulaType: { + type: "string", + enum: Object.values(FormulaType), + description: + "Defines whether this is a static or dynamic formula.", + }, + }, + }, + { + type: "object", + properties: baseColumnDef, + }, + ], + }, + }, + }, +} + +const viewOutputSchema = { + ...viewSchema, + properties: { + ...viewSchema.properties, + _id: { + description: "The ID of the view.", + type: "string", + }, + }, + required: [...viewSchema.required, "_id"], +} + +export default new Resource() + .setExamples({ + view: { + value: { + data: view, + }, + }, + views: { + value: { + data: [view], + }, + }, + }) + .setSchemas({ + view: viewSchema, + viewOutput: object({ + data: viewOutputSchema, + }), + viewSearch: object({ + data: { + type: "array", + items: viewOutputSchema, + }, + }), + }) diff --git a/packages/server/src/api/controllers/public/views.ts b/packages/server/src/api/controllers/public/views.ts new file mode 100644 index 0000000000..11fb4cc344 --- /dev/null +++ b/packages/server/src/api/controllers/public/views.ts @@ -0,0 +1,56 @@ +import { search as stringSearch } from "./utils" +import * as controller from "../view" +import { ViewV2, UserCtx } from "@budibase/types" +import { Next } from "koa" + +function fixView(view: ViewV2, params: any) { + if (!params || !view) { + return view + } + if (params.viewId) { + view.id = params.viewId + } + return view +} + +export async function search(ctx: UserCtx, next: Next) { + const { name } = ctx.request.body + // TODO: need a view search endpoint + // await controller.v2.fetch(ctx) + ctx.body = stringSearch(ctx.body, name) + await next() +} + +export async function create(ctx: UserCtx, next: Next) { + await controller.v2.create(ctx) + await next() +} + +export async function read(ctx: UserCtx, next: Next) { + await controller.v2.get(ctx) + await next() +} + +export async function update(ctx: UserCtx, next: Next) { + // TODO: this is more complex - no rev on views + // ctx.request.body = await addRev( + // fixView(ctx.request.body, ctx.params), + // ctx.params.tableId + // ) + await controller.v2.update(ctx) + await next() +} + +export async function destroy(ctx: UserCtx, next: Next) { + await controller.v2.remove(ctx) + ctx.body = ctx.table + await next() +} + +export default { + create, + read, + update, + destroy, + search, +} diff --git a/packages/server/src/api/routes/public/views.ts b/packages/server/src/api/routes/public/views.ts new file mode 100644 index 0000000000..7c182d105f --- /dev/null +++ b/packages/server/src/api/routes/public/views.ts @@ -0,0 +1,165 @@ +import controller from "../../controllers/public/views" +import Endpoint from "./utils/Endpoint" +import { viewValidator, nameValidator } from "../utils/validators" + +const read = [], + write = [] + +/** + * @openapi + * /views: + * post: + * operationId: viewCreate + * summary: Create a view + * description: Create a view, this can be against an internal or external table. + * tags: + * - views + * parameters: + * - $ref: '#/components/parameters/appId' + * requestBody: + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/view' + * examples: + * view: + * $ref: '#/components/examples/view' + * responses: + * 200: + * description: Returns the created view, including the ID which has been generated for it. + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/viewOutput' + * examples: + * view: + * $ref: '#/components/examples/view' + */ +write.push( + new Endpoint("post", "/views", controller.create).addMiddleware( + viewValidator() + ) +) + +/** + * @openapi + * /views/{viewId}: + * put: + * operationId: viewUpdate + * summary: Update a view + * description: Update a view, this can be against an internal or external table. + * tags: + * - views + * parameters: + * - $ref: '#/components/parameters/viewId' + * - $ref: '#/components/parameters/appId' + * requestBody: + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/view' + * examples: + * view: + * $ref: '#/components/examples/view' + * responses: + * 200: + * description: Returns the updated view. + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/viewOutput' + * examples: + * view: + * $ref: '#/components/examples/view' + */ +write.push( + new Endpoint("put", "/views/:viewId", controller.update).addMiddleware( + viewValidator() + ) +) + +/** + * @openapi + * /views/{viewId}: + * delete: + * operationId: viewDestroy + * summary: Delete a view + * description: Delete a view, this can be against an internal or external table. + * tags: + * - views + * parameters: + * - $ref: '#/components/parameters/viewId' + * - $ref: '#/components/parameters/appId' + * responses: + * 200: + * description: Returns the deleted view. + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/viewOutput' + * examples: + * view: + * $ref: '#/components/examples/view' + */ +write.push(new Endpoint("delete", "/views/:viewId", controller.destroy)) + +/** + * @openapi + * /views/{viewId}: + * get: + * operationId: viewGetById + * summary: Retrieve a view + * description: Lookup a view, this could be internal or external. + * tags: + * - views + * parameters: + * - $ref: '#/components/parameters/viewId' + * - $ref: '#/components/parameters/appId' + * responses: + * 200: + * description: Returns the retrieved view. + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/viewOutput' + * examples: + * view: + * $ref: '#/components/examples/view' + */ +read.push(new Endpoint("get", "/views/:viewId", controller.read)) + +/** + * @openapi + * /views/search: + * post: + * operationId: viewSearch + * summary: Search for views + * description: Based on view properties (currently only name) search for views. + * tags: + * - views + * parameters: + * - $ref: '#/components/parameters/appId' + * requestBody: + * required: true + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/viewSearch' + * responses: + * 200: + * description: Returns the found views, based on the search parameters. + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/viewSearch' + * examples: + * views: + * $ref: '#/components/examples/views' + */ +read.push( + new Endpoint("post", "/views/search", controller.search).addMiddleware( + nameValidator() + ) +) + +export default { read, write } diff --git a/packages/server/src/api/routes/utils/validators.ts b/packages/server/src/api/routes/utils/validators.ts index 862d8c30c5..68ebd72c5e 100644 --- a/packages/server/src/api/routes/utils/validators.ts +++ b/packages/server/src/api/routes/utils/validators.ts @@ -66,6 +66,10 @@ export function tableValidator() { ) } +export function viewValidator() { + return auth.joiValidator.body(Joi.object()) +} + export function nameValidator() { return auth.joiValidator.body( Joi.object({ From eeb78b2c4578e1a6a1b181e7e1377af8b38e47ff Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 25 Oct 2024 17:51:52 +0100 Subject: [PATCH 02/88] Getting schemas correct for views. --- packages/server/specs/resources/view.ts | 160 +++++------------- .../src/api/controllers/public/views.ts | 8 +- 2 files changed, 45 insertions(+), 123 deletions(-) diff --git a/packages/server/specs/resources/view.ts b/packages/server/specs/resources/view.ts index 6458af15fc..5afdf78a0e 100644 --- a/packages/server/specs/resources/view.ts +++ b/packages/server/specs/resources/view.ts @@ -1,154 +1,72 @@ -import { FieldType, FormulaType, RelationshipType } from "@budibase/types" import { object } from "./utils" import Resource from "./utils/Resource" const view = { - _id: "ta_5b1649e42a5b41dea4ef7742a36a7a70", - name: "People", + name: "peopleView", + tableId: "ta_896a325f7e8147d2a2cda93c5d236511", schema: { name: { - type: "string", - name: "name", + visible: true, + readonly: false, + order: 1, + width: 300, }, age: { - type: "number", - name: "age", + visible: true, + readonly: true, + order: 2, + width: 200, }, - relationship: { - type: "link", - name: "relationship", - tableId: "ta_...", - fieldName: "relatedColumn", - relationshipType: "many-to-many", + salary: { + visible: false, + readonly: false, }, }, + primaryDisplay: "name", } const baseColumnDef = { - type: { - type: "string", - enum: Object.values(FieldType), - description: - "Defines the type of the column, most explain themselves, a link column is a relationship.", - }, - constraints: { - type: "object", - description: - "A constraint can be applied to the column which will be validated against when a row is saved.", - properties: { - type: { - type: "string", - enum: ["string", "number", "object", "boolean"], - }, - presence: { - type: "boolean", - description: "Defines whether the column is required or not.", - }, - }, - }, - name: { - type: "string", - description: "The name of the column.", - }, - autocolumn: { + visible: { type: "boolean", - description: "Defines whether the column is automatically generated.", + description: + "Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it.", + }, + readonly: { + type: "boolean", + description: + "When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated.", + }, + order: { + type: "integer", + description: + "A number defining where the column shows up in tables, lowest being first.", + }, + width: { + type: "integer", + description: + "A width for the column, defined in pixels - this affects rendering in tables.", }, } const viewSchema = { - description: "The table to be created/updated.", + description: "The view to be created/updated.", type: "object", required: ["name", "schema"], properties: { name: { - description: "The name of the table.", + description: "The name of the view.", type: "string", }, primaryDisplay: { type: "string", description: - "The name of the column which should be used in relationship tags when relating to this table.", + "A column used to display rows from this view - usually used when rendered in tables.", }, schema: { type: "object", additionalProperties: { - oneOf: [ - // relationship - { - type: "object", - properties: { - ...baseColumnDef, - type: { - type: "string", - enum: [FieldType.LINK], - description: "A relationship column.", - }, - fieldName: { - type: "string", - description: - "The name of the column which a relationship column is related to in another table.", - }, - tableId: { - type: "string", - description: - "The ID of the table which a relationship column is related to.", - }, - relationshipType: { - type: "string", - enum: Object.values(RelationshipType), - description: - "Defines the type of relationship that this column will be used for.", - }, - through: { - type: "string", - description: - "When using a SQL table that contains many to many relationships this defines the table the relationships are linked through.", - }, - foreignKey: { - type: "string", - description: - "When using a SQL table that contains a one to many relationship this defines the foreign key.", - }, - throughFrom: { - type: "string", - description: - "When using a SQL table that utilises a through table, this defines the primary key in the through table for this table.", - }, - throughTo: { - type: "string", - description: - "When using a SQL table that utilises a through table, this defines the primary key in the through table for the related table.", - }, - }, - }, - { - type: "object", - properties: { - ...baseColumnDef, - type: { - type: "string", - enum: [FieldType.FORMULA], - description: "A formula column.", - }, - formula: { - type: "string", - description: - "Defines a Handlebars or JavaScript formula to use, note that Javascript formulas are expected to be provided in the base64 format.", - }, - formulaType: { - type: "string", - enum: Object.values(FormulaType), - description: - "Defines whether this is a static or dynamic formula.", - }, - }, - }, - { - type: "object", - properties: baseColumnDef, - }, - ], + type: "object", + properties: baseColumnDef, }, }, }, @@ -158,12 +76,12 @@ const viewOutputSchema = { ...viewSchema, properties: { ...viewSchema.properties, - _id: { + id: { description: "The ID of the view.", type: "string", }, }, - required: [...viewSchema.required, "_id"], + required: [...viewSchema.required, "id"], } export default new Resource() diff --git a/packages/server/src/api/controllers/public/views.ts b/packages/server/src/api/controllers/public/views.ts index 11fb4cc344..85979126ff 100644 --- a/packages/server/src/api/controllers/public/views.ts +++ b/packages/server/src/api/controllers/public/views.ts @@ -3,13 +3,16 @@ import * as controller from "../view" import { ViewV2, UserCtx } from "@budibase/types" import { Next } from "koa" -function fixView(view: ViewV2, params: any) { +function fixView(view: ViewV2, params?: { viewId: string }) { if (!params || !view) { return view } - if (params.viewId) { + if (params?.viewId) { view.id = params.viewId } + if (!view.version) { + view.version = 2 + } return view } @@ -22,6 +25,7 @@ export async function search(ctx: UserCtx, next: Next) { } export async function create(ctx: UserCtx, next: Next) { + ctx.body = fixView(ctx.body) await controller.v2.create(ctx) await next() } From c055e2ae729943f10cb697fe51c41e32bf89e457 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 28 Oct 2024 18:09:04 +0000 Subject: [PATCH 03/88] Adding fetch endpoint for views (will be used by search for views in Public API). --- .../src/api/controllers/view/viewsV2.ts | 7 +++++ packages/server/src/api/routes/view.ts | 5 ++++ packages/server/src/sdk/app/views/index.ts | 29 +++++++++++++++++-- packages/types/src/api/web/app/view.ts | 4 +++ 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/packages/server/src/api/controllers/view/viewsV2.ts b/packages/server/src/api/controllers/view/viewsV2.ts index f864df9e9e..6f92e7399c 100644 --- a/packages/server/src/api/controllers/view/viewsV2.ts +++ b/packages/server/src/api/controllers/view/viewsV2.ts @@ -12,6 +12,7 @@ import { RelationSchemaField, ViewFieldMetadata, CalculationType, + ViewFetchResponseEnriched, } from "@budibase/types" import { builderSocket, gridSocket } from "../../../websockets" import { helpers } from "@budibase/shared-core" @@ -119,6 +120,12 @@ export async function get(ctx: Ctx) { } } +export async function fetch(ctx: Ctx) { + ctx.body = { + data: await sdk.views.getAllEnriched(), + } +} + export async function create(ctx: Ctx) { const view = ctx.request.body const { tableId } = view diff --git a/packages/server/src/api/routes/view.ts b/packages/server/src/api/routes/view.ts index 807d8e2f28..92e5f02a18 100644 --- a/packages/server/src/api/routes/view.ts +++ b/packages/server/src/api/routes/view.ts @@ -8,6 +8,11 @@ import { permissions } from "@budibase/backend-core" const router: Router = new Router() router + .get( + "/api/v2/views", + authorized(permissions.BUILDER), + viewController.v2.fetch + ) .get( "/api/v2/views/:viewId", authorizedResource( diff --git a/packages/server/src/sdk/app/views/index.ts b/packages/server/src/sdk/app/views/index.ts index cbf3513dd0..fc2341722f 100644 --- a/packages/server/src/sdk/app/views/index.ts +++ b/packages/server/src/sdk/app/views/index.ts @@ -27,6 +27,7 @@ import { isExternalTableID } from "../../../integrations/utils" import * as internal from "./internal" import * as external from "./external" import sdk from "../../../sdk" +import { ensureQueryUISet } from "./utils" function pickApi(tableId: any) { if (isExternalTableID(tableId)) { @@ -45,6 +46,24 @@ export async function getEnriched(viewId: string): Promise { return pickApi(tableId).getEnriched(viewId) } +export async function getAllEnriched(): Promise { + const tables = await sdk.tables.getAllTables() + let views: ViewV2Enriched[] = [] + for (let table of tables) { + if (!table.views || Object.keys(table.views).length === 0) { + continue + } + const v2Views = Object.values(table.views).filter(isV2) + const enrichedViews = await Promise.all( + v2Views.map(view => + enrichSchema(ensureQueryUISet(view), table.schema, tables) + ) + ) + views = views.concat(enrichedViews) + } + return views +} + export async function getTable(view: string | ViewV2): Promise { const viewId = typeof view === "string" ? view : view.id const cached = context.getTableForView(viewId) @@ -303,13 +322,19 @@ export function allowedFields( export async function enrichSchema( view: ViewV2, - tableSchema: TableSchema + tableSchema: TableSchema, + tables?: Table[] ): Promise { async function populateRelTableSchema( tableId: string, viewFields: Record ) { - const relTable = await sdk.tables.getTable(tableId) + let relTable = tables + ? tables?.find(t => t._id === tableId) + : await sdk.tables.getTable(tableId) + if (!relTable) { + throw new Error("Cannot enrich relationship, table not found") + } const result: Record = {} for (const relTableFieldName of Object.keys(relTable.schema)) { const relTableField = relTable.schema[relTableFieldName] diff --git a/packages/types/src/api/web/app/view.ts b/packages/types/src/api/web/app/view.ts index a6be5e2986..2560f7507f 100644 --- a/packages/types/src/api/web/app/view.ts +++ b/packages/types/src/api/web/app/view.ts @@ -9,6 +9,10 @@ export interface ViewResponseEnriched { data: ViewV2Enriched } +export interface ViewFetchResponseEnriched { + data: ViewV2Enriched[] +} + export interface CreateViewRequest extends Omit {} export interface UpdateViewRequest extends ViewV2 {} From 06984548556d00993aba791271c9f4a7e6dce5b0 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 28 Oct 2024 18:09:22 +0000 Subject: [PATCH 04/88] Fixing an issue with getAllExternalTables getter also returning internal tables. --- packages/server/src/sdk/app/tables/getters.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/server/src/sdk/app/tables/getters.ts b/packages/server/src/sdk/app/tables/getters.ts index a8ad606647..ebf7b3547b 100644 --- a/packages/server/src/sdk/app/tables/getters.ts +++ b/packages/server/src/sdk/app/tables/getters.ts @@ -82,8 +82,11 @@ export async function getAllInternalTables(db?: Database): Promise { } async function getAllExternalTables(): Promise { + // this is all datasources, we'll need to filter out internal const datasources = await sdk.datasources.fetch({ enriched: true }) - const allEntities = datasources.map(datasource => datasource.entities) + const allEntities = datasources + .filter(datasource => datasource._id !== INTERNAL_TABLE_SOURCE_ID) + .map(datasource => datasource.entities) let final: Table[] = [] for (let entities of allEntities) { if (entities) { From 68a7f88db667ad30dfa0998dae4c0b62a049589e Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 28 Oct 2024 18:09:38 +0000 Subject: [PATCH 05/88] Adding test case for fetch. --- .../src/api/routes/tests/viewV2.spec.ts | 32 +++++++++++++++++++ .../server/src/tests/utilities/api/viewV2.ts | 7 ++++ 2 files changed, 39 insertions(+) diff --git a/packages/server/src/api/routes/tests/viewV2.spec.ts b/packages/server/src/api/routes/tests/viewV2.spec.ts index 2af11b513b..b344e50bb4 100644 --- a/packages/server/src/api/routes/tests/viewV2.spec.ts +++ b/packages/server/src/api/routes/tests/viewV2.spec.ts @@ -2592,6 +2592,38 @@ describe.each([ }) }) + describe("fetch", () => { + let view: ViewV2, view2: ViewV2 + let table: Table, table2: Table + + beforeEach(async () => { + // clean app to make sure fixed amount of views + await config.init() + table = await config.api.table.save(saveTableRequest()) + table2 = await config.api.table.save(saveTableRequest()) + + view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + schema: {}, + }) + view2 = await config.api.viewV2.create({ + tableId: table2._id!, + name: generator.guid(), + schema: {}, + }) + }) + + it("should be able to list views", async () => { + const response = await config.api.viewV2.fetch({ + status: 200, + }) + expect(response.data.length).toEqual(2) + expect(response.data.find(v => v.id === view.id)).toBeDefined() + expect(response.data.find(v => v.id === view2.id)).toBeDefined() + }) + }) + describe("read", () => { let view: ViewV2 let table: Table diff --git a/packages/server/src/tests/utilities/api/viewV2.ts b/packages/server/src/tests/utilities/api/viewV2.ts index 9741240f27..7cc57673a0 100644 --- a/packages/server/src/tests/utilities/api/viewV2.ts +++ b/packages/server/src/tests/utilities/api/viewV2.ts @@ -5,6 +5,7 @@ import { SearchViewRowRequest, PaginatedSearchRowResponse, ViewResponseEnriched, + ViewFetchResponseEnriched, } from "@budibase/types" import { Expectations, TestAPI } from "./base" @@ -49,6 +50,12 @@ export class ViewV2API extends TestAPI { .data } + fetch = async (expectations?: Expectations) => { + return await this._get(`/api/v2/views`, { + expectations, + }) + } + search = async ( viewId: string, params?: SearchViewRowRequest, From dd0764eb600f7c47e6ace83eb94a347b58a4a58d Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 30 Oct 2024 14:08:03 +0000 Subject: [PATCH 06/88] Putting view mapping in place, updating openAPI spec. --- packages/server/specs/openapi.json | 423 +++++++++++++++++- packages/server/specs/openapi.yaml | 290 +++++++++++- packages/server/specs/resources/index.ts | 4 + .../api/controllers/public/mapping/index.ts | 2 + .../api/controllers/public/mapping/types.ts | 3 + .../api/controllers/public/mapping/views.ts | 26 ++ .../src/api/controllers/public/views.ts | 3 +- .../api/routes/public/middleware/mapper.ts | 30 +- packages/server/src/definitions/openapi.ts | 180 ++++++++ 9 files changed, 943 insertions(+), 18 deletions(-) create mode 100644 packages/server/src/api/controllers/public/mapping/views.ts diff --git a/packages/server/specs/openapi.json b/packages/server/specs/openapi.json index f3091a1fc7..c80f947fad 100644 --- a/packages/server/specs/openapi.json +++ b/packages/server/specs/openapi.json @@ -423,6 +423,62 @@ }, "metrics": { "value": "# HELP budibase_os_uptime Time in seconds that the host operating system has been up.\n# TYPE budibase_os_uptime counter\nbudibase_os_uptime 54958\n# HELP budibase_os_free_mem Bytes of memory free for usage on the host operating system.\n# TYPE budibase_os_free_mem gauge\nbudibase_os_free_mem 804507648\n# HELP budibase_os_total_mem Total bytes of memory on the host operating system.\n# TYPE budibase_os_total_mem gauge\nbudibase_os_total_mem 16742404096\n# HELP budibase_os_used_mem Total bytes of memory in use on the host operating system.\n# TYPE budibase_os_used_mem gauge\nbudibase_os_used_mem 15937896448\n# HELP budibase_os_load1 Host operating system load average.\n# TYPE budibase_os_load1 gauge\nbudibase_os_load1 1.91\n# HELP budibase_os_load5 Host operating system load average.\n# TYPE budibase_os_load5 gauge\nbudibase_os_load5 1.75\n# HELP budibase_os_load15 Host operating system load average.\n# TYPE budibase_os_load15 gauge\nbudibase_os_load15 1.56\n# HELP budibase_tenant_user_count The number of users created.\n# TYPE budibase_tenant_user_count gauge\nbudibase_tenant_user_count 1\n# HELP budibase_tenant_app_count The number of apps created by a user.\n# TYPE budibase_tenant_app_count gauge\nbudibase_tenant_app_count 2\n# HELP budibase_tenant_production_app_count The number of apps a user has published.\n# TYPE budibase_tenant_production_app_count gauge\nbudibase_tenant_production_app_count 1\n# HELP budibase_tenant_dev_app_count The number of apps a user has unpublished in development.\n# TYPE budibase_tenant_dev_app_count gauge\nbudibase_tenant_dev_app_count 1\n# HELP budibase_tenant_db_count The number of couchdb databases including global tables such as _users.\n# TYPE budibase_tenant_db_count gauge\nbudibase_tenant_db_count 3\n# HELP budibase_quota_usage_apps The number of apps created.\n# TYPE budibase_quota_usage_apps gauge\nbudibase_quota_usage_apps 1\n# HELP budibase_quota_limit_apps The limit on the number of apps that can be created.\n# TYPE budibase_quota_limit_apps gauge\nbudibase_quota_limit_apps 9007199254740991\n# HELP budibase_quota_usage_rows The number of database rows used from the quota.\n# TYPE budibase_quota_usage_rows gauge\nbudibase_quota_usage_rows 0\n# HELP budibase_quota_limit_rows The limit on the number of rows that can be created.\n# TYPE budibase_quota_limit_rows gauge\nbudibase_quota_limit_rows 9007199254740991\n# HELP budibase_quota_usage_plugins The number of plugins in use.\n# TYPE budibase_quota_usage_plugins gauge\nbudibase_quota_usage_plugins 0\n# HELP budibase_quota_limit_plugins The limit on the number of plugins that can be created.\n# TYPE budibase_quota_limit_plugins gauge\nbudibase_quota_limit_plugins 9007199254740991\n# HELP budibase_quota_usage_user_groups The number of user groups created.\n# TYPE budibase_quota_usage_user_groups gauge\nbudibase_quota_usage_user_groups 0\n# HELP budibase_quota_limit_user_groups The limit on the number of user groups that can be created.\n# TYPE budibase_quota_limit_user_groups gauge\nbudibase_quota_limit_user_groups 9007199254740991\n# HELP budibase_quota_usage_queries The number of queries used in the current month.\n# TYPE budibase_quota_usage_queries gauge\nbudibase_quota_usage_queries 0\n# HELP budibase_quota_limit_queries The limit on the number of queries for the current month.\n# TYPE budibase_quota_limit_queries gauge\nbudibase_quota_limit_queries 9007199254740991\n# HELP budibase_quota_usage_automations The number of automations used in the current month.\n# TYPE budibase_quota_usage_automations gauge\nbudibase_quota_usage_automations 0\n# HELP budibase_quota_limit_automations The limit on the number of automations that can be created.\n# TYPE budibase_quota_limit_automations gauge\nbudibase_quota_limit_automations 9007199254740991\n" + }, + "view": { + "value": { + "data": { + "name": "peopleView", + "tableId": "ta_896a325f7e8147d2a2cda93c5d236511", + "schema": { + "name": { + "visible": true, + "readonly": false, + "order": 1, + "width": 300 + }, + "age": { + "visible": true, + "readonly": true, + "order": 2, + "width": 200 + }, + "salary": { + "visible": false, + "readonly": false + } + }, + "primaryDisplay": "name" + } + } + }, + "views": { + "value": { + "data": [ + { + "name": "peopleView", + "tableId": "ta_896a325f7e8147d2a2cda93c5d236511", + "schema": { + "name": { + "visible": true, + "readonly": false, + "order": 1, + "width": 300 + }, + "age": { + "visible": true, + "readonly": true, + "order": 2, + "width": 200 + }, + "salary": { + "visible": false, + "readonly": false + } + }, + "primaryDisplay": "name" + } + ] + } } }, "securitySchemes": { @@ -831,8 +887,7 @@ "type": "string", "enum": [ "static", - "dynamic", - "ai" + "dynamic" ], "description": "Defines whether this is a static or dynamic formula." } @@ -1042,8 +1097,7 @@ "type": "string", "enum": [ "static", - "dynamic", - "ai" + "dynamic" ], "description": "Defines whether this is a static or dynamic formula." } @@ -1264,8 +1318,7 @@ "type": "string", "enum": [ "static", - "dynamic", - "ai" + "dynamic" ], "description": "Defines whether this is a static or dynamic formula." } @@ -2024,6 +2077,161 @@ "required": [ "data" ] + }, + "view": { + "description": "The view to be created/updated.", + "type": "object", + "required": [ + "name", + "schema" + ], + "properties": { + "name": { + "description": "The name of the view.", + "type": "string" + }, + "primaryDisplay": { + "type": "string", + "description": "A column used to display rows from this view - usually used when rendered in tables." + }, + "schema": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "visible": { + "type": "boolean", + "description": "Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it." + }, + "readonly": { + "type": "boolean", + "description": "When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated." + }, + "order": { + "type": "integer", + "description": "A number defining where the column shows up in tables, lowest being first." + }, + "width": { + "type": "integer", + "description": "A width for the column, defined in pixels - this affects rendering in tables." + } + } + } + } + } + }, + "viewOutput": { + "type": "object", + "properties": { + "data": { + "description": "The view to be created/updated.", + "type": "object", + "required": [ + "name", + "schema", + "id" + ], + "properties": { + "name": { + "description": "The name of the view.", + "type": "string" + }, + "primaryDisplay": { + "type": "string", + "description": "A column used to display rows from this view - usually used when rendered in tables." + }, + "schema": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "visible": { + "type": "boolean", + "description": "Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it." + }, + "readonly": { + "type": "boolean", + "description": "When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated." + }, + "order": { + "type": "integer", + "description": "A number defining where the column shows up in tables, lowest being first." + }, + "width": { + "type": "integer", + "description": "A width for the column, defined in pixels - this affects rendering in tables." + } + } + } + }, + "id": { + "description": "The ID of the view.", + "type": "string" + } + } + } + }, + "required": [ + "data" + ] + }, + "viewSearch": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "description": "The view to be created/updated.", + "type": "object", + "required": [ + "name", + "schema", + "id" + ], + "properties": { + "name": { + "description": "The name of the view.", + "type": "string" + }, + "primaryDisplay": { + "type": "string", + "description": "A column used to display rows from this view - usually used when rendered in tables." + }, + "schema": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "visible": { + "type": "boolean", + "description": "Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it." + }, + "readonly": { + "type": "boolean", + "description": "When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated." + }, + "order": { + "type": "integer", + "description": "A number defining where the column shows up in tables, lowest being first." + }, + "width": { + "type": "integer", + "description": "A width for the column, defined in pixels - this affects rendering in tables." + } + } + } + }, + "id": { + "description": "The ID of the view.", + "type": "string" + } + } + } + } + }, + "required": [ + "data" + ] } } }, @@ -3115,6 +3323,209 @@ } } } + }, + "/views": { + "post": { + "operationId": "viewCreate", + "summary": "Create a view", + "description": "Create a view, this can be against an internal or external table.", + "tags": [ + "views" + ], + "parameters": [ + { + "$ref": "#/components/parameters/appId" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/view" + }, + "examples": { + "view": { + "$ref": "#/components/examples/view" + } + } + } + } + }, + "responses": { + "200": { + "description": "Returns the created view, including the ID which has been generated for it.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/viewOutput" + }, + "examples": { + "view": { + "$ref": "#/components/examples/view" + } + } + } + } + } + } + } + }, + "/views/{viewId}": { + "put": { + "operationId": "viewUpdate", + "summary": "Update a view", + "description": "Update a view, this can be against an internal or external table.", + "tags": [ + "views" + ], + "parameters": [ + { + "$ref": "#/components/parameters/viewId" + }, + { + "$ref": "#/components/parameters/appId" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/view" + }, + "examples": { + "view": { + "$ref": "#/components/examples/view" + } + } + } + } + }, + "responses": { + "200": { + "description": "Returns the updated view.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/viewOutput" + }, + "examples": { + "view": { + "$ref": "#/components/examples/view" + } + } + } + } + } + } + }, + "delete": { + "operationId": "viewDestroy", + "summary": "Delete a view", + "description": "Delete a view, this can be against an internal or external table.", + "tags": [ + "views" + ], + "parameters": [ + { + "$ref": "#/components/parameters/viewId" + }, + { + "$ref": "#/components/parameters/appId" + } + ], + "responses": { + "200": { + "description": "Returns the deleted view.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/viewOutput" + }, + "examples": { + "view": { + "$ref": "#/components/examples/view" + } + } + } + } + } + } + }, + "get": { + "operationId": "viewGetById", + "summary": "Retrieve a view", + "description": "Lookup a view, this could be internal or external.", + "tags": [ + "views" + ], + "parameters": [ + { + "$ref": "#/components/parameters/viewId" + }, + { + "$ref": "#/components/parameters/appId" + } + ], + "responses": { + "200": { + "description": "Returns the retrieved view.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/viewOutput" + }, + "examples": { + "view": { + "$ref": "#/components/examples/view" + } + } + } + } + } + } + } + }, + "/views/search": { + "post": { + "operationId": "viewSearch", + "summary": "Search for views", + "description": "Based on view properties (currently only name) search for views.", + "tags": [ + "views" + ], + "parameters": [ + { + "$ref": "#/components/parameters/appId" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/viewSearch" + } + } + } + }, + "responses": { + "200": { + "description": "Returns the found views, based on the search parameters.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/viewSearch" + }, + "examples": { + "views": { + "$ref": "#/components/examples/views" + } + } + } + } + } + } + } } }, "tags": [] diff --git a/packages/server/specs/openapi.yaml b/packages/server/specs/openapi.yaml index 1e9b9921cf..9a2ce6e0da 100644 --- a/packages/server/specs/openapi.yaml +++ b/packages/server/specs/openapi.yaml @@ -442,6 +442,46 @@ components: # TYPE budibase_quota_limit_automations gauge budibase_quota_limit_automations 9007199254740991 + view: + value: + data: + name: peopleView + tableId: ta_896a325f7e8147d2a2cda93c5d236511 + schema: + name: + visible: true + readonly: false + order: 1 + width: 300 + age: + visible: true + readonly: true + order: 2 + width: 200 + salary: + visible: false + readonly: false + primaryDisplay: name + views: + value: + data: + - name: peopleView + tableId: ta_896a325f7e8147d2a2cda93c5d236511 + schema: + name: + visible: true + readonly: false + order: 1 + width: 300 + age: + visible: true + readonly: true + order: 2 + width: 200 + salary: + visible: false + readonly: false + primaryDisplay: name securitySchemes: ApiKeyAuth: type: apiKey @@ -761,7 +801,6 @@ components: enum: - static - dynamic - - ai description: Defines whether this is a static or dynamic formula. - type: object properties: @@ -931,7 +970,6 @@ components: enum: - static - dynamic - - ai description: Defines whether this is a static or dynamic formula. - type: object properties: @@ -1108,7 +1146,6 @@ components: enum: - static - dynamic - - ai description: Defines whether this is a static or dynamic formula. - type: object properties: @@ -1704,6 +1741,134 @@ components: - userIds required: - data + view: + description: The view to be created/updated. + type: object + required: + - name + - schema + properties: + name: + description: The name of the view. + type: string + primaryDisplay: + type: string + description: A column used to display rows from this view - usually used when + rendered in tables. + schema: + type: object + additionalProperties: + type: object + properties: + visible: + type: boolean + description: Defines whether the column is visible or not - rows + retrieved/updated through this view will not be able to access + it. + readonly: + type: boolean + description: "When used in combination with 'visible: true' the column will be + visible in row responses but cannot be updated." + order: + type: integer + description: A number defining where the column shows up in tables, lowest being + first. + width: + type: integer + description: A width for the column, defined in pixels - this affects rendering + in tables. + viewOutput: + type: object + properties: + data: + description: The view to be created/updated. + type: object + required: + - name + - schema + - id + properties: + name: + description: The name of the view. + type: string + primaryDisplay: + type: string + description: A column used to display rows from this view - usually used when + rendered in tables. + schema: + type: object + additionalProperties: + type: object + properties: + visible: + type: boolean + description: Defines whether the column is visible or not - rows + retrieved/updated through this view will not be able to + access it. + readonly: + type: boolean + description: "When used in combination with 'visible: true' the column will be + visible in row responses but cannot be updated." + order: + type: integer + description: A number defining where the column shows up in tables, lowest being + first. + width: + type: integer + description: A width for the column, defined in pixels - this affects rendering + in tables. + id: + description: The ID of the view. + type: string + required: + - data + viewSearch: + type: object + properties: + data: + type: array + items: + description: The view to be created/updated. + type: object + required: + - name + - schema + - id + properties: + name: + description: The name of the view. + type: string + primaryDisplay: + type: string + description: A column used to display rows from this view - usually used when + rendered in tables. + schema: + type: object + additionalProperties: + type: object + properties: + visible: + type: boolean + description: Defines whether the column is visible or not - rows + retrieved/updated through this view will not be able to + access it. + readonly: + type: boolean + description: "When used in combination with 'visible: true' the column will be + visible in row responses but cannot be updated." + order: + type: integer + description: A number defining where the column shows up in tables, lowest being + first. + width: + type: integer + description: A width for the column, defined in pixels - this affects rendering + in tables. + id: + description: The ID of the view. + type: string + required: + - data security: - ApiKeyAuth: [] paths: @@ -2359,4 +2524,123 @@ paths: examples: users: $ref: "#/components/examples/users" + /views: + post: + operationId: viewCreate + summary: Create a view + description: Create a view, this can be against an internal or external table. + tags: + - views + parameters: + - $ref: "#/components/parameters/appId" + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/view" + examples: + view: + $ref: "#/components/examples/view" + responses: + "200": + description: Returns the created view, including the ID which has been generated + for it. + content: + application/json: + schema: + $ref: "#/components/schemas/viewOutput" + examples: + view: + $ref: "#/components/examples/view" + "/views/{viewId}": + put: + operationId: viewUpdate + summary: Update a view + description: Update a view, this can be against an internal or external table. + tags: + - views + parameters: + - $ref: "#/components/parameters/viewId" + - $ref: "#/components/parameters/appId" + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/view" + examples: + view: + $ref: "#/components/examples/view" + responses: + "200": + description: Returns the updated view. + content: + application/json: + schema: + $ref: "#/components/schemas/viewOutput" + examples: + view: + $ref: "#/components/examples/view" + delete: + operationId: viewDestroy + summary: Delete a view + description: Delete a view, this can be against an internal or external table. + tags: + - views + parameters: + - $ref: "#/components/parameters/viewId" + - $ref: "#/components/parameters/appId" + responses: + "200": + description: Returns the deleted view. + content: + application/json: + schema: + $ref: "#/components/schemas/viewOutput" + examples: + view: + $ref: "#/components/examples/view" + get: + operationId: viewGetById + summary: Retrieve a view + description: Lookup a view, this could be internal or external. + tags: + - views + parameters: + - $ref: "#/components/parameters/viewId" + - $ref: "#/components/parameters/appId" + responses: + "200": + description: Returns the retrieved view. + content: + application/json: + schema: + $ref: "#/components/schemas/viewOutput" + examples: + view: + $ref: "#/components/examples/view" + /views/search: + post: + operationId: viewSearch + summary: Search for views + description: Based on view properties (currently only name) search for views. + tags: + - views + parameters: + - $ref: "#/components/parameters/appId" + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/viewSearch" + responses: + "200": + description: Returns the found views, based on the search parameters. + content: + application/json: + schema: + $ref: "#/components/schemas/viewSearch" + examples: + views: + $ref: "#/components/examples/views" tags: [] diff --git a/packages/server/specs/resources/index.ts b/packages/server/specs/resources/index.ts index c06148b7de..0d32f2a007 100644 --- a/packages/server/specs/resources/index.ts +++ b/packages/server/specs/resources/index.ts @@ -6,6 +6,7 @@ import user from "./user" import metrics from "./metrics" import misc from "./misc" import roles from "./roles" +import view from "./view" export const examples = { ...application.getExamples(), @@ -15,6 +16,8 @@ export const examples = { ...user.getExamples(), ...misc.getExamples(), ...metrics.getExamples(), + ...roles.getExamples(), + ...view.getExamples(), } export const schemas = { @@ -25,4 +28,5 @@ export const schemas = { ...user.getSchemas(), ...misc.getSchemas(), ...roles.getSchemas(), + ...view.getSchemas(), } diff --git a/packages/server/src/api/controllers/public/mapping/index.ts b/packages/server/src/api/controllers/public/mapping/index.ts index 0cdcfbbe4b..b765f4bd76 100644 --- a/packages/server/src/api/controllers/public/mapping/index.ts +++ b/packages/server/src/api/controllers/public/mapping/index.ts @@ -3,6 +3,7 @@ import applications from "./applications" import users from "./users" import rows from "./rows" import queries from "./queries" +import views from "./views" export default { ...tables, @@ -10,4 +11,5 @@ export default { ...users, ...rows, ...queries, + ...views, } diff --git a/packages/server/src/api/controllers/public/mapping/types.ts b/packages/server/src/api/controllers/public/mapping/types.ts index 9fea9b7213..6cbcfddb92 100644 --- a/packages/server/src/api/controllers/public/mapping/types.ts +++ b/packages/server/src/api/controllers/public/mapping/types.ts @@ -9,6 +9,9 @@ export type CreateApplicationParams = components["schemas"]["application"] export type Table = components["schemas"]["tableOutput"]["data"] export type CreateTableParams = components["schemas"]["table"] +export type View = components["schemas"]["viewOutput"]["data"] +export type CreateViewParams = components["schemas"]["view"] + export type Row = components["schemas"]["rowOutput"]["data"] export type RowSearch = components["schemas"]["searchOutput"] export type CreateRowParams = components["schemas"]["row"] diff --git a/packages/server/src/api/controllers/public/mapping/views.ts b/packages/server/src/api/controllers/public/mapping/views.ts new file mode 100644 index 0000000000..b6cf64542e --- /dev/null +++ b/packages/server/src/api/controllers/public/mapping/views.ts @@ -0,0 +1,26 @@ +import { View } from "./types" + +function view(body: any): View { + return { + id: body.id, + name: body.name, + schema: body.schema, + primaryDisplay: body.primaryDisplay, + } +} + +function mapView(ctx: any): { data: View } { + return { + data: view(ctx.body), + } +} + +function mapViews(ctx: any): { data: View[] } { + const tables = ctx.body.map((body: any) => view(body)) + return { data: tables } +} + +export default { + mapView, + mapViews, +} diff --git a/packages/server/src/api/controllers/public/views.ts b/packages/server/src/api/controllers/public/views.ts index 85979126ff..f3265aa70d 100644 --- a/packages/server/src/api/controllers/public/views.ts +++ b/packages/server/src/api/controllers/public/views.ts @@ -18,8 +18,7 @@ function fixView(view: ViewV2, params?: { viewId: string }) { export async function search(ctx: UserCtx, next: Next) { const { name } = ctx.request.body - // TODO: need a view search endpoint - // await controller.v2.fetch(ctx) + await controller.v2.fetch(ctx) ctx.body = stringSearch(ctx.body, name) await next() } diff --git a/packages/server/src/api/routes/public/middleware/mapper.ts b/packages/server/src/api/routes/public/middleware/mapper.ts index 03feb6cc5c..9d0cae5d61 100644 --- a/packages/server/src/api/routes/public/middleware/mapper.ts +++ b/packages/server/src/api/routes/public/middleware/mapper.ts @@ -1,9 +1,10 @@ import { Ctx } from "@budibase/types" import mapping from "../../../controllers/public/mapping" -enum Resources { +enum Resource { APPLICATION = "applications", TABLES = "tables", + VIEWS = "views", ROWS = "rows", USERS = "users", QUERIES = "queries", @@ -15,7 +16,7 @@ function isAttachment(ctx: Ctx) { } function isArrayResponse(ctx: Ctx) { - return ctx.url.endsWith(Resources.SEARCH) || Array.isArray(ctx.body) + return ctx.url.endsWith(Resource.SEARCH) || Array.isArray(ctx.body) } function noResponse(ctx: Ctx) { @@ -38,6 +39,14 @@ function processTables(ctx: Ctx) { } } +function processViews(ctx: Ctx) { + if (isArrayResponse(ctx)) { + return mapping.mapViews(ctx) + } else { + return mapping.mapView(ctx) + } +} + function processRows(ctx: Ctx) { if (isArrayResponse(ctx)) { return mapping.mapRowSearch(ctx) @@ -71,20 +80,27 @@ export default async (ctx: Ctx, next: any) => { let body = {} switch (urlParts[0]) { - case Resources.APPLICATION: + case Resource.APPLICATION: body = processApplications(ctx) break - case Resources.TABLES: - if (urlParts[2] === Resources.ROWS) { + case Resource.TABLES: + if (urlParts[2] === Resource.ROWS) { body = processRows(ctx) } else { body = processTables(ctx) } break - case Resources.USERS: + case Resource.VIEWS: + if (urlParts[2] === Resource.ROWS) { + body = processRows(ctx) + } else { + body = processViews(ctx) + } + break + case Resource.USERS: body = processUsers(ctx) break - case Resources.QUERIES: + case Resource.QUERIES: body = processQueries(ctx) break } diff --git a/packages/server/src/definitions/openapi.ts b/packages/server/src/definitions/openapi.ts index 4479c89d9d..9d68e11185 100644 --- a/packages/server/src/definitions/openapi.ts +++ b/packages/server/src/definitions/openapi.ts @@ -93,6 +93,22 @@ export interface paths { /** Based on user properties (currently only name) search for users. */ post: operations["userSearch"]; }; + "/views": { + /** Create a view, this can be against an internal or external table. */ + post: operations["viewCreate"]; + }; + "/views/{viewId}": { + /** Lookup a view, this could be internal or external. */ + get: operations["viewGetById"]; + /** Update a view, this can be against an internal or external table. */ + put: operations["viewUpdate"]; + /** Delete a view, this can be against an internal or external table. */ + delete: operations["viewDestroy"]; + }; + "/views/search": { + /** Based on view properties (currently only name) search for views. */ + post: operations["viewSearch"]; + }; } export interface components { @@ -813,6 +829,70 @@ export interface components { userIds: string[]; }; }; + /** @description The view to be created/updated. */ + view: { + /** @description The name of the view. */ + name: string; + /** @description A column used to display rows from this view - usually used when rendered in tables. */ + primaryDisplay?: string; + schema: { + [key: string]: { + /** @description Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it. */ + visible?: boolean; + /** @description When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated. */ + readonly?: boolean; + /** @description A number defining where the column shows up in tables, lowest being first. */ + order?: number; + /** @description A width for the column, defined in pixels - this affects rendering in tables. */ + width?: number; + }; + }; + }; + viewOutput: { + /** @description The view to be created/updated. */ + data: { + /** @description The name of the view. */ + name: string; + /** @description A column used to display rows from this view - usually used when rendered in tables. */ + primaryDisplay?: string; + schema: { + [key: string]: { + /** @description Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it. */ + visible?: boolean; + /** @description When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated. */ + readonly?: boolean; + /** @description A number defining where the column shows up in tables, lowest being first. */ + order?: number; + /** @description A width for the column, defined in pixels - this affects rendering in tables. */ + width?: number; + }; + }; + /** @description The ID of the view. */ + id: string; + }; + }; + viewSearch: { + data: { + /** @description The name of the view. */ + name: string; + /** @description A column used to display rows from this view - usually used when rendered in tables. */ + primaryDisplay?: string; + schema: { + [key: string]: { + /** @description Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it. */ + visible?: boolean; + /** @description When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated. */ + readonly?: boolean; + /** @description A number defining where the column shows up in tables, lowest being first. */ + order?: number; + /** @description A width for the column, defined in pixels - this affects rendering in tables. */ + width?: number; + }; + }; + /** @description The ID of the view. */ + id: string; + }[]; + }; }; parameters: { /** @description The ID of the table which this request is targeting. */ @@ -1409,6 +1489,106 @@ export interface operations { }; }; }; + /** Create a view, this can be against an internal or external table. */ + viewCreate: { + parameters: { + header: { + /** The ID of the app which this request is targeting. */ + "x-budibase-app-id": components["parameters"]["appId"]; + }; + }; + responses: { + /** Returns the created view, including the ID which has been generated for it. */ + 200: { + content: { + "application/json": components["schemas"]["viewOutput"]; + }; + }; + }; + requestBody: { + content: { + "application/json": components["schemas"]["view"]; + }; + }; + }; + /** Lookup a view, this could be internal or external. */ + viewGetById: { + parameters: { + header: { + /** The ID of the app which this request is targeting. */ + "x-budibase-app-id": components["parameters"]["appId"]; + }; + }; + responses: { + /** Returns the retrieved view. */ + 200: { + content: { + "application/json": components["schemas"]["viewOutput"]; + }; + }; + }; + }; + /** Update a view, this can be against an internal or external table. */ + viewUpdate: { + parameters: { + header: { + /** The ID of the app which this request is targeting. */ + "x-budibase-app-id": components["parameters"]["appId"]; + }; + }; + responses: { + /** Returns the updated view. */ + 200: { + content: { + "application/json": components["schemas"]["viewOutput"]; + }; + }; + }; + requestBody: { + content: { + "application/json": components["schemas"]["view"]; + }; + }; + }; + /** Delete a view, this can be against an internal or external table. */ + viewDestroy: { + parameters: { + header: { + /** The ID of the app which this request is targeting. */ + "x-budibase-app-id": components["parameters"]["appId"]; + }; + }; + responses: { + /** Returns the deleted view. */ + 200: { + content: { + "application/json": components["schemas"]["viewOutput"]; + }; + }; + }; + }; + /** Based on view properties (currently only name) search for views. */ + viewSearch: { + parameters: { + header: { + /** The ID of the app which this request is targeting. */ + "x-budibase-app-id": components["parameters"]["appId"]; + }; + }; + responses: { + /** Returns the found views, based on the search parameters. */ + 200: { + content: { + "application/json": components["schemas"]["viewSearch"]; + }; + }; + }; + requestBody: { + content: { + "application/json": components["schemas"]["viewSearch"]; + }; + }; + }; } export interface external {} From 38760897bf4a5579a1df4e5ca1e1b8bae7ed5916 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 30 Oct 2024 14:40:13 +0000 Subject: [PATCH 07/88] Updating specs again. --- packages/server/specs/openapi.json | 9 +++++++++ packages/server/specs/openapi.yaml | 7 +++++++ packages/server/specs/parameters.ts | 10 ++++++++++ packages/server/src/definitions/openapi.ts | 14 ++++++++++++++ 4 files changed, 40 insertions(+) diff --git a/packages/server/specs/openapi.json b/packages/server/specs/openapi.json index c80f947fad..3af15e1f02 100644 --- a/packages/server/specs/openapi.json +++ b/packages/server/specs/openapi.json @@ -32,6 +32,15 @@ "type": "string" } }, + "viewId": { + "in": "path", + "name": "viewId", + "required": true, + "description": "The ID of the view which this request is targeting.", + "schema": { + "type": "string" + } + }, "rowId": { "in": "path", "name": "rowId", diff --git a/packages/server/specs/openapi.yaml b/packages/server/specs/openapi.yaml index 9a2ce6e0da..094957805f 100644 --- a/packages/server/specs/openapi.yaml +++ b/packages/server/specs/openapi.yaml @@ -23,6 +23,13 @@ components: description: The ID of the table which this request is targeting. schema: type: string + viewId: + in: path + name: viewId + required: true + description: The ID of the view which this request is targeting. + schema: + type: string rowId: in: path name: rowId diff --git a/packages/server/specs/parameters.ts b/packages/server/specs/parameters.ts index a4f2b27ae4..abc26c48d6 100644 --- a/packages/server/specs/parameters.ts +++ b/packages/server/specs/parameters.ts @@ -8,6 +8,16 @@ export const tableId = { }, } +export const viewId = { + in: "path", + name: "viewId", + required: true, + description: "The ID of the view which this request is targeting.", + schema: { + type: "string", + }, +} + export const rowId = { in: "path", name: "rowId", diff --git a/packages/server/src/definitions/openapi.ts b/packages/server/src/definitions/openapi.ts index 9d68e11185..a1e5d8202f 100644 --- a/packages/server/src/definitions/openapi.ts +++ b/packages/server/src/definitions/openapi.ts @@ -897,6 +897,8 @@ export interface components { parameters: { /** @description The ID of the table which this request is targeting. */ tableId: string; + /** @description The ID of the view which this request is targeting. */ + viewId: string; /** @description The ID of the row which this request is targeting. */ rowId: string; /** @description The ID of the app which this request is targeting. */ @@ -1514,6 +1516,10 @@ export interface operations { /** Lookup a view, this could be internal or external. */ viewGetById: { parameters: { + path: { + /** The ID of the view which this request is targeting. */ + viewId: components["parameters"]["viewId"]; + }; header: { /** The ID of the app which this request is targeting. */ "x-budibase-app-id": components["parameters"]["appId"]; @@ -1531,6 +1537,10 @@ export interface operations { /** Update a view, this can be against an internal or external table. */ viewUpdate: { parameters: { + path: { + /** The ID of the view which this request is targeting. */ + viewId: components["parameters"]["viewId"]; + }; header: { /** The ID of the app which this request is targeting. */ "x-budibase-app-id": components["parameters"]["appId"]; @@ -1553,6 +1563,10 @@ export interface operations { /** Delete a view, this can be against an internal or external table. */ viewDestroy: { parameters: { + path: { + /** The ID of the view which this request is targeting. */ + viewId: components["parameters"]["viewId"]; + }; header: { /** The ID of the app which this request is targeting. */ "x-budibase-app-id": components["parameters"]["appId"]; From 037a33dc7d6e8ce34e009d13cd0a8b0ca63211d0 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 30 Oct 2024 17:12:48 +0000 Subject: [PATCH 08/88] Updating specs to correct some issues with app ID. --- packages/server/specs/openapi.json | 6 +++--- packages/server/specs/openapi.yaml | 6 +++--- packages/server/specs/parameters.ts | 4 ++-- packages/server/src/api/controllers/public/views.ts | 9 +++++++-- packages/server/src/api/routes/public/index.ts | 10 +++++++--- packages/server/src/api/routes/public/views.ts | 2 +- packages/server/src/definitions/openapi.ts | 2 +- packages/server/src/middleware/publicApi.ts | 4 ++-- 8 files changed, 26 insertions(+), 17 deletions(-) diff --git a/packages/server/specs/openapi.json b/packages/server/specs/openapi.json index 3af15e1f02..1864dd8252 100644 --- a/packages/server/specs/openapi.json +++ b/packages/server/specs/openapi.json @@ -56,7 +56,7 @@ "required": true, "description": "The ID of the app which this request is targeting.", "schema": { - "default": "{{ appId }}", + "default": "{{appId}}", "type": "string" } }, @@ -66,7 +66,7 @@ "required": true, "description": "The ID of the app which this request is targeting.", "schema": { - "default": "{{ appId }}", + "default": "{{appId}}", "type": "string" } }, @@ -3512,7 +3512,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/viewSearch" + "$ref": "#/components/schemas/nameSearch" } } } diff --git a/packages/server/specs/openapi.yaml b/packages/server/specs/openapi.yaml index 094957805f..cc10882b77 100644 --- a/packages/server/specs/openapi.yaml +++ b/packages/server/specs/openapi.yaml @@ -43,7 +43,7 @@ components: required: true description: The ID of the app which this request is targeting. schema: - default: "{{ appId }}" + default: "{{appId}}" type: string appIdUrl: in: path @@ -51,7 +51,7 @@ components: required: true description: The ID of the app which this request is targeting. schema: - default: "{{ appId }}" + default: "{{appId}}" type: string queryId: in: path @@ -2639,7 +2639,7 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/viewSearch" + $ref: "#/components/schemas/nameSearch" responses: "200": description: Returns the found views, based on the search parameters. diff --git a/packages/server/specs/parameters.ts b/packages/server/specs/parameters.ts index abc26c48d6..b3fb274567 100644 --- a/packages/server/specs/parameters.ts +++ b/packages/server/specs/parameters.ts @@ -34,7 +34,7 @@ export const appId = { required: true, description: "The ID of the app which this request is targeting.", schema: { - default: "{{ appId }}", + default: "{{appId}}", type: "string", }, } @@ -45,7 +45,7 @@ export const appIdUrl = { required: true, description: "The ID of the app which this request is targeting.", schema: { - default: "{{ appId }}", + default: "{{appId}}", type: "string", }, } diff --git a/packages/server/src/api/controllers/public/views.ts b/packages/server/src/api/controllers/public/views.ts index f3265aa70d..d43f1592b1 100644 --- a/packages/server/src/api/controllers/public/views.ts +++ b/packages/server/src/api/controllers/public/views.ts @@ -19,7 +19,7 @@ function fixView(view: ViewV2, params?: { viewId: string }) { export async function search(ctx: UserCtx, next: Next) { const { name } = ctx.request.body await controller.v2.fetch(ctx) - ctx.body = stringSearch(ctx.body, name) + ctx.body = stringSearch(ctx.body.data, name) await next() } @@ -30,7 +30,12 @@ export async function create(ctx: UserCtx, next: Next) { } export async function read(ctx: UserCtx, next: Next) { - await controller.v2.get(ctx) + await controller.v2.get({ + ...ctx, + params: { + viewId: ctx.params.viewId, + }, + }) await next() } diff --git a/packages/server/src/api/routes/public/index.ts b/packages/server/src/api/routes/public/index.ts index 36e0f74bee..bcec8f3166 100644 --- a/packages/server/src/api/routes/public/index.ts +++ b/packages/server/src/api/routes/public/index.ts @@ -4,18 +4,20 @@ import queryEndpoints from "./queries" import tableEndpoints from "./tables" import rowEndpoints from "./rows" import userEndpoints from "./users" +import viewEndpoints from "./views" +import roleEndpoints from "./roles" import authorized from "../../../middleware/authorized" import publicApi from "../../../middleware/publicApi" import { paramResource, paramSubResource } from "../../../middleware/resourceId" -import { PermissionType, PermissionLevel } from "@budibase/types" +import { PermissionLevel, PermissionType } from "@budibase/types" import { CtxFn } from "./utils/Endpoint" import mapperMiddleware from "./middleware/mapper" import env from "../../../environment" +import { middleware, redis } from "@budibase/backend-core" +import { SelectableDatabase } from "@budibase/backend-core/src/redis/utils" // below imports don't have declaration files const Router = require("@koa/router") const { RateLimit, Stores } = require("koa2-ratelimit") -import { middleware, redis } from "@budibase/backend-core" -import { SelectableDatabase } from "@budibase/backend-core/src/redis/utils" interface KoaRateLimitOptions { socket: { @@ -145,8 +147,10 @@ function applyRoutes( } applyAdminRoutes(metricEndpoints) +applyAdminRoutes(roleEndpoints) applyRoutes(appEndpoints, PermissionType.APP, "appId") applyRoutes(tableEndpoints, PermissionType.TABLE, "tableId") +applyRoutes(viewEndpoints, PermissionType.VIEW, "viewId") applyRoutes(userEndpoints, PermissionType.USER, "userId") applyRoutes(queryEndpoints, PermissionType.QUERY, "queryId") // needs to be applied last for routing purposes, don't override other endpoints diff --git a/packages/server/src/api/routes/public/views.ts b/packages/server/src/api/routes/public/views.ts index 7c182d105f..139d79be1f 100644 --- a/packages/server/src/api/routes/public/views.ts +++ b/packages/server/src/api/routes/public/views.ts @@ -144,7 +144,7 @@ read.push(new Endpoint("get", "/views/:viewId", controller.read)) * content: * application/json: * schema: - * $ref: '#/components/schemas/viewSearch' + * $ref: '#/components/schemas/nameSearch' * responses: * 200: * description: Returns the found views, based on the search parameters. diff --git a/packages/server/src/definitions/openapi.ts b/packages/server/src/definitions/openapi.ts index a1e5d8202f..4d6ab6a06c 100644 --- a/packages/server/src/definitions/openapi.ts +++ b/packages/server/src/definitions/openapi.ts @@ -1599,7 +1599,7 @@ export interface operations { }; requestBody: { content: { - "application/json": components["schemas"]["viewSearch"]; + "application/json": components["schemas"]["nameSearch"]; }; }; }; diff --git a/packages/server/src/middleware/publicApi.ts b/packages/server/src/middleware/publicApi.ts index e3897d1a49..da10dd3539 100644 --- a/packages/server/src/middleware/publicApi.ts +++ b/packages/server/src/middleware/publicApi.ts @@ -1,8 +1,8 @@ import { constants, utils } from "@budibase/backend-core" -import { BBContext } from "@budibase/types" +import { Ctx } from "@budibase/types" export default function ({ requiresAppId }: { requiresAppId?: boolean } = {}) { - return async (ctx: BBContext, next: any) => { + return async (ctx: Ctx, next: any) => { const appId = await utils.getAppIdFromCtx(ctx) if (requiresAppId && !appId) { ctx.throw( From 9d8566189387a954b9986ec6627b7ec0b6ae0e60 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 31 Oct 2024 17:42:46 +0000 Subject: [PATCH 09/88] Finishing specs to explain how to configure a calculation view. --- packages/server/specs/openapi.json | 287 ++++++++++++++---- packages/server/specs/openapi.yaml | 254 ++++++++++++---- packages/server/specs/resources/view.ts | 48 ++- .../server/src/api/controllers/public/rows.ts | 20 +- .../src/api/controllers/public/views.ts | 16 +- packages/server/src/api/routes/public/rows.ts | 36 +++ packages/server/src/definitions/openapi.ts | 151 +++++++-- 7 files changed, 661 insertions(+), 151 deletions(-) diff --git a/packages/server/specs/openapi.json b/packages/server/specs/openapi.json index 1864dd8252..d45a8f28c9 100644 --- a/packages/server/specs/openapi.json +++ b/packages/server/specs/openapi.json @@ -2099,6 +2099,13 @@ "description": "The name of the view.", "type": "string" }, + "type": { + "description": "The type of view - standard (empty value) or calculation.", + "type": "string", + "enum": [ + "calculation" + ] + }, "primaryDisplay": { "type": "string", "description": "A column used to display rows from this view - usually used when rendered in tables." @@ -2106,25 +2113,65 @@ "schema": { "type": "object", "additionalProperties": { - "type": "object", - "properties": { - "visible": { - "type": "boolean", - "description": "Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it." + "oneOf": [ + { + "type": "object", + "properties": { + "visible": { + "type": "boolean", + "description": "Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it." + }, + "readonly": { + "type": "boolean", + "description": "When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated." + }, + "order": { + "type": "integer", + "description": "A number defining where the column shows up in tables, lowest being first." + }, + "width": { + "type": "integer", + "description": "A width for the column, defined in pixels - this affects rendering in tables." + }, + "column": { + "type": "array", + "description": "If this is a relationship column, we can set the columns we wish to include", + "items": { + "type": "object", + "properties": { + "readonly": { + "type": "boolean" + } + } + } + } + } }, - "readonly": { - "type": "boolean", - "description": "When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated." - }, - "order": { - "type": "integer", - "description": "A number defining where the column shows up in tables, lowest being first." - }, - "width": { - "type": "integer", - "description": "A width for the column, defined in pixels - this affects rendering in tables." + { + "type": "object", + "properties": { + "calculationType": { + "type": "string", + "description": "This column should be built from a calculation, specifying a type and field. It is important to note when a calculation is configured all non-calculation columns will be used for grouping.", + "enum": [ + "sum", + "avg", + "count", + "min", + "max" + ] + }, + "field": { + "type": "string", + "description": "The field from the table to perform the calculation on." + }, + "distinct": { + "type": "boolean", + "description": "Can be used in tandem with the count calculation type, to count unique entries." + } + } } - } + ] } } } @@ -2145,6 +2192,13 @@ "description": "The name of the view.", "type": "string" }, + "type": { + "description": "The type of view - standard (empty value) or calculation.", + "type": "string", + "enum": [ + "calculation" + ] + }, "primaryDisplay": { "type": "string", "description": "A column used to display rows from this view - usually used when rendered in tables." @@ -2152,25 +2206,65 @@ "schema": { "type": "object", "additionalProperties": { - "type": "object", - "properties": { - "visible": { - "type": "boolean", - "description": "Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it." + "oneOf": [ + { + "type": "object", + "properties": { + "visible": { + "type": "boolean", + "description": "Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it." + }, + "readonly": { + "type": "boolean", + "description": "When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated." + }, + "order": { + "type": "integer", + "description": "A number defining where the column shows up in tables, lowest being first." + }, + "width": { + "type": "integer", + "description": "A width for the column, defined in pixels - this affects rendering in tables." + }, + "column": { + "type": "array", + "description": "If this is a relationship column, we can set the columns we wish to include", + "items": { + "type": "object", + "properties": { + "readonly": { + "type": "boolean" + } + } + } + } + } }, - "readonly": { - "type": "boolean", - "description": "When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated." - }, - "order": { - "type": "integer", - "description": "A number defining where the column shows up in tables, lowest being first." - }, - "width": { - "type": "integer", - "description": "A width for the column, defined in pixels - this affects rendering in tables." + { + "type": "object", + "properties": { + "calculationType": { + "type": "string", + "description": "This column should be built from a calculation, specifying a type and field. It is important to note when a calculation is configured all non-calculation columns will be used for grouping.", + "enum": [ + "sum", + "avg", + "count", + "min", + "max" + ] + }, + "field": { + "type": "string", + "description": "The field from the table to perform the calculation on." + }, + "distinct": { + "type": "boolean", + "description": "Can be used in tandem with the count calculation type, to count unique entries." + } + } } - } + ] } }, "id": { @@ -2202,6 +2296,13 @@ "description": "The name of the view.", "type": "string" }, + "type": { + "description": "The type of view - standard (empty value) or calculation.", + "type": "string", + "enum": [ + "calculation" + ] + }, "primaryDisplay": { "type": "string", "description": "A column used to display rows from this view - usually used when rendered in tables." @@ -2209,25 +2310,65 @@ "schema": { "type": "object", "additionalProperties": { - "type": "object", - "properties": { - "visible": { - "type": "boolean", - "description": "Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it." + "oneOf": [ + { + "type": "object", + "properties": { + "visible": { + "type": "boolean", + "description": "Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it." + }, + "readonly": { + "type": "boolean", + "description": "When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated." + }, + "order": { + "type": "integer", + "description": "A number defining where the column shows up in tables, lowest being first." + }, + "width": { + "type": "integer", + "description": "A width for the column, defined in pixels - this affects rendering in tables." + }, + "column": { + "type": "array", + "description": "If this is a relationship column, we can set the columns we wish to include", + "items": { + "type": "object", + "properties": { + "readonly": { + "type": "boolean" + } + } + } + } + } }, - "readonly": { - "type": "boolean", - "description": "When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated." - }, - "order": { - "type": "integer", - "description": "A number defining where the column shows up in tables, lowest being first." - }, - "width": { - "type": "integer", - "description": "A width for the column, defined in pixels - this affects rendering in tables." + { + "type": "object", + "properties": { + "calculationType": { + "type": "string", + "description": "This column should be built from a calculation, specifying a type and field. It is important to note when a calculation is configured all non-calculation columns will be used for grouping.", + "enum": [ + "sum", + "avg", + "count", + "min", + "max" + ] + }, + "field": { + "type": "string", + "description": "The field from the table to perform the calculation on." + }, + "distinct": { + "type": "boolean", + "description": "Can be used in tandem with the count calculation type, to count unique entries." + } + } } - } + ] } }, "id": { @@ -2958,6 +3099,50 @@ } } }, + "/views/{viewId}/rows/search": { + "post": { + "operationId": "rowViewSearch", + "summary": "Search for rows in a view", + "tags": [ + "rows" + ], + "parameters": [ + { + "$ref": "#/components/parameters/viewId" + }, + { + "$ref": "#/components/parameters/appId" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/rowSearch" + } + } + } + }, + "responses": { + "200": { + "description": "The response will contain an array of rows that match the search parameters.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/searchOutput" + }, + "examples": { + "search": { + "$ref": "#/components/examples/rows" + } + } + } + } + } + } + } + }, "/tables": { "post": { "operationId": "tableCreate", diff --git a/packages/server/specs/openapi.yaml b/packages/server/specs/openapi.yaml index cc10882b77..0e551207ed 100644 --- a/packages/server/specs/openapi.yaml +++ b/packages/server/specs/openapi.yaml @@ -1758,6 +1758,11 @@ components: name: description: The name of the view. type: string + type: + description: The type of view - standard (empty value) or calculation. + type: string + enum: + - calculation primaryDisplay: type: string description: A column used to display rows from this view - usually used when @@ -1765,47 +1770,8 @@ components: schema: type: object additionalProperties: - type: object - properties: - visible: - type: boolean - description: Defines whether the column is visible or not - rows - retrieved/updated through this view will not be able to access - it. - readonly: - type: boolean - description: "When used in combination with 'visible: true' the column will be - visible in row responses but cannot be updated." - order: - type: integer - description: A number defining where the column shows up in tables, lowest being - first. - width: - type: integer - description: A width for the column, defined in pixels - this affects rendering - in tables. - viewOutput: - type: object - properties: - data: - description: The view to be created/updated. - type: object - required: - - name - - schema - - id - properties: - name: - description: The name of the view. - type: string - primaryDisplay: - type: string - description: A column used to display rows from this view - usually used when - rendered in tables. - schema: - type: object - additionalProperties: - type: object + oneOf: + - type: object properties: visible: type: boolean @@ -1824,6 +1790,112 @@ components: type: integer description: A width for the column, defined in pixels - this affects rendering in tables. + column: + type: array + description: If this is a relationship column, we can set the columns we wish to + include + items: + type: object + properties: + readonly: + type: boolean + - type: object + properties: + calculationType: + type: string + description: This column should be built from a calculation, specifying a type + and field. It is important to note when a calculation is + configured all non-calculation columns will be used for + grouping. + enum: + - sum + - avg + - count + - min + - max + field: + type: string + description: The field from the table to perform the calculation on. + distinct: + type: boolean + description: Can be used in tandem with the count calculation type, to count + unique entries. + viewOutput: + type: object + properties: + data: + description: The view to be created/updated. + type: object + required: + - name + - schema + - id + properties: + name: + description: The name of the view. + type: string + type: + description: The type of view - standard (empty value) or calculation. + type: string + enum: + - calculation + primaryDisplay: + type: string + description: A column used to display rows from this view - usually used when + rendered in tables. + schema: + type: object + additionalProperties: + oneOf: + - type: object + properties: + visible: + type: boolean + description: Defines whether the column is visible or not - rows + retrieved/updated through this view will not be able + to access it. + readonly: + type: boolean + description: "When used in combination with 'visible: true' the column will be + visible in row responses but cannot be updated." + order: + type: integer + description: A number defining where the column shows up in tables, lowest being + first. + width: + type: integer + description: A width for the column, defined in pixels - this affects rendering + in tables. + column: + type: array + description: If this is a relationship column, we can set the columns we wish to + include + items: + type: object + properties: + readonly: + type: boolean + - type: object + properties: + calculationType: + type: string + description: This column should be built from a calculation, specifying a type + and field. It is important to note when a calculation + is configured all non-calculation columns will be used + for grouping. + enum: + - sum + - avg + - count + - min + - max + field: + type: string + description: The field from the table to perform the calculation on. + distinct: + type: boolean + description: Can be used in tandem with the count calculation type, to count + unique entries. id: description: The ID of the view. type: string @@ -1845,6 +1917,11 @@ components: name: description: The name of the view. type: string + type: + description: The type of view - standard (empty value) or calculation. + type: string + enum: + - calculation primaryDisplay: type: string description: A column used to display rows from this view - usually used when @@ -1852,25 +1929,56 @@ components: schema: type: object additionalProperties: - type: object - properties: - visible: - type: boolean - description: Defines whether the column is visible or not - rows - retrieved/updated through this view will not be able to - access it. - readonly: - type: boolean - description: "When used in combination with 'visible: true' the column will be - visible in row responses but cannot be updated." - order: - type: integer - description: A number defining where the column shows up in tables, lowest being - first. - width: - type: integer - description: A width for the column, defined in pixels - this affects rendering - in tables. + oneOf: + - type: object + properties: + visible: + type: boolean + description: Defines whether the column is visible or not - rows + retrieved/updated through this view will not be able + to access it. + readonly: + type: boolean + description: "When used in combination with 'visible: true' the column will be + visible in row responses but cannot be updated." + order: + type: integer + description: A number defining where the column shows up in tables, lowest being + first. + width: + type: integer + description: A width for the column, defined in pixels - this affects rendering + in tables. + column: + type: array + description: If this is a relationship column, we can set the columns we wish to + include + items: + type: object + properties: + readonly: + type: boolean + - type: object + properties: + calculationType: + type: string + description: This column should be built from a calculation, specifying a type + and field. It is important to note when a + calculation is configured all non-calculation + columns will be used for grouping. + enum: + - sum + - avg + - count + - min + - max + field: + type: string + description: The field from the table to perform the calculation on. + distinct: + type: boolean + description: Can be used in tandem with the count calculation type, to count + unique entries. id: description: The ID of the view. type: string @@ -2308,6 +2416,32 @@ paths: examples: search: $ref: "#/components/examples/rows" + "/views/{viewId}/rows/search": + post: + operationId: rowViewSearch + summary: Search for rows in a view + tags: + - rows + parameters: + - $ref: "#/components/parameters/viewId" + - $ref: "#/components/parameters/appId" + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/rowSearch" + responses: + "200": + description: The response will contain an array of rows that match the search + parameters. + content: + application/json: + schema: + $ref: "#/components/schemas/searchOutput" + examples: + search: + $ref: "#/components/examples/rows" /tables: post: operationId: tableCreate diff --git a/packages/server/specs/resources/view.ts b/packages/server/specs/resources/view.ts index 5afdf78a0e..e798883ced 100644 --- a/packages/server/specs/resources/view.ts +++ b/packages/server/specs/resources/view.ts @@ -1,5 +1,6 @@ import { object } from "./utils" import Resource from "./utils/Resource" +import { CalculationType } from "@budibase/types" const view = { name: "peopleView", @@ -46,6 +47,19 @@ const baseColumnDef = { description: "A width for the column, defined in pixels - this affects rendering in tables.", }, + column: { + type: "array", + description: + "If this is a relationship column, we can set the columns we wish to include", + items: { + type: "object", + properties: { + readonly: { + type: "boolean", + }, + }, + }, + }, } const viewSchema = { @@ -57,6 +71,11 @@ const viewSchema = { description: "The name of the view.", type: "string", }, + type: { + description: "The type of view - standard (empty value) or calculation.", + type: "string", + enum: ["calculation"], + }, primaryDisplay: { type: "string", description: @@ -65,8 +84,33 @@ const viewSchema = { schema: { type: "object", additionalProperties: { - type: "object", - properties: baseColumnDef, + oneOf: [ + { + type: "object", + properties: baseColumnDef, + }, + { + type: "object", + properties: { + calculationType: { + type: "string", + description: + "This column should be built from a calculation, specifying a type and field. It is important to note when a calculation is configured all non-calculation columns will be used for grouping.", + enum: Object.values(CalculationType), + }, + field: { + type: "string", + description: + "The field from the table to perform the calculation on.", + }, + distinct: { + type: "boolean", + description: + "Can be used in tandem with the count calculation type, to count unique entries.", + }, + }, + }, + ], }, }, }, diff --git a/packages/server/src/api/controllers/public/rows.ts b/packages/server/src/api/controllers/public/rows.ts index 16403b06c9..634a41ed85 100644 --- a/packages/server/src/api/controllers/public/rows.ts +++ b/packages/server/src/api/controllers/public/rows.ts @@ -22,13 +22,13 @@ export function fixRow(row: Row, params: any) { return row } -export async function search(ctx: UserCtx, next: Next) { +function getSearchParameters(ctx: UserCtx) { let { sort, paginate, bookmark, limit, query } = ctx.request.body // update the body to the correct format of the internal search if (!sort) { sort = {} } - ctx.request.body = { + return { sort: sort.column, sortType: sort.type, sortOrder: sort.order, @@ -37,10 +37,25 @@ export async function search(ctx: UserCtx, next: Next) { limit, query, } +} + +export async function search(ctx: UserCtx, next: Next) { + ctx.request.body = getSearchParameters(ctx) await rowController.search(ctx) await next() } +export async function viewSearch(ctx: UserCtx, next: Next) { + ctx.request.body = getSearchParameters(ctx) + await rowController.views.searchView({ + ...ctx, + params: { + viewId: ctx.params.viewId, + }, + }) + await next() +} + export async function create(ctx: UserCtx, next: Next) { ctx.request.body = fixRow(ctx.request.body, ctx.params) await rowController.save(ctx) @@ -79,4 +94,5 @@ export default { update, destroy, search, + viewSearch, } diff --git a/packages/server/src/api/controllers/public/views.ts b/packages/server/src/api/controllers/public/views.ts index d43f1592b1..e400e850ea 100644 --- a/packages/server/src/api/controllers/public/views.ts +++ b/packages/server/src/api/controllers/public/views.ts @@ -40,12 +40,16 @@ export async function read(ctx: UserCtx, next: Next) { } export async function update(ctx: UserCtx, next: Next) { - // TODO: this is more complex - no rev on views - // ctx.request.body = await addRev( - // fixView(ctx.request.body, ctx.params), - // ctx.params.tableId - // ) - await controller.v2.update(ctx) + const viewId = ctx.params.viewId + await controller.v2.update({ + ...ctx, + body: { + data: fixView(ctx.body, { viewId }), + }, + params: { + viewId, + }, + }) await next() } diff --git a/packages/server/src/api/routes/public/rows.ts b/packages/server/src/api/routes/public/rows.ts index 80ad6d6434..2085c5cf0f 100644 --- a/packages/server/src/api/routes/public/rows.ts +++ b/packages/server/src/api/routes/public/rows.ts @@ -168,4 +168,40 @@ read.push( ).addMiddleware(externalSearchValidator()) ) +/** + * @openapi + * /views/{viewId}/rows/search: + * post: + * operationId: rowViewSearch + * summary: Search for rows in a view + * tags: + * - rows + * parameters: + * - $ref: '#/components/parameters/viewId' + * - $ref: '#/components/parameters/appId' + * requestBody: + * required: true + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/rowSearch' + * responses: + * 200: + * description: The response will contain an array of rows that match the search parameters. + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/searchOutput' + * examples: + * search: + * $ref: '#/components/examples/rows' + */ +read.push( + new Endpoint( + "post", + "/views/:viewId/rows/search", + controller.search + ).addMiddleware(externalSearchValidator()) +) + export default { read, write } diff --git a/packages/server/src/definitions/openapi.ts b/packages/server/src/definitions/openapi.ts index 4d6ab6a06c..fed19ec5cf 100644 --- a/packages/server/src/definitions/openapi.ts +++ b/packages/server/src/definitions/openapi.ts @@ -65,6 +65,9 @@ export interface paths { "/tables/{tableId}/rows/search": { post: operations["rowSearch"]; }; + "/views/{viewId}/rows/search": { + post: operations["rowViewSearch"]; + }; "/tables": { /** Create a table, this could be internal or external. */ post: operations["tableCreate"]; @@ -833,19 +836,40 @@ export interface components { view: { /** @description The name of the view. */ name: string; + /** + * @description The type of view - standard (empty value) or calculation. + * @enum {string} + */ + type?: "calculation"; /** @description A column used to display rows from this view - usually used when rendered in tables. */ primaryDisplay?: string; schema: { - [key: string]: { - /** @description Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it. */ - visible?: boolean; - /** @description When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated. */ - readonly?: boolean; - /** @description A number defining where the column shows up in tables, lowest being first. */ - order?: number; - /** @description A width for the column, defined in pixels - this affects rendering in tables. */ - width?: number; - }; + [key: string]: + | { + /** @description Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it. */ + visible?: boolean; + /** @description When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated. */ + readonly?: boolean; + /** @description A number defining where the column shows up in tables, lowest being first. */ + order?: number; + /** @description A width for the column, defined in pixels - this affects rendering in tables. */ + width?: number; + /** @description If this is a relationship column, we can set the columns we wish to include */ + column?: { + readonly?: boolean; + }[]; + } + | { + /** + * @description This column should be built from a calculation, specifying a type and field. It is important to note when a calculation is configured all non-calculation columns will be used for grouping. + * @enum {string} + */ + calculationType?: "sum" | "avg" | "count" | "min" | "max"; + /** @description The field from the table to perform the calculation on. */ + field?: string; + /** @description Can be used in tandem with the count calculation type, to count unique entries. */ + distinct?: boolean; + }; }; }; viewOutput: { @@ -853,19 +877,40 @@ export interface components { data: { /** @description The name of the view. */ name: string; + /** + * @description The type of view - standard (empty value) or calculation. + * @enum {string} + */ + type?: "calculation"; /** @description A column used to display rows from this view - usually used when rendered in tables. */ primaryDisplay?: string; schema: { - [key: string]: { - /** @description Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it. */ - visible?: boolean; - /** @description When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated. */ - readonly?: boolean; - /** @description A number defining where the column shows up in tables, lowest being first. */ - order?: number; - /** @description A width for the column, defined in pixels - this affects rendering in tables. */ - width?: number; - }; + [key: string]: + | { + /** @description Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it. */ + visible?: boolean; + /** @description When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated. */ + readonly?: boolean; + /** @description A number defining where the column shows up in tables, lowest being first. */ + order?: number; + /** @description A width for the column, defined in pixels - this affects rendering in tables. */ + width?: number; + /** @description If this is a relationship column, we can set the columns we wish to include */ + column?: { + readonly?: boolean; + }[]; + } + | { + /** + * @description This column should be built from a calculation, specifying a type and field. It is important to note when a calculation is configured all non-calculation columns will be used for grouping. + * @enum {string} + */ + calculationType?: "sum" | "avg" | "count" | "min" | "max"; + /** @description The field from the table to perform the calculation on. */ + field?: string; + /** @description Can be used in tandem with the count calculation type, to count unique entries. */ + distinct?: boolean; + }; }; /** @description The ID of the view. */ id: string; @@ -875,19 +920,40 @@ export interface components { data: { /** @description The name of the view. */ name: string; + /** + * @description The type of view - standard (empty value) or calculation. + * @enum {string} + */ + type?: "calculation"; /** @description A column used to display rows from this view - usually used when rendered in tables. */ primaryDisplay?: string; schema: { - [key: string]: { - /** @description Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it. */ - visible?: boolean; - /** @description When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated. */ - readonly?: boolean; - /** @description A number defining where the column shows up in tables, lowest being first. */ - order?: number; - /** @description A width for the column, defined in pixels - this affects rendering in tables. */ - width?: number; - }; + [key: string]: + | { + /** @description Defines whether the column is visible or not - rows retrieved/updated through this view will not be able to access it. */ + visible?: boolean; + /** @description When used in combination with 'visible: true' the column will be visible in row responses but cannot be updated. */ + readonly?: boolean; + /** @description A number defining where the column shows up in tables, lowest being first. */ + order?: number; + /** @description A width for the column, defined in pixels - this affects rendering in tables. */ + width?: number; + /** @description If this is a relationship column, we can set the columns we wish to include */ + column?: { + readonly?: boolean; + }[]; + } + | { + /** + * @description This column should be built from a calculation, specifying a type and field. It is important to note when a calculation is configured all non-calculation columns will be used for grouping. + * @enum {string} + */ + calculationType?: "sum" | "avg" | "count" | "min" | "max"; + /** @description The field from the table to perform the calculation on. */ + field?: string; + /** @description Can be used in tandem with the count calculation type, to count unique entries. */ + distinct?: boolean; + }; }; /** @description The ID of the view. */ id: string; @@ -1295,6 +1361,31 @@ export interface operations { }; }; }; + rowViewSearch: { + parameters: { + path: { + /** The ID of the view which this request is targeting. */ + viewId: components["parameters"]["viewId"]; + }; + header: { + /** The ID of the app which this request is targeting. */ + "x-budibase-app-id": components["parameters"]["appId"]; + }; + }; + responses: { + /** The response will contain an array of rows that match the search parameters. */ + 200: { + content: { + "application/json": components["schemas"]["searchOutput"]; + }; + }; + }; + requestBody: { + content: { + "application/json": components["schemas"]["rowSearch"]; + }; + }; + }; /** Create a table, this could be internal or external. */ tableCreate: { parameters: { From b3ee2660230f426489b9a6b49860e3af7a1f61a0 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 1 Nov 2024 17:53:26 +0000 Subject: [PATCH 10/88] Adding test case for creation, updating validator. --- .../src/api/controllers/public/views.ts | 3 + .../src/api/routes/public/tests/Request.ts | 82 ++++++++++++++++++- .../src/api/routes/public/tests/views.spec.ts | 32 ++++++++ .../server/src/api/routes/utils/validators.ts | 36 +++++++- 4 files changed, 145 insertions(+), 8 deletions(-) create mode 100644 packages/server/src/api/routes/public/tests/views.spec.ts diff --git a/packages/server/src/api/controllers/public/views.ts b/packages/server/src/api/controllers/public/views.ts index e400e850ea..135d3c0128 100644 --- a/packages/server/src/api/controllers/public/views.ts +++ b/packages/server/src/api/controllers/public/views.ts @@ -13,6 +13,9 @@ function fixView(view: ViewV2, params?: { viewId: string }) { if (!view.version) { view.version = 2 } + if (!view.query) { + view.query = {} + } return view } diff --git a/packages/server/src/api/routes/public/tests/Request.ts b/packages/server/src/api/routes/public/tests/Request.ts index 92a4996124..7b3c5b6e06 100644 --- a/packages/server/src/api/routes/public/tests/Request.ts +++ b/packages/server/src/api/routes/public/tests/Request.ts @@ -1,10 +1,19 @@ -import { User, Table, SearchFilters, Row } from "@budibase/types" +import { + User, + Table, + SearchFilters, + Row, + ViewV2Schema, + ViewV2, + ViewV2Type, +} from "@budibase/types" import { HttpMethod, MakeRequestResponse, generateMakeRequest } from "./utils" import TestConfiguration from "../../../../tests/utilities/TestConfiguration" -import { Expectations } from "../../../../tests/utilities/api/base" type RequestOpts = { internal?: boolean; appId?: string } +type Response = { data: T } + export interface PublicAPIExpectations { status?: number body?: Record @@ -15,6 +24,7 @@ export class PublicAPIRequest { private appId: string | undefined tables: PublicTableAPI + views: PublicViewAPI rows: PublicRowAPI apiKey: string @@ -28,6 +38,7 @@ export class PublicAPIRequest { this.appId = appId this.tables = new PublicTableAPI(this) this.rows = new PublicRowAPI(this) + this.views = new PublicViewAPI(this) } static async init(config: TestConfiguration, user: User, opts?: RequestOpts) { @@ -73,7 +84,7 @@ export class PublicTableAPI { async create( table: Table, expectations?: PublicAPIExpectations - ): Promise<{ data: Table }> { + ): Promise> { return this.request.send("post", "/tables", table, expectations) } } @@ -89,7 +100,7 @@ export class PublicRowAPI { tableId: string, query: SearchFilters, expectations?: PublicAPIExpectations - ): Promise<{ data: Row[] }> { + ): Promise> { return this.request.send( "post", `/tables/${tableId}/rows/search`, @@ -99,4 +110,67 @@ export class PublicRowAPI { expectations ) } + + async viewSearch( + viewId: string, + query: SearchFilters, + expectations?: PublicAPIExpectations + ): Promise> { + return this.request.send( + "post", + `/views/${viewId}/rows/search`, + { + query, + }, + expectations + ) + } +} + +export class PublicViewAPI { + request: PublicAPIRequest + + constructor(request: PublicAPIRequest) { + this.request = request + } + + async create( + view: Omit, + expectations?: PublicAPIExpectations + ): Promise> { + return this.request.send("post", "/views", view, expectations) + } + + async update( + viewId: string, + view: Omit, + expectations?: PublicAPIExpectations + ): Promise> { + return this.request.send("put", `/views/${viewId}`, view, expectations) + } + + async destroy( + viewId: string, + expectations?: PublicAPIExpectations + ): Promise { + return this.request.send( + "delete", + `/views/${viewId}`, + undefined, + expectations + ) + } + + async find( + viewId: string, + expectations?: PublicAPIExpectations + ): Promise> { + return this.request.send("get", `/views/${viewId}`, undefined, expectations) + } + + async fetch( + expectations?: PublicAPIExpectations + ): Promise> { + return this.request.send("get", "/views", undefined, expectations) + } } diff --git a/packages/server/src/api/routes/public/tests/views.spec.ts b/packages/server/src/api/routes/public/tests/views.spec.ts new file mode 100644 index 0000000000..dce2e1ab7a --- /dev/null +++ b/packages/server/src/api/routes/public/tests/views.spec.ts @@ -0,0 +1,32 @@ +import * as setup from "../../tests/utilities" +import { basicTable } from "../../../../tests/utilities/structures" +import { Table } from "@budibase/types" +import { PublicAPIRequest } from "./Request" + +describe("check public API security", () => { + const config = setup.getConfig() + let request: PublicAPIRequest, table: Table + + beforeAll(async () => { + await config.init() + request = await PublicAPIRequest.init(config, await config.globalUser()) + table = (await request.tables.create(basicTable())).data + }) + + it("should be able to create a view", async () => { + await request.views.create( + { + name: "view", + tableId: table._id!, + query: {}, + schema: { + name: { + readonly: true, + visible: true, + }, + }, + }, + { status: 201 } + ) + }) +}) diff --git a/packages/server/src/api/routes/utils/validators.ts b/packages/server/src/api/routes/utils/validators.ts index 68ebd72c5e..9bae8b64d9 100644 --- a/packages/server/src/api/routes/utils/validators.ts +++ b/packages/server/src/api/routes/utils/validators.ts @@ -9,6 +9,9 @@ import { Table, WebhookActionType, BuiltinPermissionID, + ViewV2Type, + SortOrder, + SortType, } from "@budibase/types" import Joi, { CustomValidator } from "joi" import { ValidSnippetNameRegex, helpers } from "@budibase/shared-core" @@ -67,7 +70,26 @@ export function tableValidator() { } export function viewValidator() { - return auth.joiValidator.body(Joi.object()) + return auth.joiValidator.body( + Joi.object({ + id: OPTIONAL_STRING, + tableId: Joi.string().required(), + name: Joi.string().required(), + type: Joi.string().optional().valid(null, ViewV2Type.CALCULATION), + primaryDisplay: OPTIONAL_STRING, + schema: Joi.object().required(), + query: searchFiltersValidator().optional(), + sort: Joi.object({ + field: Joi.string().required(), + order: Joi.string() + .optional() + .valid(...Object.values(SortOrder)), + type: Joi.string() + .optional() + .valid(...Object.values(SortType)), + }).optional(), + }) + ) } export function nameValidator() { @@ -95,8 +117,7 @@ export function datasourceValidator() { ) } -function filterObject(opts?: { unknown: boolean }) { - const { unknown = true } = opts || {} +function searchFiltersValidator() { const conditionalFilteringObject = () => Joi.object({ conditions: Joi.array().items(Joi.link("#schema")).required(), @@ -123,7 +144,14 @@ function filterObject(opts?: { unknown: boolean }) { fuzzyOr: Joi.forbidden(), documentType: Joi.forbidden(), } - return Joi.object(filtersValidators).unknown(unknown).id("schema") + + return Joi.object(filtersValidators) +} + +function filterObject(opts?: { unknown: boolean }) { + const { unknown = true } = opts || {} + + return searchFiltersValidator().unknown(unknown).id("schema") } export function internalSearchValidator() { From 6e5aab1f3f9269f5da24084ed204d5bcb6df3ae5 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 1 Nov 2024 17:53:38 +0000 Subject: [PATCH 11/88] Updating view definition to include complete query and sorting. --- packages/server/specs/openapi.json | 348 +++++++++++++++++++++ packages/server/specs/openapi.yaml | 301 ++++++++++++++++++ packages/server/specs/resources/misc.ts | 182 +++++------ packages/server/specs/resources/view.ts | 25 +- packages/server/src/definitions/openapi.ts | 174 +++++++++++ 5 files changed, 939 insertions(+), 91 deletions(-) diff --git a/packages/server/specs/openapi.json b/packages/server/specs/openapi.json index d45a8f28c9..fcabba8eba 100644 --- a/packages/server/specs/openapi.json +++ b/packages/server/specs/openapi.json @@ -2110,6 +2110,122 @@ "type": "string", "description": "A column used to display rows from this view - usually used when rendered in tables." }, + "query": { + "type": "object", + "properties": { + "allOr": { + "type": "boolean", + "description": "Specifies that a row should be returned if it satisfies any of the specified options, rather than requiring it to fulfill all the search parameters. This defaults to false, meaning AND logic will be used." + }, + "string": { + "type": "object", + "example": { + "columnName1": "value", + "columnName2": "value" + }, + "description": "A map of field name to the string to search for, this will look for rows that have a value starting with the string value.", + "additionalProperties": { + "type": "string", + "description": "The value to search for in the column." + } + }, + "fuzzy": { + "type": "object", + "description": "Searches for a sub-string within a string column, e.g. searching for 'dib' will match 'Budibase'." + }, + "range": { + "type": "object", + "description": "Searches within a range, the format of this must be in the format of an object with a \"low\" and \"high\" property.", + "example": { + "columnName1": { + "low": 10, + "high": 20 + } + } + }, + "equal": { + "type": "object", + "description": "Searches for rows that have a column value that is exactly the value set." + }, + "notEqual": { + "type": "object", + "description": "Searches for any row which does not contain the specified column value." + }, + "empty": { + "type": "object", + "description": "Searches for rows which do not contain the specified column. The object should simply contain keys of the column names, these can map to any value.", + "example": { + "columnName1": "" + } + }, + "notEmpty": { + "type": "object", + "description": "Searches for rows which have the specified column." + }, + "oneOf": { + "type": "object", + "description": "Searches for rows which have a column value that is any of the specified values. The format of this must be columnName -> [value1, value2]." + }, + "contains": { + "type": "object", + "description": "Searches for a value, or set of values in array column types (such as a multi-select). If an array of search options is provided then it must match all.", + "example": { + "arrayColumn": [ + "a", + "b" + ] + } + }, + "notContains": { + "type": "object", + "description": "The logical inverse of contains. Only works on array column types. If an array of values is passed, the row must not match any of them to be returned in the response.", + "example": { + "arrayColumn": [ + "a", + "b" + ] + } + }, + "containsAny": { + "type": "object", + "description": "As with the contains search, only works on array column types and searches for any of the provided values when given an array.", + "example": { + "arrayColumn": [ + "a", + "b" + ] + } + } + } + }, + "sort": { + "type": "object", + "required": [ + "field" + ], + "properties": { + "field": { + "type": "string", + "description": "The field from the table/view schema to sort on." + }, + "order": { + "type": "string", + "description": "The order in which to sort.", + "enum": [ + "ascending", + "descending" + ] + }, + "type": { + "type": "string", + "description": "The type of sort to perform (by number, or by alphabetically).", + "enum": [ + "string", + "number" + ] + } + } + }, "schema": { "type": "object", "additionalProperties": { @@ -2203,6 +2319,122 @@ "type": "string", "description": "A column used to display rows from this view - usually used when rendered in tables." }, + "query": { + "type": "object", + "properties": { + "allOr": { + "type": "boolean", + "description": "Specifies that a row should be returned if it satisfies any of the specified options, rather than requiring it to fulfill all the search parameters. This defaults to false, meaning AND logic will be used." + }, + "string": { + "type": "object", + "example": { + "columnName1": "value", + "columnName2": "value" + }, + "description": "A map of field name to the string to search for, this will look for rows that have a value starting with the string value.", + "additionalProperties": { + "type": "string", + "description": "The value to search for in the column." + } + }, + "fuzzy": { + "type": "object", + "description": "Searches for a sub-string within a string column, e.g. searching for 'dib' will match 'Budibase'." + }, + "range": { + "type": "object", + "description": "Searches within a range, the format of this must be in the format of an object with a \"low\" and \"high\" property.", + "example": { + "columnName1": { + "low": 10, + "high": 20 + } + } + }, + "equal": { + "type": "object", + "description": "Searches for rows that have a column value that is exactly the value set." + }, + "notEqual": { + "type": "object", + "description": "Searches for any row which does not contain the specified column value." + }, + "empty": { + "type": "object", + "description": "Searches for rows which do not contain the specified column. The object should simply contain keys of the column names, these can map to any value.", + "example": { + "columnName1": "" + } + }, + "notEmpty": { + "type": "object", + "description": "Searches for rows which have the specified column." + }, + "oneOf": { + "type": "object", + "description": "Searches for rows which have a column value that is any of the specified values. The format of this must be columnName -> [value1, value2]." + }, + "contains": { + "type": "object", + "description": "Searches for a value, or set of values in array column types (such as a multi-select). If an array of search options is provided then it must match all.", + "example": { + "arrayColumn": [ + "a", + "b" + ] + } + }, + "notContains": { + "type": "object", + "description": "The logical inverse of contains. Only works on array column types. If an array of values is passed, the row must not match any of them to be returned in the response.", + "example": { + "arrayColumn": [ + "a", + "b" + ] + } + }, + "containsAny": { + "type": "object", + "description": "As with the contains search, only works on array column types and searches for any of the provided values when given an array.", + "example": { + "arrayColumn": [ + "a", + "b" + ] + } + } + } + }, + "sort": { + "type": "object", + "required": [ + "field" + ], + "properties": { + "field": { + "type": "string", + "description": "The field from the table/view schema to sort on." + }, + "order": { + "type": "string", + "description": "The order in which to sort.", + "enum": [ + "ascending", + "descending" + ] + }, + "type": { + "type": "string", + "description": "The type of sort to perform (by number, or by alphabetically).", + "enum": [ + "string", + "number" + ] + } + } + }, "schema": { "type": "object", "additionalProperties": { @@ -2307,6 +2539,122 @@ "type": "string", "description": "A column used to display rows from this view - usually used when rendered in tables." }, + "query": { + "type": "object", + "properties": { + "allOr": { + "type": "boolean", + "description": "Specifies that a row should be returned if it satisfies any of the specified options, rather than requiring it to fulfill all the search parameters. This defaults to false, meaning AND logic will be used." + }, + "string": { + "type": "object", + "example": { + "columnName1": "value", + "columnName2": "value" + }, + "description": "A map of field name to the string to search for, this will look for rows that have a value starting with the string value.", + "additionalProperties": { + "type": "string", + "description": "The value to search for in the column." + } + }, + "fuzzy": { + "type": "object", + "description": "Searches for a sub-string within a string column, e.g. searching for 'dib' will match 'Budibase'." + }, + "range": { + "type": "object", + "description": "Searches within a range, the format of this must be in the format of an object with a \"low\" and \"high\" property.", + "example": { + "columnName1": { + "low": 10, + "high": 20 + } + } + }, + "equal": { + "type": "object", + "description": "Searches for rows that have a column value that is exactly the value set." + }, + "notEqual": { + "type": "object", + "description": "Searches for any row which does not contain the specified column value." + }, + "empty": { + "type": "object", + "description": "Searches for rows which do not contain the specified column. The object should simply contain keys of the column names, these can map to any value.", + "example": { + "columnName1": "" + } + }, + "notEmpty": { + "type": "object", + "description": "Searches for rows which have the specified column." + }, + "oneOf": { + "type": "object", + "description": "Searches for rows which have a column value that is any of the specified values. The format of this must be columnName -> [value1, value2]." + }, + "contains": { + "type": "object", + "description": "Searches for a value, or set of values in array column types (such as a multi-select). If an array of search options is provided then it must match all.", + "example": { + "arrayColumn": [ + "a", + "b" + ] + } + }, + "notContains": { + "type": "object", + "description": "The logical inverse of contains. Only works on array column types. If an array of values is passed, the row must not match any of them to be returned in the response.", + "example": { + "arrayColumn": [ + "a", + "b" + ] + } + }, + "containsAny": { + "type": "object", + "description": "As with the contains search, only works on array column types and searches for any of the provided values when given an array.", + "example": { + "arrayColumn": [ + "a", + "b" + ] + } + } + } + }, + "sort": { + "type": "object", + "required": [ + "field" + ], + "properties": { + "field": { + "type": "string", + "description": "The field from the table/view schema to sort on." + }, + "order": { + "type": "string", + "description": "The order in which to sort.", + "enum": [ + "ascending", + "descending" + ] + }, + "type": { + "type": "string", + "description": "The type of sort to perform (by number, or by alphabetically).", + "enum": [ + "string", + "number" + ] + } + } + }, "schema": { "type": "object", "additionalProperties": { diff --git a/packages/server/specs/openapi.yaml b/packages/server/specs/openapi.yaml index 0e551207ed..4d2a4fc5bd 100644 --- a/packages/server/specs/openapi.yaml +++ b/packages/server/specs/openapi.yaml @@ -1767,6 +1767,106 @@ components: type: string description: A column used to display rows from this view - usually used when rendered in tables. + query: + type: object + properties: + allOr: + type: boolean + description: Specifies that a row should be returned if it satisfies any of the + specified options, rather than requiring it to fulfill all the + search parameters. This defaults to false, meaning AND logic + will be used. + string: + type: object + example: + columnName1: value + columnName2: value + description: A map of field name to the string to search for, this will look for + rows that have a value starting with the string value. + additionalProperties: + type: string + description: The value to search for in the column. + fuzzy: + type: object + description: Searches for a sub-string within a string column, e.g. searching + for 'dib' will match 'Budibase'. + range: + type: object + description: Searches within a range, the format of this must be in the format + of an object with a "low" and "high" property. + example: + columnName1: + low: 10 + high: 20 + equal: + type: object + description: Searches for rows that have a column value that is exactly the + value set. + notEqual: + type: object + description: Searches for any row which does not contain the specified column + value. + empty: + type: object + description: Searches for rows which do not contain the specified column. The + object should simply contain keys of the column names, these can + map to any value. + example: + columnName1: "" + notEmpty: + type: object + description: Searches for rows which have the specified column. + oneOf: + type: object + description: Searches for rows which have a column value that is any of the + specified values. The format of this must be columnName -> + [value1, value2]. + contains: + type: object + description: Searches for a value, or set of values in array column types (such + as a multi-select). If an array of search options is provided + then it must match all. + example: + arrayColumn: + - a + - b + notContains: + type: object + description: The logical inverse of contains. Only works on array column types. + If an array of values is passed, the row must not match any of + them to be returned in the response. + example: + arrayColumn: + - a + - b + containsAny: + type: object + description: As with the contains search, only works on array column types and + searches for any of the provided values when given an array. + example: + arrayColumn: + - a + - b + sort: + type: object + required: + - field + properties: + field: + type: string + description: The field from the table/view schema to sort on. + order: + type: string + description: The order in which to sort. + enum: + - ascending + - descending + type: + type: string + description: The type of sort to perform (by number, or by alphabetically). + enum: + - string + - number schema: type: object additionalProperties: @@ -1843,6 +1943,106 @@ components: type: string description: A column used to display rows from this view - usually used when rendered in tables. + query: + type: object + properties: + allOr: + type: boolean + description: Specifies that a row should be returned if it satisfies any of the + specified options, rather than requiring it to fulfill all + the search parameters. This defaults to false, meaning AND + logic will be used. + string: + type: object + example: + columnName1: value + columnName2: value + description: A map of field name to the string to search for, this will look for + rows that have a value starting with the string value. + additionalProperties: + type: string + description: The value to search for in the column. + fuzzy: + type: object + description: Searches for a sub-string within a string column, e.g. searching + for 'dib' will match 'Budibase'. + range: + type: object + description: Searches within a range, the format of this must be in the format + of an object with a "low" and "high" property. + example: + columnName1: + low: 10 + high: 20 + equal: + type: object + description: Searches for rows that have a column value that is exactly the + value set. + notEqual: + type: object + description: Searches for any row which does not contain the specified column + value. + empty: + type: object + description: Searches for rows which do not contain the specified column. The + object should simply contain keys of the column names, these + can map to any value. + example: + columnName1: "" + notEmpty: + type: object + description: Searches for rows which have the specified column. + oneOf: + type: object + description: Searches for rows which have a column value that is any of the + specified values. The format of this must be columnName -> + [value1, value2]. + contains: + type: object + description: Searches for a value, or set of values in array column types (such + as a multi-select). If an array of search options is + provided then it must match all. + example: + arrayColumn: + - a + - b + notContains: + type: object + description: The logical inverse of contains. Only works on array column types. + If an array of values is passed, the row must not match any + of them to be returned in the response. + example: + arrayColumn: + - a + - b + containsAny: + type: object + description: As with the contains search, only works on array column types and + searches for any of the provided values when given an array. + example: + arrayColumn: + - a + - b + sort: + type: object + required: + - field + properties: + field: + type: string + description: The field from the table/view schema to sort on. + order: + type: string + description: The order in which to sort. + enum: + - ascending + - descending + type: + type: string + description: The type of sort to perform (by number, or by alphabetically). + enum: + - string + - number schema: type: object additionalProperties: @@ -1926,6 +2126,107 @@ components: type: string description: A column used to display rows from this view - usually used when rendered in tables. + query: + type: object + properties: + allOr: + type: boolean + description: Specifies that a row should be returned if it satisfies any of the + specified options, rather than requiring it to fulfill all + the search parameters. This defaults to false, meaning AND + logic will be used. + string: + type: object + example: + columnName1: value + columnName2: value + description: A map of field name to the string to search for, this will look for + rows that have a value starting with the string value. + additionalProperties: + type: string + description: The value to search for in the column. + fuzzy: + type: object + description: Searches for a sub-string within a string column, e.g. searching + for 'dib' will match 'Budibase'. + range: + type: object + description: Searches within a range, the format of this must be in the format + of an object with a "low" and "high" property. + example: + columnName1: + low: 10 + high: 20 + equal: + type: object + description: Searches for rows that have a column value that is exactly the + value set. + notEqual: + type: object + description: Searches for any row which does not contain the specified column + value. + empty: + type: object + description: Searches for rows which do not contain the specified column. The + object should simply contain keys of the column names, + these can map to any value. + example: + columnName1: "" + notEmpty: + type: object + description: Searches for rows which have the specified column. + oneOf: + type: object + description: Searches for rows which have a column value that is any of the + specified values. The format of this must be columnName -> + [value1, value2]. + contains: + type: object + description: Searches for a value, or set of values in array column types (such + as a multi-select). If an array of search options is + provided then it must match all. + example: + arrayColumn: + - a + - b + notContains: + type: object + description: The logical inverse of contains. Only works on array column types. + If an array of values is passed, the row must not match + any of them to be returned in the response. + example: + arrayColumn: + - a + - b + containsAny: + type: object + description: As with the contains search, only works on array column types and + searches for any of the provided values when given an + array. + example: + arrayColumn: + - a + - b + sort: + type: object + required: + - field + properties: + field: + type: string + description: The field from the table/view schema to sort on. + order: + type: string + description: The order in which to sort. + enum: + - ascending + - descending + type: + type: string + description: The type of sort to perform (by number, or by alphabetically). + enum: + - string + - number schema: type: object additionalProperties: diff --git a/packages/server/specs/resources/misc.ts b/packages/server/specs/resources/misc.ts index f56dff3301..8f77d2b22a 100644 --- a/packages/server/specs/resources/misc.ts +++ b/packages/server/specs/resources/misc.ts @@ -1,99 +1,101 @@ import { object } from "./utils" import Resource from "./utils/Resource" +export const searchSchema = { + type: "object", + properties: { + allOr: { + type: "boolean", + description: + "Specifies that a row should be returned if it satisfies any of the specified options, rather than requiring it to fulfill all the search parameters. This defaults to false, meaning AND logic will be used.", + }, + string: { + type: "object", + example: { + columnName1: "value", + columnName2: "value", + }, + description: + "A map of field name to the string to search for, this will look for rows that have a value starting with the string value.", + additionalProperties: { + type: "string", + description: "The value to search for in the column.", + }, + }, + fuzzy: { + type: "object", + description: + "Searches for a sub-string within a string column, e.g. searching for 'dib' will match 'Budibase'.", + }, + range: { + type: "object", + description: + 'Searches within a range, the format of this must be in the format of an object with a "low" and "high" property.', + example: { + columnName1: { + low: 10, + high: 20, + }, + }, + }, + equal: { + type: "object", + description: + "Searches for rows that have a column value that is exactly the value set.", + }, + notEqual: { + type: "object", + description: + "Searches for any row which does not contain the specified column value.", + }, + empty: { + type: "object", + description: + "Searches for rows which do not contain the specified column. The object should simply contain keys of the column names, these can map to any value.", + example: { + columnName1: "", + }, + }, + notEmpty: { + type: "object", + description: "Searches for rows which have the specified column.", + }, + oneOf: { + type: "object", + description: + "Searches for rows which have a column value that is any of the specified values. The format of this must be columnName -> [value1, value2].", + }, + contains: { + type: "object", + description: + "Searches for a value, or set of values in array column types (such as a multi-select). If an array of search options is provided then it must match all.", + example: { + arrayColumn: ["a", "b"], + }, + }, + notContains: { + type: "object", + description: + "The logical inverse of contains. Only works on array column types. If an array of values is passed, the row must not match any of them to be returned in the response.", + example: { + arrayColumn: ["a", "b"], + }, + }, + containsAny: { + type: "object", + description: + "As with the contains search, only works on array column types and searches for any of the provided values when given an array.", + example: { + arrayColumn: ["a", "b"], + }, + }, + }, +} + export default new Resource().setSchemas({ rowSearch: object( { - query: { - type: "object", - properties: { - allOr: { - type: "boolean", - description: - "Specifies that a row should be returned if it satisfies any of the specified options, rather than requiring it to fulfill all the search parameters. This defaults to false, meaning AND logic will be used.", - }, - string: { - type: "object", - example: { - columnName1: "value", - columnName2: "value", - }, - description: - "A map of field name to the string to search for, this will look for rows that have a value starting with the string value.", - additionalProperties: { - type: "string", - description: "The value to search for in the column.", - }, - }, - fuzzy: { - type: "object", - description: - "Searches for a sub-string within a string column, e.g. searching for 'dib' will match 'Budibase'.", - }, - range: { - type: "object", - description: - 'Searches within a range, the format of this must be in the format of an object with a "low" and "high" property.', - example: { - columnName1: { - low: 10, - high: 20, - }, - }, - }, - equal: { - type: "object", - description: - "Searches for rows that have a column value that is exactly the value set.", - }, - notEqual: { - type: "object", - description: - "Searches for any row which does not contain the specified column value.", - }, - empty: { - type: "object", - description: - "Searches for rows which do not contain the specified column. The object should simply contain keys of the column names, these can map to any value.", - example: { - columnName1: "", - }, - }, - notEmpty: { - type: "object", - description: "Searches for rows which have the specified column.", - }, - oneOf: { - type: "object", - description: - "Searches for rows which have a column value that is any of the specified values. The format of this must be columnName -> [value1, value2].", - }, - contains: { - type: "object", - description: - "Searches for a value, or set of values in array column types (such as a multi-select). If an array of search options is provided then it must match all.", - example: { - arrayColumn: ["a", "b"], - }, - }, - notContains: { - type: "object", - description: - "The logical inverse of contains. Only works on array column types. If an array of values is passed, the row must not match any of them to be returned in the response.", - example: { - arrayColumn: ["a", "b"], - }, - }, - containsAny: { - type: "object", - description: - "As with the contains search, only works on array column types and searches for any of the provided values when given an array.", - example: { - arrayColumn: ["a", "b"], - }, - }, - }, - }, + query: searchSchema, paginate: { type: "boolean", description: "Enables pagination, by default this is disabled.", diff --git a/packages/server/specs/resources/view.ts b/packages/server/specs/resources/view.ts index e798883ced..364e7badd2 100644 --- a/packages/server/specs/resources/view.ts +++ b/packages/server/specs/resources/view.ts @@ -1,6 +1,7 @@ import { object } from "./utils" import Resource from "./utils/Resource" -import { CalculationType } from "@budibase/types" +import { CalculationType, SortOrder, SortType } from "@budibase/types" +import { searchSchema } from "./misc" const view = { name: "peopleView", @@ -81,6 +82,28 @@ const viewSchema = { description: "A column used to display rows from this view - usually used when rendered in tables.", }, + query: searchSchema, + sort: { + type: "object", + required: ["field"], + properties: { + field: { + type: "string", + description: "The field from the table/view schema to sort on.", + }, + order: { + type: "string", + description: "The order in which to sort.", + enum: Object.values(SortOrder), + }, + type: { + type: "string", + description: + "The type of sort to perform (by number, or by alphabetically).", + enum: Object.values(SortType), + }, + }, + }, schema: { type: "object", additionalProperties: { diff --git a/packages/server/src/definitions/openapi.ts b/packages/server/src/definitions/openapi.ts index fed19ec5cf..6f53df0ab5 100644 --- a/packages/server/src/definitions/openapi.ts +++ b/packages/server/src/definitions/openapi.ts @@ -843,6 +843,64 @@ export interface components { type?: "calculation"; /** @description A column used to display rows from this view - usually used when rendered in tables. */ primaryDisplay?: string; + query?: { + /** @description Specifies that a row should be returned if it satisfies any of the specified options, rather than requiring it to fulfill all the search parameters. This defaults to false, meaning AND logic will be used. */ + allOr?: boolean; + /** + * @description A map of field name to the string to search for, this will look for rows that have a value starting with the string value. + * @example [object Object] + */ + string?: { [key: string]: string }; + /** @description Searches for a sub-string within a string column, e.g. searching for 'dib' will match 'Budibase'. */ + fuzzy?: { [key: string]: unknown }; + /** + * @description Searches within a range, the format of this must be in the format of an object with a "low" and "high" property. + * @example [object Object] + */ + range?: { [key: string]: unknown }; + /** @description Searches for rows that have a column value that is exactly the value set. */ + equal?: { [key: string]: unknown }; + /** @description Searches for any row which does not contain the specified column value. */ + notEqual?: { [key: string]: unknown }; + /** + * @description Searches for rows which do not contain the specified column. The object should simply contain keys of the column names, these can map to any value. + * @example [object Object] + */ + empty?: { [key: string]: unknown }; + /** @description Searches for rows which have the specified column. */ + notEmpty?: { [key: string]: unknown }; + /** @description Searches for rows which have a column value that is any of the specified values. The format of this must be columnName -> [value1, value2]. */ + oneOf?: { [key: string]: unknown }; + /** + * @description Searches for a value, or set of values in array column types (such as a multi-select). If an array of search options is provided then it must match all. + * @example [object Object] + */ + contains?: { [key: string]: unknown }; + /** + * @description The logical inverse of contains. Only works on array column types. If an array of values is passed, the row must not match any of them to be returned in the response. + * @example [object Object] + */ + notContains?: { [key: string]: unknown }; + /** + * @description As with the contains search, only works on array column types and searches for any of the provided values when given an array. + * @example [object Object] + */ + containsAny?: { [key: string]: unknown }; + }; + sort?: { + /** @description The field from the table/view schema to sort on. */ + field: string; + /** + * @description The order in which to sort. + * @enum {string} + */ + order?: "ascending" | "descending"; + /** + * @description The type of sort to perform (by number, or by alphabetically). + * @enum {string} + */ + type?: "string" | "number"; + }; schema: { [key: string]: | { @@ -884,6 +942,64 @@ export interface components { type?: "calculation"; /** @description A column used to display rows from this view - usually used when rendered in tables. */ primaryDisplay?: string; + query?: { + /** @description Specifies that a row should be returned if it satisfies any of the specified options, rather than requiring it to fulfill all the search parameters. This defaults to false, meaning AND logic will be used. */ + allOr?: boolean; + /** + * @description A map of field name to the string to search for, this will look for rows that have a value starting with the string value. + * @example [object Object] + */ + string?: { [key: string]: string }; + /** @description Searches for a sub-string within a string column, e.g. searching for 'dib' will match 'Budibase'. */ + fuzzy?: { [key: string]: unknown }; + /** + * @description Searches within a range, the format of this must be in the format of an object with a "low" and "high" property. + * @example [object Object] + */ + range?: { [key: string]: unknown }; + /** @description Searches for rows that have a column value that is exactly the value set. */ + equal?: { [key: string]: unknown }; + /** @description Searches for any row which does not contain the specified column value. */ + notEqual?: { [key: string]: unknown }; + /** + * @description Searches for rows which do not contain the specified column. The object should simply contain keys of the column names, these can map to any value. + * @example [object Object] + */ + empty?: { [key: string]: unknown }; + /** @description Searches for rows which have the specified column. */ + notEmpty?: { [key: string]: unknown }; + /** @description Searches for rows which have a column value that is any of the specified values. The format of this must be columnName -> [value1, value2]. */ + oneOf?: { [key: string]: unknown }; + /** + * @description Searches for a value, or set of values in array column types (such as a multi-select). If an array of search options is provided then it must match all. + * @example [object Object] + */ + contains?: { [key: string]: unknown }; + /** + * @description The logical inverse of contains. Only works on array column types. If an array of values is passed, the row must not match any of them to be returned in the response. + * @example [object Object] + */ + notContains?: { [key: string]: unknown }; + /** + * @description As with the contains search, only works on array column types and searches for any of the provided values when given an array. + * @example [object Object] + */ + containsAny?: { [key: string]: unknown }; + }; + sort?: { + /** @description The field from the table/view schema to sort on. */ + field: string; + /** + * @description The order in which to sort. + * @enum {string} + */ + order?: "ascending" | "descending"; + /** + * @description The type of sort to perform (by number, or by alphabetically). + * @enum {string} + */ + type?: "string" | "number"; + }; schema: { [key: string]: | { @@ -927,6 +1043,64 @@ export interface components { type?: "calculation"; /** @description A column used to display rows from this view - usually used when rendered in tables. */ primaryDisplay?: string; + query?: { + /** @description Specifies that a row should be returned if it satisfies any of the specified options, rather than requiring it to fulfill all the search parameters. This defaults to false, meaning AND logic will be used. */ + allOr?: boolean; + /** + * @description A map of field name to the string to search for, this will look for rows that have a value starting with the string value. + * @example [object Object] + */ + string?: { [key: string]: string }; + /** @description Searches for a sub-string within a string column, e.g. searching for 'dib' will match 'Budibase'. */ + fuzzy?: { [key: string]: unknown }; + /** + * @description Searches within a range, the format of this must be in the format of an object with a "low" and "high" property. + * @example [object Object] + */ + range?: { [key: string]: unknown }; + /** @description Searches for rows that have a column value that is exactly the value set. */ + equal?: { [key: string]: unknown }; + /** @description Searches for any row which does not contain the specified column value. */ + notEqual?: { [key: string]: unknown }; + /** + * @description Searches for rows which do not contain the specified column. The object should simply contain keys of the column names, these can map to any value. + * @example [object Object] + */ + empty?: { [key: string]: unknown }; + /** @description Searches for rows which have the specified column. */ + notEmpty?: { [key: string]: unknown }; + /** @description Searches for rows which have a column value that is any of the specified values. The format of this must be columnName -> [value1, value2]. */ + oneOf?: { [key: string]: unknown }; + /** + * @description Searches for a value, or set of values in array column types (such as a multi-select). If an array of search options is provided then it must match all. + * @example [object Object] + */ + contains?: { [key: string]: unknown }; + /** + * @description The logical inverse of contains. Only works on array column types. If an array of values is passed, the row must not match any of them to be returned in the response. + * @example [object Object] + */ + notContains?: { [key: string]: unknown }; + /** + * @description As with the contains search, only works on array column types and searches for any of the provided values when given an array. + * @example [object Object] + */ + containsAny?: { [key: string]: unknown }; + }; + sort?: { + /** @description The field from the table/view schema to sort on. */ + field: string; + /** + * @description The order in which to sort. + * @enum {string} + */ + order?: "ascending" | "descending"; + /** + * @description The type of sort to perform (by number, or by alphabetically). + * @enum {string} + */ + type?: "string" | "number"; + }; schema: { [key: string]: | { From af30548f50c997af5e894ed29a6923cf9ad2a3cd Mon Sep 17 00:00:00 2001 From: Christian Struck Date: Wed, 6 Nov 2024 13:44:42 +0100 Subject: [PATCH 12/88] fix helm chart secret to correctly reapply the existing secret --- charts/budibase/templates/secrets.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/charts/budibase/templates/secrets.yaml b/charts/budibase/templates/secrets.yaml index a44d2c0d9b..20701d4125 100644 --- a/charts/budibase/templates/secrets.yaml +++ b/charts/budibase/templates/secrets.yaml @@ -12,12 +12,12 @@ metadata: type: Opaque data: {{- if $existingSecret }} - internalApiKey: {{ index $existingSecret.data "internalApiKey" }} - jwtSecret: {{ index $existingSecret.data "jwtSecret" }} - objectStoreAccess: {{ index $existingSecret.data "objectStoreAccess" }} - objectStoreSecret: {{ index $existingSecret.data "objectStoreSecret" }} - bbEncryptionKey: {{ index $existingSecret.data "bbEncryptionKey" }} - apiEncryptionKey: {{ index $existingSecret.data "apiEncryptionKey" }} + internalApiKey: {{ index $existingSecret.data "internalApiKey" | quote }} + jwtSecret: {{ index $existingSecret.data "jwtSecret" | quote }} + objectStoreAccess: {{ index $existingSecret.data "objectStoreAccess" | quote }} + objectStoreSecret: {{ index $existingSecret.data "objectStoreSecret" | quote }} + bbEncryptionKey: {{ index $existingSecret.data "bbEncryptionKey" | quote }} + apiEncryptionKey: {{ index $existingSecret.data "apiEncryptionKey" | quote }} {{- else }} internalApiKey: {{ template "budibase.defaultsecret" .Values.globals.internalApiKey }} jwtSecret: {{ template "budibase.defaultsecret" .Values.globals.jwtSecret }} From 26956f4f2e38c854831369b582bb77d3361d2671 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Thu, 7 Nov 2024 15:57:46 +0000 Subject: [PATCH 13/88] Allow using fields without forms and enable standalone mode for text and options fields --- packages/client/manifest.json | 26 ++++- .../src/components/app/forms/Field.svelte | 103 ++++++++++-------- .../src/components/app/forms/Form.svelte | 3 - .../src/components/app/forms/InnerForm.svelte | 14 ++- 4 files changed, 94 insertions(+), 52 deletions(-) diff --git a/packages/client/manifest.json b/packages/client/manifest.json index 393c08a282..0feac0ee80 100644 --- a/packages/client/manifest.json +++ b/packages/client/manifest.json @@ -3096,7 +3096,6 @@ "name": "Text Field", "icon": "Text", "styles": ["size"], - "requiredAncestors": ["form"], "editable": true, "size": { "width": 400, @@ -3226,7 +3225,17 @@ } ] } - ] + ], + "context": { + "type": "static", + "values": [ + { + "label": "Value", + "key": "value", + "type": "string" + } + ] + } }, "numberfield": { "name": "Number Field", @@ -3506,7 +3515,6 @@ "name": "Options Picker", "icon": "Menu", "styles": ["size"], - "requiredAncestors": ["form"], "editable": true, "size": { "width": 400, @@ -3714,7 +3722,17 @@ } ] } - ] + ], + "context": { + "type": "static", + "values": [ + { + "label": "Value", + "key": "value", + "type": "string" + } + ] + } }, "multifieldselect": { "name": "Multi-select Picker", diff --git a/packages/client/src/components/app/forms/Field.svelte b/packages/client/src/components/app/forms/Field.svelte index 9210b6ea8f..846bfa6eef 100644 --- a/packages/client/src/components/app/forms/Field.svelte +++ b/packages/client/src/components/app/forms/Field.svelte @@ -2,6 +2,9 @@ import Placeholder from "../Placeholder.svelte" import { getContext, onDestroy } from "svelte" import { Icon } from "@budibase/bbui" + import InnerForm from "./InnerForm.svelte" + import { writable } from "svelte/store" + import Provider from "components/context/Provider.svelte" export let label export let field @@ -71,52 +74,66 @@ }) -
- {#key $component.editing} - - {/key} -
- {#if !formContext} - - {:else if !fieldState} - - {:else if schemaType && schemaType !== type && !["options", "longform"].includes(type)} - - {:else} - - {#if fieldState.error} -
- - {fieldState.error} -
- {:else if helpText} -
- {helpText} -
+ + + + + +{:else} +
+ {#key $component.editing} + + {/key} +
+ {#if !fieldState} + + {:else if schemaType && schemaType !== type && !["options", "longform"].includes(type)} + + {:else} + + {#if fieldState.error} +
+ + {fieldState.error} +
+ {:else if helpText} +
+ {helpText} +
+ {/if} {/if} - {/if} +
-
+{/if} diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/DNDPositionIndicator.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/DNDPositionIndicator.svelte index 4612440a2c..45185d8e2d 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/DNDPositionIndicator.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/ComponentList/DNDPositionIndicator.svelte @@ -50,8 +50,6 @@ border-radius: 4px; pointer-events: none; } - .indicator.above { - } .indicator.below { margin-top: 32px; } From 013f2a6dce8edede978c54e9de824f9c8afeba7d Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 26 Nov 2024 10:53:08 +0100 Subject: [PATCH 62/88] Enable typescript files --- packages/builder/package.json | 1 + packages/builder/vite.config.mjs | 4 +- yarn.lock | 334 ++++++++++++------------------- 3 files changed, 130 insertions(+), 209 deletions(-) diff --git a/packages/builder/package.json b/packages/builder/package.json index fd819b8a9c..5b3d4413cf 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -89,6 +89,7 @@ "@babel/plugin-transform-runtime": "^7.13.10", "@babel/preset-env": "^7.13.12", "@rollup/plugin-replace": "^5.0.3", + "@rollup/plugin-typescript": "8.3.0", "@roxi/routify": "2.18.12", "@sveltejs/vite-plugin-svelte": "1.4.0", "@testing-library/jest-dom": "6.4.2", diff --git a/packages/builder/vite.config.mjs b/packages/builder/vite.config.mjs index f5ff388952..ccc5729d28 100644 --- a/packages/builder/vite.config.mjs +++ b/packages/builder/vite.config.mjs @@ -3,6 +3,7 @@ import replace from "@rollup/plugin-replace" import { defineConfig, loadEnv } from "vite" import { viteStaticCopy } from "vite-plugin-static-copy" import path from "path" +import typescript from "@rollup/plugin-typescript" const ignoredWarnings = [ "unused-export-let", @@ -35,7 +36,7 @@ export default defineConfig(({ mode }) => { // Copy fonts to an additional path so that svelte's automatic // prefixing of the base URL path can still resolve assets copyFonts("builder/fonts"), -] + ] return { test: { @@ -61,6 +62,7 @@ export default defineConfig(({ mode }) => { sourcemap: !isProduction, }, plugins: [ + typescript({ outDir: "../server/builder/dist" }), svelte({ hot: !isProduction, emitCss: true, diff --git a/yarn.lock b/yarn.lock index dd01832bba..dcaab4e315 100644 --- a/yarn.lock +++ b/yarn.lock @@ -842,7 +842,7 @@ "@azure/abort-controller" "^2.0.0" tslib "^2.6.2" -"@azure/identity@4.2.1", "@azure/identity@^4.2.1": +"@azure/identity@^4.2.1": version "4.2.1" resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-4.2.1.tgz#22b366201e989b7b41c0e1690e103bd579c31e4c" integrity sha512-U8hsyC9YPcEIzoaObJlRDvp7KiF0MGS7xcWbyJSVvXRkC/HXo1f0oYeBYmEvVgRfacw7GHf6D6yAoh9JHz6A5Q== @@ -2196,47 +2196,6 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@budibase/backend-core@3.2.11": - version "0.0.0" - dependencies: - "@budibase/nano" "10.1.5" - "@budibase/pouchdb-replication-stream" "1.2.11" - "@budibase/shared-core" "0.0.0" - "@budibase/types" "0.0.0" - "@techpass/passport-openidconnect" "0.3.3" - aws-cloudfront-sign "3.0.2" - aws-sdk "2.1692.0" - bcrypt "5.1.0" - bcryptjs "2.4.3" - bull "4.10.1" - correlation-id "4.0.0" - dd-trace "5.26.0" - dotenv "16.0.1" - google-auth-library "^8.0.1" - google-spreadsheet "npm:@budibase/google-spreadsheet@4.1.5" - ioredis "5.3.2" - joi "17.6.0" - jsonwebtoken "9.0.2" - knex "2.4.2" - koa-passport "^6.0.0" - koa-pino-logger "4.0.0" - lodash "4.17.21" - node-fetch "2.6.7" - passport-google-oauth "2.0.0" - passport-local "1.0.0" - passport-oauth2-refresh "^2.1.0" - pino "8.11.0" - pino-http "8.3.3" - posthog-node "4.0.1" - pouchdb "9.0.0" - pouchdb-find "9.0.0" - redlock "4.2.0" - rotating-file-stream "3.1.0" - sanitize-s3-objectkey "0.0.1" - semver "^7.5.4" - tar-fs "2.1.1" - uuid "^8.3.2" - "@budibase/handlebars-helpers@^0.13.2": version "0.13.2" resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.13.2.tgz#73ab51c464e91fd955b429017648e0257060db77" @@ -2279,47 +2238,6 @@ pouchdb-promise "^6.0.4" through2 "^2.0.0" -"@budibase/pro@npm:@budibase/pro@latest": - version "3.2.11" - resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-3.2.11.tgz#40d4929b3958dacca3f4c207718a4647c08a6100" - integrity sha512-xE1tx/C2cnbyR4s/6XkkweoQw6CW5fsQt++gzrrML8abgsODru+tA7M2NbWlKsEnVWHDQRvUVcXm4wqDeNNZ9g== - dependencies: - "@anthropic-ai/sdk" "^0.27.3" - "@budibase/backend-core" "3.2.11" - "@budibase/shared-core" "3.2.11" - "@budibase/string-templates" "3.2.11" - "@budibase/types" "3.2.11" - "@koa/router" "13.1.0" - bull "4.10.1" - dd-trace "5.23.0" - joi "17.6.0" - jsonwebtoken "9.0.2" - lru-cache "^7.14.1" - memorystream "^0.3.1" - node-fetch "2.6.7" - openai "4.59.0" - scim-patch "^0.8.1" - scim2-parse-filter "^0.2.8" - -"@budibase/shared-core@3.2.11": - version "0.0.0" - dependencies: - "@budibase/types" "0.0.0" - cron-validate "1.4.5" - -"@budibase/string-templates@3.2.11": - version "0.0.0" - dependencies: - "@budibase/handlebars-helpers" "^0.13.2" - dayjs "^1.10.8" - handlebars "^4.7.8" - lodash.clonedeep "^4.5.0" - -"@budibase/types@3.2.11": - version "0.0.0" - dependencies: - scim-patch "^0.8.1" - "@bull-board/api@5.10.2": version "5.10.2" resolved "https://registry.yarnpkg.com/@bull-board/api/-/api-5.10.2.tgz#ae8ff6918b23897bf879a6ead3683f964374c4b3" @@ -2482,13 +2400,6 @@ resolved "https://registry.yarnpkg.com/@datadog/libdatadog/-/libdatadog-0.2.2.tgz#ac02c76ac9a38250dca740727c7cdf00244ce3d3" integrity sha512-rTWo96mEPTY5UbtGoFj8/wY0uKSViJhsPg/Z6aoFWBFXQ8b45Ix2e/yvf92AAwrhG+gPLTxEqTXh3kef2dP8Ow== -"@datadog/native-appsec@8.1.1": - version "8.1.1" - resolved "https://registry.yarnpkg.com/@datadog/native-appsec/-/native-appsec-8.1.1.tgz#76aa34697e6ecbd3d9ef7e6938d3cdcfa689b1f3" - integrity sha512-mf+Ym/AzET4FeUTXOs8hz0uLOSsVIUnavZPUx8YoKWK5lKgR2L+CLfEzOpjBwgFpDgbV8I1/vyoGelgGpsMKHA== - dependencies: - node-gyp-build "^3.9.0" - "@datadog/native-appsec@8.3.0": version "8.3.0" resolved "https://registry.yarnpkg.com/@datadog/native-appsec/-/native-appsec-8.3.0.tgz#91afd89d18d386be4da8a1b0e04500f2f8b5eb66" @@ -2496,14 +2407,6 @@ dependencies: node-gyp-build "^3.9.0" -"@datadog/native-iast-rewriter@2.4.1": - version "2.4.1" - resolved "https://registry.yarnpkg.com/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.4.1.tgz#e8211f78c818906513fb96a549374da0382c7623" - integrity sha512-j3auTmyyn63e2y+SL28CGNy/l+jXQyh+pxqoGTacWaY5FW/dvo5nGQepAismgJ3qJ8VhQfVWRdxBSiT7wu9clw== - dependencies: - lru-cache "^7.14.0" - node-gyp-build "^4.5.0" - "@datadog/native-iast-rewriter@2.5.0": version "2.5.0" resolved "https://registry.yarnpkg.com/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.5.0.tgz#b613defe86e78168f750d1f1662d4ffb3cf002e6" @@ -2512,13 +2415,6 @@ lru-cache "^7.14.0" node-gyp-build "^4.5.0" -"@datadog/native-iast-taint-tracking@3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-3.1.0.tgz#7b2ed7f8fad212d65e5ab03bcdea8b42a3051b2e" - integrity sha512-rw6qSjmxmu1yFHVvZLXFt/rVq2tUZXocNogPLB8n7MPpA0jijNGb109WokWw5ITImiW91GcGDuBW6elJDVKouQ== - dependencies: - node-gyp-build "^3.9.0" - "@datadog/native-iast-taint-tracking@3.2.0": version "3.2.0" resolved "https://registry.yarnpkg.com/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-3.2.0.tgz#9fb6823d82f934e12c06ea1baa7399ca80deb2ec" @@ -2526,14 +2422,6 @@ dependencies: node-gyp-build "^3.9.0" -"@datadog/native-metrics@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@datadog/native-metrics/-/native-metrics-2.0.0.tgz#65bf03313ee419956361e097551db36173e85712" - integrity sha512-YklGVwUtmKGYqFf1MNZuOHvTYdKuR4+Af1XkWcMD8BwOAjxmd9Z+97328rCOY8TFUJzlGUPaXzB8j2qgG/BMwA== - dependencies: - node-addon-api "^6.1.0" - node-gyp-build "^3.9.0" - "@datadog/native-metrics@^3.0.1": version "3.0.1" resolved "https://registry.yarnpkg.com/@datadog/native-metrics/-/native-metrics-3.0.1.tgz#dc276c93785c0377a048e316f23b7c8ff3acfa84" @@ -2542,17 +2430,6 @@ node-addon-api "^6.1.0" node-gyp-build "^3.9.0" -"@datadog/pprof@5.3.0": - version "5.3.0" - resolved "https://registry.yarnpkg.com/@datadog/pprof/-/pprof-5.3.0.tgz#c2f58d328ecced7f99887f1a559d7fe3aecb9219" - integrity sha512-53z2Q3K92T6Pf4vz4Ezh8kfkVEvLzbnVqacZGgcbkP//q0joFzO8q00Etw1S6NdnCX0XmX08ULaF4rUI5r14mw== - dependencies: - delay "^5.0.0" - node-gyp-build "<4.0" - p-limit "^3.1.0" - pprof-format "^2.1.0" - source-map "^0.7.4" - "@datadog/pprof@5.4.1": version "5.4.1" resolved "https://registry.yarnpkg.com/@datadog/pprof/-/pprof-5.4.1.tgz#08c9bcf5d8efb2eeafdfc9f5bb5402f79fb41266" @@ -3469,16 +3346,6 @@ resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796" integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg== -"@jsep-plugin/assignment@^1.2.1": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@jsep-plugin/assignment/-/assignment-1.3.0.tgz#fcfc5417a04933f7ceee786e8ab498aa3ce2b242" - integrity sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ== - -"@jsep-plugin/regex@^1.0.3": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@jsep-plugin/regex/-/regex-1.0.4.tgz#cb2fc423220fa71c609323b9ba7f7d344a755fcc" - integrity sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg== - "@koa/cors@5.0.0": version "5.0.0" resolved "https://registry.yarnpkg.com/@koa/cors/-/cors-5.0.0.tgz#0029b5f057fa0d0ae0e37dd2c89ece315a0daffd" @@ -7374,7 +7241,23 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.13.2.tgz#0aa167216965ac9474ccfa83892cfb6b3e1e52ef" integrity sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw== -axios@1.1.3, axios@1.7.7, axios@^0.21.1, axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.6.2, axios@^1.6.8: +axios@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.1.3.tgz#8274250dada2edf53814ed7db644b9c2866c1e35" + integrity sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA== + dependencies: + follow-redirects "^1.15.0" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +axios@^0.21.1: + version "0.21.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" + integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== + dependencies: + follow-redirects "^1.14.0" + +axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.6.2, axios@^1.6.8: version "1.7.7" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f" integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q== @@ -9336,43 +9219,6 @@ dc-polyfill@^0.1.4: resolved "https://registry.yarnpkg.com/dc-polyfill/-/dc-polyfill-0.1.6.tgz#c2940fa68ffb24a7bf127cc6cfdd15b39f0e7f02" integrity sha512-UV33cugmCC49a5uWAApM+6Ev9ZdvIUMTrtCO9fj96TPGOQiea54oeO3tiEVdVeo3J9N2UdJEmbS4zOkkEA35uQ== -dd-trace@5.23.0: - version "5.23.0" - resolved "https://registry.yarnpkg.com/dd-trace/-/dd-trace-5.23.0.tgz#a0c11863406de440a6675648caf06e1d07d67ba8" - integrity sha512-nLvwSGpTMIk6S3sMSge6yFqqgqI573VgZc8MF31vl6K0ouJoE7OkVx9cmSVjS4CbSi525tcKq9z7tApsNLpVLQ== - dependencies: - "@datadog/native-appsec" "8.1.1" - "@datadog/native-iast-rewriter" "2.4.1" - "@datadog/native-iast-taint-tracking" "3.1.0" - "@datadog/native-metrics" "^2.0.0" - "@datadog/pprof" "5.3.0" - "@datadog/sketches-js" "^2.1.0" - "@opentelemetry/api" ">=1.0.0 <1.9.0" - "@opentelemetry/core" "^1.14.0" - crypto-randomuuid "^1.0.0" - dc-polyfill "^0.1.4" - ignore "^5.2.4" - import-in-the-middle "1.11.2" - int64-buffer "^0.1.9" - istanbul-lib-coverage "3.2.0" - jest-docblock "^29.7.0" - jsonpath-plus "^9.0.0" - koalas "^1.0.2" - limiter "1.1.5" - lodash.sortby "^4.7.0" - lru-cache "^7.14.0" - module-details-from-path "^1.0.3" - msgpack-lite "^0.1.26" - opentracing ">=0.12.1" - path-to-regexp "^0.1.10" - pprof-format "^2.1.0" - protobufjs "^7.2.5" - retry "^0.13.1" - rfdc "^1.3.1" - semver "^7.5.4" - shell-quote "^1.8.1" - tlhunter-sorted-set "^0.1.0" - dd-trace@5.26.0: version "5.26.0" resolved "https://registry.yarnpkg.com/dd-trace/-/dd-trace-5.26.0.tgz#cc55061f66742bf01d0d7dc9f75c0e4937c82f40" @@ -11405,7 +11251,7 @@ fn.name@1.x.x: resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== -follow-redirects@^1.15.6: +follow-redirects@^1.14.0, follow-redirects@^1.15.0, follow-redirects@^1.15.6: version "1.15.9" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== @@ -12523,7 +12369,12 @@ http-assert@^1.3.0: deep-equal "~1.0.1" http-errors "~1.8.0" -http-cache-semantics@3.8.1, http-cache-semantics@4.1.1, http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: +http-cache-semantics@3.8.1: + version "3.8.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" + integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== + +http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== @@ -13013,6 +12864,11 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + is-buffer@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" @@ -13474,11 +13330,6 @@ isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== -isobject@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" - integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== - isolated-vm@^4.7.2: version "4.7.2" resolved "https://registry.yarnpkg.com/isolated-vm/-/isolated-vm-4.7.2.tgz#5670d5cce1d92004f9b825bec5b0b11fc7501b65" @@ -14148,11 +13999,6 @@ jsdom@^21.1.1: ws "^8.13.0" xml-name-validator "^4.0.0" -jsep@^1.3.8: - version "1.4.0" - resolved "https://registry.yarnpkg.com/jsep/-/jsep-1.4.0.tgz#19feccbfa51d8a79f72480b4b8e40ce2e17152f0" - integrity sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw== - jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -14256,15 +14102,6 @@ jsonparse@^1.2.0, jsonparse@^1.3.1: resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== -jsonpath-plus@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/jsonpath-plus/-/jsonpath-plus-9.0.0.tgz#bb8703ee481531142bca8dee9a42fe72b8358a7f" - integrity sha512-bqE77VIDStrOTV/czspZhTn+o27Xx9ZJRGVkdVShEtPoqsIx5yALv3lWVU6y+PqYvWPJNWE7ORCQheQkEe0DDA== - dependencies: - "@jsep-plugin/assignment" "^1.2.1" - "@jsep-plugin/regex" "^1.0.3" - jsep "^1.3.8" - jsonschema@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.4.0.tgz#1afa34c4bc22190d8e42271ec17ac8b3404f87b2" @@ -14370,7 +14207,14 @@ kill-port@^1.6.1: get-them-args "1.3.2" shell-exec "1.0.2" -kind-of@6.0.3, kind-of@^3.0.2, kind-of@^3.1.0, kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: +kind-of@^3.0.2, kind-of@^3.1.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== + dependencies: + is-buffer "^1.1.5" + +kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== @@ -15944,7 +15788,7 @@ msgpackr-extract@^3.0.2: "@msgpackr-extract/msgpackr-extract-linux-x64" "3.0.2" "@msgpackr-extract/msgpackr-extract-win32-x64" "3.0.2" -msgpackr@1.10.1, msgpackr@^1.5.2: +msgpackr@^1.5.2: version "1.10.1" resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.10.1.tgz#51953bb4ce4f3494f0c4af3f484f01cfbb306555" integrity sha512-r5VRLv9qouXuLiIBrLpl2d5ZvPt8svdQTl5/vMvE4nzDMyEX4sgW5yWhuBBj5UmgwOTWj8CIdSXn5sAfsHAWIQ== @@ -16142,13 +15986,27 @@ node-domexception@1.0.0: resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== -node-fetch@2.6.7, node-fetch@2.6.9, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7, node-fetch@^2.6.9, node-fetch@^2.7.0: +node-fetch@2.6.7, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0" +node-fetch@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" + integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg== + dependencies: + whatwg-url "^5.0.0" + +node-fetch@^2.6.9, node-fetch@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-forge@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" @@ -17246,7 +17104,15 @@ passport-strategy@1.x.x, passport-strategy@^1.0.0: resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" integrity sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA== -passport@0.6.0, passport@^0.4.0, passport@^0.6.0: +passport@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/passport/-/passport-0.4.1.tgz#941446a21cb92fc688d97a0861c38ce9f738f270" + integrity sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg== + dependencies: + passport-strategy "1.x.x" + pause "0.0.1" + +passport@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/passport/-/passport-0.6.0.tgz#e869579fab465b5c0b291e841e6cc95c005fac9d" integrity sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug== @@ -18511,6 +18377,13 @@ pseudomap@^1.0.2: resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== +psl@^1.1.28: + version "1.13.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.13.0.tgz#8b2357f13ef3cf546af3f52de00543a94da86cfa" + integrity sha512-BFwmFXiJoFqlUpZ5Qssolv15DMyc84gTBds1BjsV1BfXEo1UyyD7GsmN67n7J77uRhoSNW1AXtXKPLcBFQn9Aw== + dependencies: + punycode "^2.3.1" + psl@^1.1.33: version "1.9.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" @@ -18556,6 +18429,11 @@ punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== +punycode@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + pupa@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62" @@ -19526,6 +19404,11 @@ sax@1.2.1: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" integrity sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA== +sax@>=0.1.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f" + integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg== + sax@>=0.6.0: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -19598,13 +19481,33 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -"semver@2 || 3 || 4 || 5", semver@7.5.3, semver@^5.5.0, semver@^5.6.0, semver@^5.7.1, semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@~2.3.1: +"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0, semver@^5.7.1: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +semver@7.5.3, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3: version "7.5.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== dependencies: lru-cache "^6.0.0" +semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.5.4, semver@^7.6.0: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + +semver@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-2.3.2.tgz#b9848f25d6cf36333073ec9ef8856d42f1233e52" + integrity sha512-abLdIKCosKfpnmhS52NCTjO4RiLspDfsn37prjzGrp9im5DPJOgh82Os92vtwGh6XdQryKI/7SREZnV+aqiXrA== + seq-queue@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/seq-queue/-/seq-queue-0.0.5.tgz#d56812e1c017a6e4e7c3e3a37a1da6d78dd3c93e" @@ -21179,7 +21082,7 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -tough-cookie@4.1.3, "tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2, tough-cookie@~2.5.0: +"tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2: version "4.1.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw== @@ -21189,6 +21092,14 @@ tough-cookie@4.1.3, "tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0 universalify "^0.2.0" url-parse "^1.5.3" +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + tr46@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240" @@ -21664,14 +21575,6 @@ unpipe@1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -unset-value@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-2.0.1.tgz#57bed0c22d26f28d69acde5df9a11b77c74d2df3" - integrity sha512-2hvrBfjUE00PkqN+q0XP6yRAOGrR06uSiUoIQGZkc7GxvQ9H7v8quUPNtZjMg4uux69i8HWpIjLPUKwCuRGyNg== - dependencies: - has-value "^2.0.2" - isobject "^4.0.0" - untildify@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" @@ -22380,7 +22283,14 @@ xml-parse-from-string@^1.0.0: resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28" integrity sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g== -xml2js@0.1.x, xml2js@0.6.2, xml2js@^0.5.0: +xml2js@0.1.x: + version "0.1.14" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.1.14.tgz#5274e67f5a64c5f92974cd85139e0332adc6b90c" + integrity sha512-pbdws4PPPNc1HPluSUKamY4GWMk592K7qwcj6BExbVOhhubub8+pMda/ql68b6L3luZs/OGjGSB5goV7SnmgnA== + dependencies: + sax ">=0.1.1" + +xml2js@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499" integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA== @@ -22388,6 +22298,14 @@ xml2js@0.1.x, xml2js@0.6.2, xml2js@^0.5.0: sax ">=0.6.0" xmlbuilder "~11.0.0" +xml2js@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7" + integrity sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA== + dependencies: + sax ">=0.6.0" + xmlbuilder "~11.0.0" + xmlbuilder@~11.0.0: version "11.0.1" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" From 3d98e96e9362afdaf86a72b14bdc2adf8f0cb991 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 26 Nov 2024 10:53:13 +0100 Subject: [PATCH 63/88] Gitignore --- packages/builder/.gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/builder/.gitignore b/packages/builder/.gitignore index e5c961d509..41411ea16c 100644 --- a/packages/builder/.gitignore +++ b/packages/builder/.gitignore @@ -5,4 +5,5 @@ package-lock.json release/ dist/ routify -.routify/ \ No newline at end of file +.routify/ +.rollup.cache \ No newline at end of file From 90833d18897eccedf0d71e0807d525867e819b42 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 26 Nov 2024 10:54:41 +0100 Subject: [PATCH 64/88] Transform plugins and navigation store --- packages/builder/src/api.ts | 59 ++++++++++++++ .../builder/src/stores/portal/navigation.ts | 38 +++++++++ packages/builder/src/stores/portal/plugins.ts | 81 +++++++++++++++++++ 3 files changed, 178 insertions(+) create mode 100644 packages/builder/src/api.ts create mode 100644 packages/builder/src/stores/portal/navigation.ts create mode 100644 packages/builder/src/stores/portal/plugins.ts diff --git a/packages/builder/src/api.ts b/packages/builder/src/api.ts new file mode 100644 index 0000000000..5d1a0beaeb --- /dev/null +++ b/packages/builder/src/api.ts @@ -0,0 +1,59 @@ +import { + createAPIClient, + CookieUtils, + Constants, +} from "@budibase/frontend-core" +import { appStore } from "stores/builder" +import { get } from "svelte/store" +import { auth, navigation } from "./stores/portal" + +export const API = createAPIClient({ + attachHeaders: (headers: Record) => { + // Attach app ID header from store + let appId = get(appStore).appId + if (appId) { + headers["x-budibase-app-id"] = appId + } + + // Add csrf token if authenticated + const user: any = get(auth).user + if (user?.csrfToken) { + headers["x-csrf-token"] = user.csrfToken + } + }, + + onError: (error: any) => { + const { url, message, status, method, handled } = error || {} + + // Log any errors that we haven't manually handled + if (!handled) { + console.error("Unhandled error from API client", error) + return + } + + // Log all errors to console + console.warn(`[Builder] HTTP ${status} on ${method}:${url}\n\t${message}`) + + // Logout on 403's + if (status === 403) { + // Remove cookies + CookieUtils.removeCookie(Constants.Cookies.Auth) + + // Reload after removing cookie, go to login + if (!url.includes("self") && !url.includes("login")) { + location.reload() + } + } + }, + onMigrationDetected: (appId: string) => { + const updatingUrl = `/builder/app/updating/${appId}` + + if (window.location.pathname === updatingUrl) { + return + } + + get(navigation)?.goto( + `${updatingUrl}?returnUrl=${encodeURIComponent(window.location.pathname)}` + ) + }, +}) diff --git a/packages/builder/src/stores/portal/navigation.ts b/packages/builder/src/stores/portal/navigation.ts new file mode 100644 index 0000000000..2b230622f6 --- /dev/null +++ b/packages/builder/src/stores/portal/navigation.ts @@ -0,0 +1,38 @@ +import { writable } from "svelte/store" + +type GotoFuncType = (path: string) => void + +interface Store { + initialisated: boolean + goto: GotoFuncType +} + +export function createNavigationStore() { + const store = writable({ + initialisated: false, + goto: undefined as any, + }) + const { set, subscribe } = store + + const init = (gotoFunc: GotoFuncType) => { + if (typeof gotoFunc !== "function") { + throw new Error( + `gotoFunc must be a function, found a "${typeof gotoFunc}" instead` + ) + } + + set({ + initialisated: true, + goto: gotoFunc, + }) + } + + return { + subscribe, + actions: { + init, + }, + } +} + +export const navigation = createNavigationStore() diff --git a/packages/builder/src/stores/portal/plugins.ts b/packages/builder/src/stores/portal/plugins.ts new file mode 100644 index 0000000000..ff4dc3618f --- /dev/null +++ b/packages/builder/src/stores/portal/plugins.ts @@ -0,0 +1,81 @@ +import { writable } from "svelte/store" +import { PluginSource } from "constants/index" + +const { API } = require("api") + +interface Plugin { + _id: string +} + +export function createPluginsStore() { + const { subscribe, set, update } = writable([]) + + async function load() { + const plugins = await API.getPlugins() + set(plugins) + } + + async function deletePlugin(pluginId: string) { + await API.deletePlugin(pluginId) + update(state => { + state = state.filter(existing => existing._id !== pluginId) + return state + }) + } + + async function createPlugin(source: string, url: string, auth = null) { + let pluginData: any = { + source, + url, + } + + switch (source) { + case PluginSource.URL: + pluginData.headers = auth + break + case PluginSource.GITHUB: + pluginData.githubToken = auth + break + } + + let res = await API.createPlugin(pluginData) + let newPlugin = res.plugin + update(state => { + const currentIdx = state.findIndex(plugin => plugin._id === newPlugin._id) + if (currentIdx >= 0) { + state.splice(currentIdx, 1, newPlugin) + } else { + state.push(newPlugin) + } + return state + }) + } + + async function uploadPlugin(file: File) { + if (!file) { + return + } + let data = new FormData() + data.append("file", file) + let resp = await API.uploadPlugin(data) + let newPlugin = resp.plugins[0] + update(state => { + const currentIdx = state.findIndex(plugin => plugin._id === newPlugin._id) + if (currentIdx >= 0) { + state.splice(currentIdx, 1, newPlugin) + } else { + state.push(newPlugin) + } + return state + }) + } + return { + subscribe, + load, + createPlugin, + deletePlugin, + uploadPlugin, + } +} + +export const plugins = createPluginsStore() From e44a68d356488ff0bff381b691a33f4e460a66fd Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 26 Nov 2024 11:04:37 +0100 Subject: [PATCH 65/88] Delete js files (moved to ts) --- packages/builder/src/api.js | 59 -------------- .../builder/src/stores/portal/navigation.js | 31 -------- packages/builder/src/stores/portal/plugins.js | 76 ------------------- 3 files changed, 166 deletions(-) delete mode 100644 packages/builder/src/api.js delete mode 100644 packages/builder/src/stores/portal/navigation.js delete mode 100644 packages/builder/src/stores/portal/plugins.js diff --git a/packages/builder/src/api.js b/packages/builder/src/api.js deleted file mode 100644 index 6441b4ff48..0000000000 --- a/packages/builder/src/api.js +++ /dev/null @@ -1,59 +0,0 @@ -import { - createAPIClient, - CookieUtils, - Constants, -} from "@budibase/frontend-core" -import { appStore } from "stores/builder" -import { get } from "svelte/store" -import { auth, navigation } from "./stores/portal" - -export const API = createAPIClient({ - attachHeaders: headers => { - // Attach app ID header from store - let appId = get(appStore).appId - if (appId) { - headers["x-budibase-app-id"] = appId - } - - // Add csrf token if authenticated - const user = get(auth).user - if (user?.csrfToken) { - headers["x-csrf-token"] = user.csrfToken - } - }, - - onError: error => { - const { url, message, status, method, handled } = error || {} - - // Log any errors that we haven't manually handled - if (!handled) { - console.error("Unhandled error from API client", error) - return - } - - // Log all errors to console - console.warn(`[Builder] HTTP ${status} on ${method}:${url}\n\t${message}`) - - // Logout on 403's - if (status === 403) { - // Remove cookies - CookieUtils.removeCookie(Constants.Cookies.Auth) - - // Reload after removing cookie, go to login - if (!url.includes("self") && !url.includes("login")) { - location.reload() - } - } - }, - onMigrationDetected: appId => { - const updatingUrl = `/builder/app/updating/${appId}` - - if (window.location.pathname === updatingUrl) { - return - } - - get(navigation).goto( - `${updatingUrl}?returnUrl=${encodeURIComponent(window.location.pathname)}` - ) - }, -}) diff --git a/packages/builder/src/stores/portal/navigation.js b/packages/builder/src/stores/portal/navigation.js deleted file mode 100644 index 67a06eff53..0000000000 --- a/packages/builder/src/stores/portal/navigation.js +++ /dev/null @@ -1,31 +0,0 @@ -import { writable } from "svelte/store" - -export function createNavigationStore() { - const store = writable({ - initialisated: false, - goto: undefined, - }) - const { set, subscribe } = store - - const init = gotoFunc => { - if (typeof gotoFunc !== "function") { - throw new Error( - `gotoFunc must be a function, found a "${typeof gotoFunc}" instead` - ) - } - - set({ - initialisated: true, - goto: gotoFunc, - }) - } - - return { - subscribe, - actions: { - init, - }, - } -} - -export const navigation = createNavigationStore() diff --git a/packages/builder/src/stores/portal/plugins.js b/packages/builder/src/stores/portal/plugins.js deleted file mode 100644 index e259f9aa6d..0000000000 --- a/packages/builder/src/stores/portal/plugins.js +++ /dev/null @@ -1,76 +0,0 @@ -import { writable } from "svelte/store" -import { API } from "api" -import { PluginSource } from "constants" - -export function createPluginsStore() { - const { subscribe, set, update } = writable([]) - - async function load() { - const plugins = await API.getPlugins() - set(plugins) - } - - async function deletePlugin(pluginId) { - await API.deletePlugin(pluginId) - update(state => { - state = state.filter(existing => existing._id !== pluginId) - return state - }) - } - - async function createPlugin(source, url, auth = null) { - let pluginData = { - source, - url, - } - - switch (source) { - case PluginSource.URL: - pluginData.headers = auth - break - case PluginSource.GITHUB: - pluginData.githubToken = auth - break - } - - let res = await API.createPlugin(pluginData) - let newPlugin = res.plugin - update(state => { - const currentIdx = state.findIndex(plugin => plugin._id === newPlugin._id) - if (currentIdx >= 0) { - state.splice(currentIdx, 1, newPlugin) - } else { - state.push(newPlugin) - } - return state - }) - } - - async function uploadPlugin(file) { - if (!file) { - return - } - let data = new FormData() - data.append("file", file) - let resp = await API.uploadPlugin(data) - let newPlugin = resp.plugins[0] - update(state => { - const currentIdx = state.findIndex(plugin => plugin._id === newPlugin._id) - if (currentIdx >= 0) { - state.splice(currentIdx, 1, newPlugin) - } else { - state.push(newPlugin) - } - return state - }) - } - return { - subscribe, - load, - createPlugin, - deletePlugin, - uploadPlugin, - } -} - -export const plugins = createPluginsStore() From 78725cff9142c6c09d9d90f6b1c789910827c5c6 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 26 Nov 2024 11:21:51 +0100 Subject: [PATCH 66/88] Fix imports --- packages/builder/src/index.d.ts | 8 ++++++++ packages/builder/src/stores/portal/plugins.ts | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 packages/builder/src/index.d.ts diff --git a/packages/builder/src/index.d.ts b/packages/builder/src/index.d.ts new file mode 100644 index 0000000000..1cbad4f12c --- /dev/null +++ b/packages/builder/src/index.d.ts @@ -0,0 +1,8 @@ +declare module "api" { + const API: { + getPlugins: () => Promise + createPlugin: (plugin: object) => Promise + uploadPlugin: (plugin: FormData) => Promise + deletePlugin: (id: string) => Promise + } +} diff --git a/packages/builder/src/stores/portal/plugins.ts b/packages/builder/src/stores/portal/plugins.ts index ff4dc3618f..15110a852b 100644 --- a/packages/builder/src/stores/portal/plugins.ts +++ b/packages/builder/src/stores/portal/plugins.ts @@ -1,7 +1,7 @@ import { writable } from "svelte/store" import { PluginSource } from "constants/index" -const { API } = require("api") +import { API } from "api" interface Plugin { _id: string From 55b9e530e0f6a04e098143c4956ea40fbec8363b Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 26 Nov 2024 12:23:58 +0100 Subject: [PATCH 67/88] Update yarn.lock --- yarn.lock | 334 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 208 insertions(+), 126 deletions(-) diff --git a/yarn.lock b/yarn.lock index dcaab4e315..dd01832bba 100644 --- a/yarn.lock +++ b/yarn.lock @@ -842,7 +842,7 @@ "@azure/abort-controller" "^2.0.0" tslib "^2.6.2" -"@azure/identity@^4.2.1": +"@azure/identity@4.2.1", "@azure/identity@^4.2.1": version "4.2.1" resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-4.2.1.tgz#22b366201e989b7b41c0e1690e103bd579c31e4c" integrity sha512-U8hsyC9YPcEIzoaObJlRDvp7KiF0MGS7xcWbyJSVvXRkC/HXo1f0oYeBYmEvVgRfacw7GHf6D6yAoh9JHz6A5Q== @@ -2196,6 +2196,47 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@budibase/backend-core@3.2.11": + version "0.0.0" + dependencies: + "@budibase/nano" "10.1.5" + "@budibase/pouchdb-replication-stream" "1.2.11" + "@budibase/shared-core" "0.0.0" + "@budibase/types" "0.0.0" + "@techpass/passport-openidconnect" "0.3.3" + aws-cloudfront-sign "3.0.2" + aws-sdk "2.1692.0" + bcrypt "5.1.0" + bcryptjs "2.4.3" + bull "4.10.1" + correlation-id "4.0.0" + dd-trace "5.26.0" + dotenv "16.0.1" + google-auth-library "^8.0.1" + google-spreadsheet "npm:@budibase/google-spreadsheet@4.1.5" + ioredis "5.3.2" + joi "17.6.0" + jsonwebtoken "9.0.2" + knex "2.4.2" + koa-passport "^6.0.0" + koa-pino-logger "4.0.0" + lodash "4.17.21" + node-fetch "2.6.7" + passport-google-oauth "2.0.0" + passport-local "1.0.0" + passport-oauth2-refresh "^2.1.0" + pino "8.11.0" + pino-http "8.3.3" + posthog-node "4.0.1" + pouchdb "9.0.0" + pouchdb-find "9.0.0" + redlock "4.2.0" + rotating-file-stream "3.1.0" + sanitize-s3-objectkey "0.0.1" + semver "^7.5.4" + tar-fs "2.1.1" + uuid "^8.3.2" + "@budibase/handlebars-helpers@^0.13.2": version "0.13.2" resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.13.2.tgz#73ab51c464e91fd955b429017648e0257060db77" @@ -2238,6 +2279,47 @@ pouchdb-promise "^6.0.4" through2 "^2.0.0" +"@budibase/pro@npm:@budibase/pro@latest": + version "3.2.11" + resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-3.2.11.tgz#40d4929b3958dacca3f4c207718a4647c08a6100" + integrity sha512-xE1tx/C2cnbyR4s/6XkkweoQw6CW5fsQt++gzrrML8abgsODru+tA7M2NbWlKsEnVWHDQRvUVcXm4wqDeNNZ9g== + dependencies: + "@anthropic-ai/sdk" "^0.27.3" + "@budibase/backend-core" "3.2.11" + "@budibase/shared-core" "3.2.11" + "@budibase/string-templates" "3.2.11" + "@budibase/types" "3.2.11" + "@koa/router" "13.1.0" + bull "4.10.1" + dd-trace "5.23.0" + joi "17.6.0" + jsonwebtoken "9.0.2" + lru-cache "^7.14.1" + memorystream "^0.3.1" + node-fetch "2.6.7" + openai "4.59.0" + scim-patch "^0.8.1" + scim2-parse-filter "^0.2.8" + +"@budibase/shared-core@3.2.11": + version "0.0.0" + dependencies: + "@budibase/types" "0.0.0" + cron-validate "1.4.5" + +"@budibase/string-templates@3.2.11": + version "0.0.0" + dependencies: + "@budibase/handlebars-helpers" "^0.13.2" + dayjs "^1.10.8" + handlebars "^4.7.8" + lodash.clonedeep "^4.5.0" + +"@budibase/types@3.2.11": + version "0.0.0" + dependencies: + scim-patch "^0.8.1" + "@bull-board/api@5.10.2": version "5.10.2" resolved "https://registry.yarnpkg.com/@bull-board/api/-/api-5.10.2.tgz#ae8ff6918b23897bf879a6ead3683f964374c4b3" @@ -2400,6 +2482,13 @@ resolved "https://registry.yarnpkg.com/@datadog/libdatadog/-/libdatadog-0.2.2.tgz#ac02c76ac9a38250dca740727c7cdf00244ce3d3" integrity sha512-rTWo96mEPTY5UbtGoFj8/wY0uKSViJhsPg/Z6aoFWBFXQ8b45Ix2e/yvf92AAwrhG+gPLTxEqTXh3kef2dP8Ow== +"@datadog/native-appsec@8.1.1": + version "8.1.1" + resolved "https://registry.yarnpkg.com/@datadog/native-appsec/-/native-appsec-8.1.1.tgz#76aa34697e6ecbd3d9ef7e6938d3cdcfa689b1f3" + integrity sha512-mf+Ym/AzET4FeUTXOs8hz0uLOSsVIUnavZPUx8YoKWK5lKgR2L+CLfEzOpjBwgFpDgbV8I1/vyoGelgGpsMKHA== + dependencies: + node-gyp-build "^3.9.0" + "@datadog/native-appsec@8.3.0": version "8.3.0" resolved "https://registry.yarnpkg.com/@datadog/native-appsec/-/native-appsec-8.3.0.tgz#91afd89d18d386be4da8a1b0e04500f2f8b5eb66" @@ -2407,6 +2496,14 @@ dependencies: node-gyp-build "^3.9.0" +"@datadog/native-iast-rewriter@2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.4.1.tgz#e8211f78c818906513fb96a549374da0382c7623" + integrity sha512-j3auTmyyn63e2y+SL28CGNy/l+jXQyh+pxqoGTacWaY5FW/dvo5nGQepAismgJ3qJ8VhQfVWRdxBSiT7wu9clw== + dependencies: + lru-cache "^7.14.0" + node-gyp-build "^4.5.0" + "@datadog/native-iast-rewriter@2.5.0": version "2.5.0" resolved "https://registry.yarnpkg.com/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.5.0.tgz#b613defe86e78168f750d1f1662d4ffb3cf002e6" @@ -2415,6 +2512,13 @@ lru-cache "^7.14.0" node-gyp-build "^4.5.0" +"@datadog/native-iast-taint-tracking@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-3.1.0.tgz#7b2ed7f8fad212d65e5ab03bcdea8b42a3051b2e" + integrity sha512-rw6qSjmxmu1yFHVvZLXFt/rVq2tUZXocNogPLB8n7MPpA0jijNGb109WokWw5ITImiW91GcGDuBW6elJDVKouQ== + dependencies: + node-gyp-build "^3.9.0" + "@datadog/native-iast-taint-tracking@3.2.0": version "3.2.0" resolved "https://registry.yarnpkg.com/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-3.2.0.tgz#9fb6823d82f934e12c06ea1baa7399ca80deb2ec" @@ -2422,6 +2526,14 @@ dependencies: node-gyp-build "^3.9.0" +"@datadog/native-metrics@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@datadog/native-metrics/-/native-metrics-2.0.0.tgz#65bf03313ee419956361e097551db36173e85712" + integrity sha512-YklGVwUtmKGYqFf1MNZuOHvTYdKuR4+Af1XkWcMD8BwOAjxmd9Z+97328rCOY8TFUJzlGUPaXzB8j2qgG/BMwA== + dependencies: + node-addon-api "^6.1.0" + node-gyp-build "^3.9.0" + "@datadog/native-metrics@^3.0.1": version "3.0.1" resolved "https://registry.yarnpkg.com/@datadog/native-metrics/-/native-metrics-3.0.1.tgz#dc276c93785c0377a048e316f23b7c8ff3acfa84" @@ -2430,6 +2542,17 @@ node-addon-api "^6.1.0" node-gyp-build "^3.9.0" +"@datadog/pprof@5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@datadog/pprof/-/pprof-5.3.0.tgz#c2f58d328ecced7f99887f1a559d7fe3aecb9219" + integrity sha512-53z2Q3K92T6Pf4vz4Ezh8kfkVEvLzbnVqacZGgcbkP//q0joFzO8q00Etw1S6NdnCX0XmX08ULaF4rUI5r14mw== + dependencies: + delay "^5.0.0" + node-gyp-build "<4.0" + p-limit "^3.1.0" + pprof-format "^2.1.0" + source-map "^0.7.4" + "@datadog/pprof@5.4.1": version "5.4.1" resolved "https://registry.yarnpkg.com/@datadog/pprof/-/pprof-5.4.1.tgz#08c9bcf5d8efb2eeafdfc9f5bb5402f79fb41266" @@ -3346,6 +3469,16 @@ resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796" integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg== +"@jsep-plugin/assignment@^1.2.1": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@jsep-plugin/assignment/-/assignment-1.3.0.tgz#fcfc5417a04933f7ceee786e8ab498aa3ce2b242" + integrity sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ== + +"@jsep-plugin/regex@^1.0.3": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@jsep-plugin/regex/-/regex-1.0.4.tgz#cb2fc423220fa71c609323b9ba7f7d344a755fcc" + integrity sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg== + "@koa/cors@5.0.0": version "5.0.0" resolved "https://registry.yarnpkg.com/@koa/cors/-/cors-5.0.0.tgz#0029b5f057fa0d0ae0e37dd2c89ece315a0daffd" @@ -7241,23 +7374,7 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.13.2.tgz#0aa167216965ac9474ccfa83892cfb6b3e1e52ef" integrity sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw== -axios@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.1.3.tgz#8274250dada2edf53814ed7db644b9c2866c1e35" - integrity sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA== - dependencies: - follow-redirects "^1.15.0" - form-data "^4.0.0" - proxy-from-env "^1.1.0" - -axios@^0.21.1: - version "0.21.4" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" - integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== - dependencies: - follow-redirects "^1.14.0" - -axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.6.2, axios@^1.6.8: +axios@1.1.3, axios@1.7.7, axios@^0.21.1, axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.6.2, axios@^1.6.8: version "1.7.7" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f" integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q== @@ -9219,6 +9336,43 @@ dc-polyfill@^0.1.4: resolved "https://registry.yarnpkg.com/dc-polyfill/-/dc-polyfill-0.1.6.tgz#c2940fa68ffb24a7bf127cc6cfdd15b39f0e7f02" integrity sha512-UV33cugmCC49a5uWAApM+6Ev9ZdvIUMTrtCO9fj96TPGOQiea54oeO3tiEVdVeo3J9N2UdJEmbS4zOkkEA35uQ== +dd-trace@5.23.0: + version "5.23.0" + resolved "https://registry.yarnpkg.com/dd-trace/-/dd-trace-5.23.0.tgz#a0c11863406de440a6675648caf06e1d07d67ba8" + integrity sha512-nLvwSGpTMIk6S3sMSge6yFqqgqI573VgZc8MF31vl6K0ouJoE7OkVx9cmSVjS4CbSi525tcKq9z7tApsNLpVLQ== + dependencies: + "@datadog/native-appsec" "8.1.1" + "@datadog/native-iast-rewriter" "2.4.1" + "@datadog/native-iast-taint-tracking" "3.1.0" + "@datadog/native-metrics" "^2.0.0" + "@datadog/pprof" "5.3.0" + "@datadog/sketches-js" "^2.1.0" + "@opentelemetry/api" ">=1.0.0 <1.9.0" + "@opentelemetry/core" "^1.14.0" + crypto-randomuuid "^1.0.0" + dc-polyfill "^0.1.4" + ignore "^5.2.4" + import-in-the-middle "1.11.2" + int64-buffer "^0.1.9" + istanbul-lib-coverage "3.2.0" + jest-docblock "^29.7.0" + jsonpath-plus "^9.0.0" + koalas "^1.0.2" + limiter "1.1.5" + lodash.sortby "^4.7.0" + lru-cache "^7.14.0" + module-details-from-path "^1.0.3" + msgpack-lite "^0.1.26" + opentracing ">=0.12.1" + path-to-regexp "^0.1.10" + pprof-format "^2.1.0" + protobufjs "^7.2.5" + retry "^0.13.1" + rfdc "^1.3.1" + semver "^7.5.4" + shell-quote "^1.8.1" + tlhunter-sorted-set "^0.1.0" + dd-trace@5.26.0: version "5.26.0" resolved "https://registry.yarnpkg.com/dd-trace/-/dd-trace-5.26.0.tgz#cc55061f66742bf01d0d7dc9f75c0e4937c82f40" @@ -11251,7 +11405,7 @@ fn.name@1.x.x: resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== -follow-redirects@^1.14.0, follow-redirects@^1.15.0, follow-redirects@^1.15.6: +follow-redirects@^1.15.6: version "1.15.9" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== @@ -12369,12 +12523,7 @@ http-assert@^1.3.0: deep-equal "~1.0.1" http-errors "~1.8.0" -http-cache-semantics@3.8.1: - version "3.8.1" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" - integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== - -http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: +http-cache-semantics@3.8.1, http-cache-semantics@4.1.1, http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== @@ -12864,11 +13013,6 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - is-buffer@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" @@ -13330,6 +13474,11 @@ isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== +isobject@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" + integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== + isolated-vm@^4.7.2: version "4.7.2" resolved "https://registry.yarnpkg.com/isolated-vm/-/isolated-vm-4.7.2.tgz#5670d5cce1d92004f9b825bec5b0b11fc7501b65" @@ -13999,6 +14148,11 @@ jsdom@^21.1.1: ws "^8.13.0" xml-name-validator "^4.0.0" +jsep@^1.3.8: + version "1.4.0" + resolved "https://registry.yarnpkg.com/jsep/-/jsep-1.4.0.tgz#19feccbfa51d8a79f72480b4b8e40ce2e17152f0" + integrity sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw== + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -14102,6 +14256,15 @@ jsonparse@^1.2.0, jsonparse@^1.3.1: resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== +jsonpath-plus@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/jsonpath-plus/-/jsonpath-plus-9.0.0.tgz#bb8703ee481531142bca8dee9a42fe72b8358a7f" + integrity sha512-bqE77VIDStrOTV/czspZhTn+o27Xx9ZJRGVkdVShEtPoqsIx5yALv3lWVU6y+PqYvWPJNWE7ORCQheQkEe0DDA== + dependencies: + "@jsep-plugin/assignment" "^1.2.1" + "@jsep-plugin/regex" "^1.0.3" + jsep "^1.3.8" + jsonschema@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.4.0.tgz#1afa34c4bc22190d8e42271ec17ac8b3404f87b2" @@ -14207,14 +14370,7 @@ kill-port@^1.6.1: get-them-args "1.3.2" shell-exec "1.0.2" -kind-of@^3.0.2, kind-of@^3.1.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== - dependencies: - is-buffer "^1.1.5" - -kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: +kind-of@6.0.3, kind-of@^3.0.2, kind-of@^3.1.0, kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== @@ -15788,7 +15944,7 @@ msgpackr-extract@^3.0.2: "@msgpackr-extract/msgpackr-extract-linux-x64" "3.0.2" "@msgpackr-extract/msgpackr-extract-win32-x64" "3.0.2" -msgpackr@^1.5.2: +msgpackr@1.10.1, msgpackr@^1.5.2: version "1.10.1" resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.10.1.tgz#51953bb4ce4f3494f0c4af3f484f01cfbb306555" integrity sha512-r5VRLv9qouXuLiIBrLpl2d5ZvPt8svdQTl5/vMvE4nzDMyEX4sgW5yWhuBBj5UmgwOTWj8CIdSXn5sAfsHAWIQ== @@ -15986,27 +16142,13 @@ node-domexception@1.0.0: resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== -node-fetch@2.6.7, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7: +node-fetch@2.6.7, node-fetch@2.6.9, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7, node-fetch@^2.6.9, node-fetch@^2.7.0: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0" -node-fetch@2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" - integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg== - dependencies: - whatwg-url "^5.0.0" - -node-fetch@^2.6.9, node-fetch@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== - dependencies: - whatwg-url "^5.0.0" - node-forge@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" @@ -17104,15 +17246,7 @@ passport-strategy@1.x.x, passport-strategy@^1.0.0: resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" integrity sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA== -passport@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/passport/-/passport-0.4.1.tgz#941446a21cb92fc688d97a0861c38ce9f738f270" - integrity sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg== - dependencies: - passport-strategy "1.x.x" - pause "0.0.1" - -passport@^0.6.0: +passport@0.6.0, passport@^0.4.0, passport@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/passport/-/passport-0.6.0.tgz#e869579fab465b5c0b291e841e6cc95c005fac9d" integrity sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug== @@ -18377,13 +18511,6 @@ pseudomap@^1.0.2: resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== -psl@^1.1.28: - version "1.13.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.13.0.tgz#8b2357f13ef3cf546af3f52de00543a94da86cfa" - integrity sha512-BFwmFXiJoFqlUpZ5Qssolv15DMyc84gTBds1BjsV1BfXEo1UyyD7GsmN67n7J77uRhoSNW1AXtXKPLcBFQn9Aw== - dependencies: - punycode "^2.3.1" - psl@^1.1.33: version "1.9.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" @@ -18429,11 +18556,6 @@ punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== -punycode@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" - integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== - pupa@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62" @@ -19404,11 +19526,6 @@ sax@1.2.1: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" integrity sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA== -sax@>=0.1.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f" - integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg== - sax@>=0.6.0: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -19481,33 +19598,13 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0, semver@^5.7.1: - version "5.7.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" - integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== - -semver@7.5.3, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3: +"semver@2 || 3 || 4 || 5", semver@7.5.3, semver@^5.5.0, semver@^5.6.0, semver@^5.7.1, semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@~2.3.1: version "7.5.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== dependencies: lru-cache "^6.0.0" -semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - -semver@^7.5.4, semver@^7.6.0: - version "7.6.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" - integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== - -semver@~2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-2.3.2.tgz#b9848f25d6cf36333073ec9ef8856d42f1233e52" - integrity sha512-abLdIKCosKfpnmhS52NCTjO4RiLspDfsn37prjzGrp9im5DPJOgh82Os92vtwGh6XdQryKI/7SREZnV+aqiXrA== - seq-queue@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/seq-queue/-/seq-queue-0.0.5.tgz#d56812e1c017a6e4e7c3e3a37a1da6d78dd3c93e" @@ -21082,7 +21179,7 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -"tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2: +tough-cookie@4.1.3, "tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2, tough-cookie@~2.5.0: version "4.1.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw== @@ -21092,14 +21189,6 @@ touch@^3.1.0: universalify "^0.2.0" url-parse "^1.5.3" -tough-cookie@~2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" - integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== - dependencies: - psl "^1.1.28" - punycode "^2.1.1" - tr46@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240" @@ -21575,6 +21664,14 @@ unpipe@1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== +unset-value@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-2.0.1.tgz#57bed0c22d26f28d69acde5df9a11b77c74d2df3" + integrity sha512-2hvrBfjUE00PkqN+q0XP6yRAOGrR06uSiUoIQGZkc7GxvQ9H7v8quUPNtZjMg4uux69i8HWpIjLPUKwCuRGyNg== + dependencies: + has-value "^2.0.2" + isobject "^4.0.0" + untildify@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" @@ -22283,14 +22380,7 @@ xml-parse-from-string@^1.0.0: resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28" integrity sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g== -xml2js@0.1.x: - version "0.1.14" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.1.14.tgz#5274e67f5a64c5f92974cd85139e0332adc6b90c" - integrity sha512-pbdws4PPPNc1HPluSUKamY4GWMk592K7qwcj6BExbVOhhubub8+pMda/ql68b6L3luZs/OGjGSB5goV7SnmgnA== - dependencies: - sax ">=0.1.1" - -xml2js@0.6.2: +xml2js@0.1.x, xml2js@0.6.2, xml2js@^0.5.0: version "0.6.2" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499" integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA== @@ -22298,14 +22388,6 @@ xml2js@0.6.2: sax ">=0.6.0" xmlbuilder "~11.0.0" -xml2js@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7" - integrity sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA== - dependencies: - sax ">=0.6.0" - xmlbuilder "~11.0.0" - xmlbuilder@~11.0.0: version "11.0.1" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" From f1c7d1e257e89f96b0d4018d5082809f295e14dd Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 26 Nov 2024 12:29:24 +0100 Subject: [PATCH 68/88] Add checks --- packages/builder/package.json | 8 +++++--- packages/builder/tsconfig.build.json | 14 ++++---------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/packages/builder/package.json b/packages/builder/package.json index 5b3d4413cf..7e00f3e550 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -4,14 +4,16 @@ "license": "GPL-3.0", "private": true, "scripts": { - "svelte-check": "svelte-check --no-tsconfig", - "build": "yarn svelte-check && routify -b && vite build --emptyOutDir", + "build": "routify -b && vite build --emptyOutDir", "start": "routify -c rollup", "dev": "routify -c dev:vite", "dev:vite": "vite --host 0.0.0.0", "rollup": "rollup -c -w", "test": "vitest run", - "test:watch": "vitest" + "test:watch": "vitest", + "svelte-check": "svelte-check --no-tsconfig", + "check:types": "yarn svelte-check && yarn check:ts", + "check:ts": "tsc --noEmit --target es2020" }, "jest": { "globals": { diff --git a/packages/builder/tsconfig.build.json b/packages/builder/tsconfig.build.json index 6a5ba315a1..ca1316f83c 100644 --- a/packages/builder/tsconfig.build.json +++ b/packages/builder/tsconfig.build.json @@ -9,15 +9,9 @@ "noImplicitAny": true, "esModuleInterop": true, "resolveJsonModule": true, - "incremental": true + "incremental": true, + "skipLibCheck": true }, - "include": [ - "./src/**/*" - ], - "exclude": [ - "node_modules", - "**/*.json", - "**/*.spec.ts", - "**/*.spec.js" - ] + "include": ["./src/**/*"], + "exclude": ["node_modules", "**/*.json", "**/*.spec.ts", "**/*.spec.js"] } From 9f7a823818033ea0fc4f2b07491d68a67949b5a1 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 26 Nov 2024 12:29:36 +0100 Subject: [PATCH 69/88] Add error --- packages/builder/src/stores/portal/plugins.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/stores/portal/plugins.ts b/packages/builder/src/stores/portal/plugins.ts index 15110a852b..86c4f48c86 100644 --- a/packages/builder/src/stores/portal/plugins.ts +++ b/packages/builder/src/stores/portal/plugins.ts @@ -11,7 +11,7 @@ export function createPluginsStore() { const { subscribe, set, update } = writable([]) async function load() { - const plugins = await API.getPlugins() + const plugins = await API.getPugins() set(plugins) } From 2474e44c54da7493c72475a30fc727f281ad18fb Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 26 Nov 2024 12:34:42 +0100 Subject: [PATCH 70/88] Use svelte-check for ts checks and move it to check:ts --- packages/builder/package.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/builder/package.json b/packages/builder/package.json index 7e00f3e550..f1ba3e2b3e 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -11,9 +11,7 @@ "rollup": "rollup -c -w", "test": "vitest run", "test:watch": "vitest", - "svelte-check": "svelte-check --no-tsconfig", - "check:types": "yarn svelte-check && yarn check:ts", - "check:ts": "tsc --noEmit --target es2020" + "check:types": "yarn svelte-check" }, "jest": { "globals": { From 541f66d784d0e673745f911751640e803c494397 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 26 Nov 2024 12:48:19 +0100 Subject: [PATCH 71/88] Increase max size --- packages/builder/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/package.json b/packages/builder/package.json index 5b3d4413cf..ebd6571fd2 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -5,7 +5,7 @@ "private": true, "scripts": { "svelte-check": "svelte-check --no-tsconfig", - "build": "yarn svelte-check && routify -b && vite build --emptyOutDir", + "build": "yarn svelte-check && routify -b && NODE_OPTIONS=\"--max_old_space_size=4096\" vite build --emptyOutDir", "start": "routify -c rollup", "dev": "routify -c dev:vite", "dev:vite": "vite --host 0.0.0.0", From e8ade0caee935f24f93ad648327db6e81219e741 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Tue, 26 Nov 2024 12:00:47 +0000 Subject: [PATCH 72/88] update row spec file using automation builder --- .../src/automations/tests/updateRow.spec.ts | 144 +++++++++++------- 1 file changed, 85 insertions(+), 59 deletions(-) diff --git a/packages/server/src/automations/tests/updateRow.spec.ts b/packages/server/src/automations/tests/updateRow.spec.ts index 457bf60533..ee90e996de 100644 --- a/packages/server/src/automations/tests/updateRow.spec.ts +++ b/packages/server/src/automations/tests/updateRow.spec.ts @@ -8,58 +8,83 @@ import { Table, TableSourceType, } from "@budibase/types" +import { createAutomationBuilder } from "./utilities/AutomationTestBuilder" import * as setup from "./utilities" import * as uuid from "uuid" describe("test the update row action", () => { - let table: Table, row: Row, inputs: any - let config = setup.getConfig() + let table: Table, + row: any, + config = setup.getConfig() beforeAll(async () => { await config.init() table = await config.createTable() row = await config.createRow() - inputs = { - rowId: row._id, - row: { - ...row, - name: "Updated name", - // put a falsy option in to be removed - description: "", - }, - } }) afterAll(setup.afterAll) - it("should be able to run the action", async () => { - const res = await setup.runStep( - config, - setup.actions.UPDATE_ROW.stepId, - inputs + it("should be able to run the update row action", async () => { + const builder = createAutomationBuilder({ + name: "Update Row Automation", + }) + + const results = await builder + .appAction({ fields: {} }) + .updateRow({ + rowId: row._id, + row: { + ...row, + name: "Updated name", + description: "", + }, + meta: {}, + }) + .run() + + expect(results.steps[0].outputs.success).toEqual(true) + const updatedRow = await config.api.row.get( + table._id!, + results.steps[0].outputs.id ) - expect(res.success).toEqual(true) - const updatedRow = await config.api.row.get(table._id!, res.id) expect(updatedRow.name).toEqual("Updated name") expect(updatedRow.description).not.toEqual("") }) it("should check invalid inputs return an error", async () => { - const res = await setup.runStep(config, setup.actions.UPDATE_ROW.stepId, {}) - expect(res.success).toEqual(false) + const builder = createAutomationBuilder({ + name: "Invalid Inputs Automation", + }) + + const results = await builder + .appAction({ fields: {} }) + .updateRow({ meta: {}, row: {}, rowId: "" }) + .run() + + expect(results.steps[0].outputs.success).toEqual(false) }) it("should return an error when table doesn't exist", async () => { - const res = await setup.runStep(config, setup.actions.UPDATE_ROW.stepId, { - row: { _id: "invalid" }, - rowId: "invalid", + const builder = createAutomationBuilder({ + name: "Nonexistent Table Automation", }) - expect(res.success).toEqual(false) + + const results = await builder + .appAction({ fields: {} }) + .updateRow({ + row: { _id: "invalid" }, + rowId: "invalid", + meta: {}, + }) + .run() + + expect(results.steps[0].outputs.success).toEqual(false) }) it("should not overwrite links if those links are not set", async () => { - let linkField: FieldSchema = { + const linkField: FieldSchema = { type: FieldType.LINK, name: "", fieldName: "", @@ -71,7 +96,7 @@ describe("test the update row action", () => { tableId: InternalTable.USER_METADATA, } - let table = await config.api.table.save({ + const table = await config.api.table.save({ name: uuid.v4(), type: "table", sourceType: TableSourceType.INTERNAL, @@ -82,23 +107,22 @@ describe("test the update row action", () => { }, }) - let user1 = await config.createUser() - let user2 = await config.createUser() + const user1 = await config.createUser() + const user2 = await config.createUser() - let row = await config.api.row.save(table._id!, { + const row = await config.api.row.save(table._id!, { user1: [{ _id: user1._id }], user2: [{ _id: user2._id }], }) - let getResp = await config.api.row.get(table._id!, row._id!) - expect(getResp.user1[0]._id).toEqual(user1._id) - expect(getResp.user2[0]._id).toEqual(user2._id) + const builder = createAutomationBuilder({ + name: "Link Preservation Automation", + }) - let stepResp = await setup.runStep( - config, - setup.actions.UPDATE_ROW.stepId, - { - rowId: row._id, + const results = await builder + .appAction({ fields: {} }) + .updateRow({ + rowId: row._id!, row: { _id: row._id, _rev: row._rev, @@ -106,17 +130,19 @@ describe("test the update row action", () => { user1: [user2._id], user2: "", }, - } - ) - expect(stepResp.success).toEqual(true) + meta: {}, + }) + .run() - getResp = await config.api.row.get(table._id!, row._id!) + expect(results.steps[0].outputs.success).toEqual(true) + + const getResp = await config.api.row.get(table._id!, row._id!) expect(getResp.user1[0]._id).toEqual(user2._id) expect(getResp.user2[0]._id).toEqual(user2._id) }) - it("should overwrite links if those links are not set and we ask it do", async () => { - let linkField: FieldSchema = { + it("should overwrite links if those links are not set and we ask it to", async () => { + const linkField: FieldSchema = { type: FieldType.LINK, name: "", fieldName: "", @@ -128,7 +154,7 @@ describe("test the update row action", () => { tableId: InternalTable.USER_METADATA, } - let table = await config.api.table.save({ + const table = await config.api.table.save({ name: uuid.v4(), type: "table", sourceType: TableSourceType.INTERNAL, @@ -139,23 +165,22 @@ describe("test the update row action", () => { }, }) - let user1 = await config.createUser() - let user2 = await config.createUser() + const user1 = await config.createUser() + const user2 = await config.createUser() - let row = await config.api.row.save(table._id!, { + const row = await config.api.row.save(table._id!, { user1: [{ _id: user1._id }], user2: [{ _id: user2._id }], }) - let getResp = await config.api.row.get(table._id!, row._id!) - expect(getResp.user1[0]._id).toEqual(user1._id) - expect(getResp.user2[0]._id).toEqual(user2._id) + const builder = createAutomationBuilder({ + name: "Link Overwrite Automation", + }) - let stepResp = await setup.runStep( - config, - setup.actions.UPDATE_ROW.stepId, - { - rowId: row._id, + const results = await builder + .appAction({ fields: {} }) + .updateRow({ + rowId: row._id!, row: { _id: row._id, _rev: row._rev, @@ -170,11 +195,12 @@ describe("test the update row action", () => { }, }, }, - } - ) - expect(stepResp.success).toEqual(true) + }) + .run() - getResp = await config.api.row.get(table._id!, row._id!) + expect(results.steps[0].outputs.success).toEqual(true) + + const getResp = await config.api.row.get(table._id!, row._id!) expect(getResp.user1[0]._id).toEqual(user2._id) expect(getResp.user2).toBeUndefined() }) From ed12fb8367982e35e3388299c0d262091b638e8c Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 26 Nov 2024 12:43:15 +0100 Subject: [PATCH 73/88] Fix build --- packages/builder/src/stores/portal/plugins.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/stores/portal/plugins.ts b/packages/builder/src/stores/portal/plugins.ts index 86c4f48c86..15110a852b 100644 --- a/packages/builder/src/stores/portal/plugins.ts +++ b/packages/builder/src/stores/portal/plugins.ts @@ -11,7 +11,7 @@ export function createPluginsStore() { const { subscribe, set, update } = writable([]) async function load() { - const plugins = await API.getPugins() + const plugins = await API.getPlugins() set(plugins) } From b99d411ceca13d08f57a8f5099db2baeea1ab1e7 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Tue, 26 Nov 2024 15:48:40 +0000 Subject: [PATCH 74/88] migrate deleteRow from runStep to test builder --- .../src/automations/tests/deleteRow.spec.ts | 73 +++++++++++-------- .../src/automations/tests/updateRow.spec.ts | 4 +- 2 files changed, 45 insertions(+), 32 deletions(-) diff --git a/packages/server/src/automations/tests/deleteRow.spec.ts b/packages/server/src/automations/tests/deleteRow.spec.ts index dd13aa49c1..cabf590421 100644 --- a/packages/server/src/automations/tests/deleteRow.spec.ts +++ b/packages/server/src/automations/tests/deleteRow.spec.ts @@ -1,52 +1,65 @@ +import { createAutomationBuilder } from "./utilities/AutomationTestBuilder" import * as setup from "./utilities" describe("test the delete row action", () => { - let table: any - let row: any - let inputs: any - let config = setup.getConfig() + let table: any, + row: any, + config = setup.getConfig() - beforeEach(async () => { + beforeAll(async () => { await config.init() table = await config.createTable() row = await config.createRow() - inputs = { - tableId: table._id, - id: row._id, - revision: row._rev, - } }) afterAll(setup.afterAll) - it("should be able to run the action", async () => { - const res = await setup.runStep( - config, - setup.actions.DELETE_ROW.stepId, - inputs - ) - expect(res.success).toEqual(true) - expect(res.response).toBeDefined() - expect(res.row._id).toEqual(row._id) - }) + it("should be able to run the delete row action", async () => { + const builder = createAutomationBuilder({ + name: "Delete Row Automation", + }) - it("check usage quota attempts", async () => { - await setup.runInProd(async () => { - await setup.runStep(config, setup.actions.DELETE_ROW.stepId, inputs) + await builder + .appAction({ fields: {} }) + .deleteRow({ + tableId: table._id, + id: row._id, + revision: row._rev, + }) + .run() + + await config.api.row.get(table._id, row._id, { + status: 404, }) }) it("should check invalid inputs return an error", async () => { - const res = await setup.runStep(config, setup.actions.DELETE_ROW.stepId, {}) - expect(res.success).toEqual(false) + const builder = createAutomationBuilder({ + name: "Invalid Inputs Automation", + }) + + const results = await builder + .appAction({ fields: {} }) + .deleteRow({ tableId: "", id: "", revision: "" }) + .run() + + expect(results.steps[0].outputs.success).toEqual(false) }) it("should return an error when table doesn't exist", async () => { - const res = await setup.runStep(config, setup.actions.DELETE_ROW.stepId, { - tableId: "invalid", - id: "invalid", - revision: "invalid", + const builder = createAutomationBuilder({ + name: "Nonexistent Table Automation", }) - expect(res.success).toEqual(false) + + const results = await builder + .appAction({ fields: {} }) + .deleteRow({ + tableId: "invalid", + id: "invalid", + revision: "invalid", + }) + .run() + + expect(results.steps[0].outputs.success).toEqual(false) }) }) diff --git a/packages/server/src/automations/tests/updateRow.spec.ts b/packages/server/src/automations/tests/updateRow.spec.ts index ee90e996de..45f78826f6 100644 --- a/packages/server/src/automations/tests/updateRow.spec.ts +++ b/packages/server/src/automations/tests/updateRow.spec.ts @@ -15,7 +15,7 @@ import * as uuid from "uuid" describe("test the update row action", () => { let table: Table, - row: any, + row: Row, config = setup.getConfig() beforeAll(async () => { @@ -34,7 +34,7 @@ describe("test the update row action", () => { const results = await builder .appAction({ fields: {} }) .updateRow({ - rowId: row._id, + rowId: row._id!, row: { ...row, name: "Updated name", From cfa6d487f85237a64fb8e99f548ef73907516c56 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 26 Nov 2024 16:06:55 +0000 Subject: [PATCH 75/88] Convert client to vite --- packages/client/package.json | 19 ++----- packages/client/rollup.config.js | 22 +++----- packages/client/src/index.js | 2 +- packages/client/tsconfig.json | 6 ++- packages/client/vite.config.mjs | 89 ++++++++++++++++++++++++++++++++ yarn.lock | 82 ++++++----------------------- 6 files changed, 123 insertions(+), 97 deletions(-) create mode 100644 packages/client/vite.config.mjs diff --git a/packages/client/package.json b/packages/client/package.json index fb9851e0a1..0d4932dc0d 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -15,8 +15,8 @@ "./manifest.json": "./manifest.json" }, "scripts": { - "build": "rollup -c", - "dev": "rollup -cw" + "build": "vite build", + "dev": "vite build --watch" }, "dependencies": { "@budibase/bbui": "0.0.0", @@ -36,19 +36,10 @@ "svelte-spa-router": "^4.0.1" }, "devDependencies": { - "@rollup/plugin-alias": "^5.1.0", - "@rollup/plugin-commonjs": "^25.0.7", - "@rollup/plugin-image": "^3.0.3", - "@rollup/plugin-node-resolve": "^15.2.3", + "@sveltejs/vite-plugin-svelte": "1.4.0", "postcss": "^8.4.35", - "rollup": "^4.9.6", - "rollup-plugin-json": "^4.0.0", - "rollup-plugin-polyfill-node": "^0.13.0", - "rollup-plugin-postcss": "^4.0.2", - "rollup-plugin-svelte": "^7.1.6", - "rollup-plugin-svg": "^2.0.0", - "rollup-plugin-terser": "^7.0.2", - "rollup-plugin-visualizer": "^5.12.0" + "vite": "^4.5.0", + "vite-plugin-css-injected-by-js": "3.5.2" }, "resolutions": { "loader-utils": "1.4.1" diff --git a/packages/client/rollup.config.js b/packages/client/rollup.config.js index 9839414f7e..3178a527fe 100644 --- a/packages/client/rollup.config.js +++ b/packages/client/rollup.config.js @@ -10,6 +10,7 @@ import json from "rollup-plugin-json" import nodePolyfills from "rollup-plugin-polyfill-node" import path from "path" import { visualizer } from "rollup-plugin-visualizer" +import typescript from "@rollup/plugin-typescript" const production = !process.env.ROLLUP_WATCH const ignoredWarnings = [ @@ -20,19 +21,6 @@ const ignoredWarnings = [ "a11y-click-events-have-key-events", ] -const devPaths = production - ? [] - : [ - { - find: "@budibase/shared-core", - replacement: path.resolve("../shared-core/dist/index"), - }, - { - find: "@budibase/types", - replacement: path.resolve("../types/dist/index"), - }, - ] - export default { input: "src/index.js", output: [ @@ -53,6 +41,12 @@ export default { warn(warning) }, plugins: [ + typescript({ + include: [ + "src/**/*.ts", + `${path.resolve("..")}/frontend-core/src/**/*.ts`, + ], + }), alias({ entries: [ { @@ -83,7 +77,6 @@ export default { find: "sdk", replacement: path.resolve("./src/sdk"), }, - ...devPaths, ], }), svelte({ @@ -102,6 +95,7 @@ export default { preferBuiltins: true, browser: true, dedupe: ["svelte", "svelte/internal"], + extensions: [".js", ".ts", ".json"], }), svg(), image({ diff --git a/packages/client/src/index.js b/packages/client/src/index.js index de6d1bdc12..9cef52bb1e 100644 --- a/packages/client/src/index.js +++ b/packages/client/src/index.js @@ -10,7 +10,7 @@ import { eventStore, hoverStore, } from "./stores" -import loadSpectrumIcons from "@budibase/bbui/spectrum-icons-rollup.js" +import loadSpectrumIcons from "@budibase/bbui/spectrum-icons-vite.js" import { get } from "svelte/store" import { initWebsocket } from "./websocket.js" diff --git a/packages/client/tsconfig.json b/packages/client/tsconfig.json index 81f1657f48..5bc64cc5c0 100644 --- a/packages/client/tsconfig.json +++ b/packages/client/tsconfig.json @@ -3,6 +3,10 @@ "allowJs": true, "strict": true, "outDir": "dist", + "allowSyntheticDefaultImports": true, + "target": "ESNext", + "moduleResolution": "bundler", + "resolveJsonModule": true, "paths": { "@budibase/*": [ "../*/src/index.ts", @@ -13,5 +17,5 @@ "*": ["./src/*"] } }, - "include": ["src/**/*"] + "include": ["src/**/*.ts", "../frontend-core/src/**/*.ts"] } diff --git a/packages/client/vite.config.mjs b/packages/client/vite.config.mjs new file mode 100644 index 0000000000..9c623b709f --- /dev/null +++ b/packages/client/vite.config.mjs @@ -0,0 +1,89 @@ +import { svelte } from "@sveltejs/vite-plugin-svelte" +import { defineConfig } from "vite" +import path from "path" +import cssInjectedByJsPlugin from "vite-plugin-css-injected-by-js" + +const ignoredWarnings = [ + "unused-export-let", + "css-unused-selector", + "module-script-reactive-declaration", + "a11y-no-onchange", + "a11y-click-events-have-key-events", +] + +export default defineConfig(({ mode }) => { + const isProduction = mode === "production" + + return { + server: { + open: false, + }, + build: { + lib: { + entry: "src/index.js", + formats: ["iife"], + outDir: "dist", + name: "budibase_client", + fileName: () => "budibase-client.js", + minify: isProduction, + }, + }, + plugins: [ + svelte({ + emitCss: true, + onwarn: (warning, handler) => { + // Ignore some warnings + if (!ignoredWarnings.includes(warning.code)) { + handler(warning) + } + }, + }), + cssInjectedByJsPlugin(), + ], + resolve: { + dedupe: ["svelte", "svelte/internal"], + alias: [ + { + find: "manifest.json", + replacement: path.resolve("./manifest.json"), + }, + { + find: "api", + replacement: path.resolve("./src/api"), + }, + { + find: "components", + replacement: path.resolve("./src/components"), + }, + { + find: "stores", + replacement: path.resolve("./src/stores"), + }, + { + find: "utils", + replacement: path.resolve("./src/utils"), + }, + { + find: "constants", + replacement: path.resolve("./src/constants"), + }, + { + find: "sdk", + replacement: path.resolve("./src/sdk"), + }, + { + find: "@budibase/types", + replacement: path.resolve("../types/src"), + }, + { + find: "@budibase/shared-core", + replacement: path.resolve("../shared-core/src"), + }, + { + find: "@budibase/bbui", + replacement: path.resolve("../bbui/src"), + }, + ], + }, + } +}) diff --git a/yarn.lock b/yarn.lock index dd01832bba..b15f31f7e6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4075,13 +4075,6 @@ resolved "https://registry.yarnpkg.com/@redis/time-series/-/time-series-1.0.4.tgz#af85eb080f6934580e4d3b58046026b6c2b18717" integrity sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng== -"@rollup/plugin-alias@^5.1.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@rollup/plugin-alias/-/plugin-alias-5.1.0.tgz#99a94accc4ff9a3483be5baeedd5d7da3b597e93" - integrity sha512-lpA3RZ9PdIG7qqhEfv79tBffNaoDuukFDrmhLqg9ifv99u/ehn+lOg30x2zmhf8AQqQUZaMk/B9fZraQ6/acDQ== - dependencies: - slash "^4.0.0" - "@rollup/plugin-commonjs@16.0.0", "@rollup/plugin-commonjs@^16.0.0": version "16.0.0" resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-16.0.0.tgz#169004d56cd0f0a1d0f35915d31a036b0efe281f" @@ -4120,14 +4113,6 @@ is-reference "1.2.1" magic-string "^0.30.3" -"@rollup/plugin-image@^3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@rollup/plugin-image/-/plugin-image-3.0.3.tgz#025b557180bae20f2349ff5130ef2114169feaac" - integrity sha512-qXWQwsXpvD4trSb8PeFPFajp8JLpRtqqOeNYRUKnEQNHm7e5UP7fuSRcbjQAJ7wDZBbnJvSdY5ujNBQd9B1iFg== - dependencies: - "@rollup/pluginutils" "^5.0.1" - mini-svg-data-uri "^1.4.4" - "@rollup/plugin-inject@^5.0.4", "@rollup/plugin-inject@^5.0.5": version "5.0.5" resolved "https://registry.yarnpkg.com/@rollup/plugin-inject/-/plugin-inject-5.0.5.tgz#616f3a73fe075765f91c5bec90176608bed277a3" @@ -10885,11 +10870,6 @@ estraverse@^5.1.0, estraverse@^5.2.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== -estree-walker@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.2.1.tgz#bdafe8095383d8414d5dc2ecf4c9173b6db9412e" - integrity sha512-6/I1dwNKk0N9iGOU3ydzAAurz4NPo/ttxZNCqgIVbWFvWyzWBSNonRrJ5CpjDuyBfmM7ENN7WCzUi9aT/UPXXQ== - estree-walker@^0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.5.2.tgz#d3850be7529c9580d815600b53126515e146dd39" @@ -12635,6 +12615,11 @@ husky@^8.0.3: resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184" integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg== +husky@^9.1.4: + version "9.1.7" + resolved "https://registry.yarnpkg.com/husky/-/husky-9.1.7.tgz#d46a38035d101b46a70456a850ff4201344c0b2d" + integrity sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA== + ical-generator@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ical-generator/-/ical-generator-4.1.0.tgz#2a336c951864c5583a2aa715d16f2edcdfd2d90b" @@ -15653,11 +15638,6 @@ min-indent@^1.0.0: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== -mini-svg-data-uri@^1.4.4: - version "1.4.4" - resolved "https://registry.yarnpkg.com/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz#8ab0aabcdf8c29ad5693ca595af19dd2ead09939" - integrity sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg== - minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -15668,7 +15648,7 @@ minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== -"minimatch@2 || 3", minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: +"minimatch@2 || 3", minimatch@^3.0.3, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -19245,13 +19225,6 @@ rollup-plugin-inject-process-env@^1.3.1: dependencies: magic-string "^0.25.7" -rollup-plugin-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-json/-/rollup-plugin-json-4.0.0.tgz#a18da0a4b30bf5ca1ee76ddb1422afbb84ae2b9e" - integrity sha512-hgb8N7Cgfw5SZAkb3jf0QXii6QX/FOkiIq2M7BAQIEydjHvTyxXHQiIzZaTFgx1GK0cRCHOCBHIyEkkLdWKxow== - dependencies: - rollup-pluginutils "^2.5.0" - rollup-plugin-node-builtins@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/rollup-plugin-node-builtins/-/rollup-plugin-node-builtins-2.1.2.tgz#24a1fed4a43257b6b64371d8abc6ce1ab14597e9" @@ -19292,7 +19265,7 @@ rollup-plugin-polyfill-node@^0.13.0: dependencies: "@rollup/plugin-inject" "^5.0.4" -rollup-plugin-postcss@^4.0.0, rollup-plugin-postcss@^4.0.2: +rollup-plugin-postcss@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/rollup-plugin-postcss/-/rollup-plugin-postcss-4.0.2.tgz#15e9462f39475059b368ce0e49c800fa4b1f7050" integrity sha512-05EaY6zvZdmvPUDi3uCcAQoESDcYnv8ogJJQRp6V5kZ6J6P7uAVJlrTZcaaA20wTH527YTnKfkAoPxWI/jPp4w== @@ -19311,7 +19284,7 @@ rollup-plugin-postcss@^4.0.0, rollup-plugin-postcss@^4.0.2: safe-identifier "^0.4.2" style-inject "^0.3.0" -rollup-plugin-svelte@^7.1.0, rollup-plugin-svelte@^7.1.6: +rollup-plugin-svelte@^7.1.0: version "7.1.6" resolved "https://registry.yarnpkg.com/rollup-plugin-svelte/-/rollup-plugin-svelte-7.1.6.tgz#44a4ea6c6e8ed976824d9fd40c78d048515e5838" integrity sha512-nVFRBpGWI2qUY1OcSiEEA/kjCY2+vAjO9BI8SzA7NRrh2GTunLd6w2EYmnMt/atgdg8GvcNjLsmZmbQs/u4SQA== @@ -19319,13 +19292,6 @@ rollup-plugin-svelte@^7.1.0, rollup-plugin-svelte@^7.1.6: "@rollup/pluginutils" "^4.1.0" resolve.exports "^2.0.0" -rollup-plugin-svg@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-svg/-/rollup-plugin-svg-2.0.0.tgz#ce11b55e915d5b2190328c4e6632bd6b4fe12ee9" - integrity sha512-DmE7dSQHo1SC5L2uH2qul3Mjyd5oV6U1aVVkyvTLX/mUsRink7f1b1zaIm+32GEBA6EHu8H/JJi3DdWqM53ySQ== - dependencies: - rollup-pluginutils "^1.3.1" - rollup-plugin-terser@^7.0.2: version "7.0.2" resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz#e8fbba4869981b2dc35ae7e8a502d5c6c04d324d" @@ -19336,30 +19302,12 @@ rollup-plugin-terser@^7.0.2: serialize-javascript "^4.0.0" terser "^5.0.0" -rollup-plugin-visualizer@^5.12.0: - version "5.12.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-visualizer/-/rollup-plugin-visualizer-5.12.0.tgz#661542191ce78ee4f378995297260d0c1efb1302" - integrity sha512-8/NU9jXcHRs7Nnj07PF2o4gjxmm9lXIrZ8r175bT9dK8qoLlvKTwRMArRCMgpMGlq8CTLugRvEmyMeMXIU2pNQ== - dependencies: - open "^8.4.0" - picomatch "^2.3.1" - source-map "^0.7.4" - yargs "^17.5.1" - rollup-plugin-web-worker-loader@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/rollup-plugin-web-worker-loader/-/rollup-plugin-web-worker-loader-1.6.1.tgz#9d7a27575b64b0780fe4e8b3bc87470d217e485f" integrity sha512-4QywQSz1NXFHKdyiou16mH3ijpcfLtLGOrAqvAqu1Gx+P8+zj+3gwC2BSL/VW1d+LW4nIHC8F7d7OXhs9UdR2A== -rollup-pluginutils@^1.3.1: - version "1.5.2" - resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz#1e156e778f94b7255bfa1b3d0178be8f5c552408" - integrity sha512-SjdWWWO/CUoMpDy8RUbZ/pSpG68YHmhk5ROKNIoi2En9bJ8bTt3IhYi254RWiTclQmL7Awmrq+rZFOhZkJAHmQ== - dependencies: - estree-walker "^0.2.1" - minimatch "^3.0.2" - -rollup-pluginutils@^2.3.1, rollup-pluginutils@^2.5.0, rollup-pluginutils@^2.8.1, rollup-pluginutils@^2.8.2: +rollup-pluginutils@^2.3.1, rollup-pluginutils@^2.8.1, rollup-pluginutils@^2.8.2: version "2.8.2" resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e" integrity sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ== @@ -19817,11 +19765,6 @@ slash@3.0.0, slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -slash@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" - integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== - slice-ansi@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a" @@ -21897,6 +21840,11 @@ vite-node@0.29.8: picocolors "^1.0.0" vite "^3.0.0 || ^4.0.0" +vite-plugin-css-injected-by-js@3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/vite-plugin-css-injected-by-js/-/vite-plugin-css-injected-by-js-3.5.2.tgz#1f75d16ad5c05b6b49bf18018099a189ec2e46ad" + integrity sha512-2MpU/Y+SCZyWUB6ua3HbJCrgnF0KACAsmzOQt1UvRVJCGF6S8xdA3ZUhWcWdM9ivG4I5az8PnQmwwrkC2CAQrQ== + vite-plugin-static-copy@^0.17.0: version "0.17.0" resolved "https://registry.yarnpkg.com/vite-plugin-static-copy/-/vite-plugin-static-copy-0.17.0.tgz#e45527da186c4a3818d09635797b6fc7cc9e035f" @@ -22534,7 +22482,7 @@ yargs@16.2.0, yargs@^16.1.0, yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@^17.3.1, yargs@^17.5.1, yargs@^17.6.2, yargs@^17.7.2: +yargs@^17.3.1, yargs@^17.6.2, yargs@^17.7.2: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== From d4c9e5140d2c4ead19899334e37e6cbd6d576f5e Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 26 Nov 2024 16:13:02 +0000 Subject: [PATCH 76/88] Remove old rollup config and update tsconfig --- packages/client/rollup.config.js | 111 ------------------------------- packages/client/tsconfig.json | 3 +- 2 files changed, 1 insertion(+), 113 deletions(-) delete mode 100644 packages/client/rollup.config.js diff --git a/packages/client/rollup.config.js b/packages/client/rollup.config.js deleted file mode 100644 index 3178a527fe..0000000000 --- a/packages/client/rollup.config.js +++ /dev/null @@ -1,111 +0,0 @@ -import commonjs from "@rollup/plugin-commonjs" -import resolve from "@rollup/plugin-node-resolve" -import alias from "@rollup/plugin-alias" -import svelte from "rollup-plugin-svelte" -import { terser } from "rollup-plugin-terser" -import postcss from "rollup-plugin-postcss" -import svg from "rollup-plugin-svg" -import image from "@rollup/plugin-image" -import json from "rollup-plugin-json" -import nodePolyfills from "rollup-plugin-polyfill-node" -import path from "path" -import { visualizer } from "rollup-plugin-visualizer" -import typescript from "@rollup/plugin-typescript" - -const production = !process.env.ROLLUP_WATCH -const ignoredWarnings = [ - "unused-export-let", - "css-unused-selector", - "module-script-reactive-declaration", - "a11y-no-onchange", - "a11y-click-events-have-key-events", -] - -export default { - input: "src/index.js", - output: [ - { - sourcemap: false, - format: "iife", - file: `./dist/budibase-client.js`, - }, - ], - onwarn(warning, warn) { - if ( - warning.code === "THIS_IS_UNDEFINED" || - warning.code === "CIRCULAR_DEPENDENCY" || - warning.code === "EVAL" - ) { - return - } - warn(warning) - }, - plugins: [ - typescript({ - include: [ - "src/**/*.ts", - `${path.resolve("..")}/frontend-core/src/**/*.ts`, - ], - }), - alias({ - entries: [ - { - find: "manifest.json", - replacement: path.resolve("./manifest.json"), - }, - { - find: "api", - replacement: path.resolve("./src/api"), - }, - { - find: "components", - replacement: path.resolve("./src/components"), - }, - { - find: "stores", - replacement: path.resolve("./src/stores"), - }, - { - find: "utils", - replacement: path.resolve("./src/utils"), - }, - { - find: "constants", - replacement: path.resolve("./src/constants"), - }, - { - find: "sdk", - replacement: path.resolve("./src/sdk"), - }, - ], - }), - svelte({ - emitCss: true, - onwarn: (warning, handler) => { - // Ignore some warnings - if (!ignoredWarnings.includes(warning.code)) { - handler(warning) - } - }, - }), - postcss(), - commonjs(), - nodePolyfills(), - resolve({ - preferBuiltins: true, - browser: true, - dedupe: ["svelte", "svelte/internal"], - extensions: [".js", ".ts", ".json"], - }), - svg(), - image({ - exclude: "**/*.svg", - }), - json(), - production && terser(), - !production && visualizer(), - ], - watch: { - clearScreen: false, - }, -} diff --git a/packages/client/tsconfig.json b/packages/client/tsconfig.json index 5bc64cc5c0..740b129738 100644 --- a/packages/client/tsconfig.json +++ b/packages/client/tsconfig.json @@ -16,6 +16,5 @@ ], "*": ["./src/*"] } - }, - "include": ["src/**/*.ts", "../frontend-core/src/**/*.ts"] + } } From 0ac507f7946bcf40364335b9173aa01ad0cfbd01 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 26 Nov 2024 16:15:21 +0000 Subject: [PATCH 77/88] Remove postcss --- packages/client/package.json | 1 - yarn.lock | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/client/package.json b/packages/client/package.json index 0d4932dc0d..073869415d 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -37,7 +37,6 @@ }, "devDependencies": { "@sveltejs/vite-plugin-svelte": "1.4.0", - "postcss": "^8.4.35", "vite": "^4.5.0", "vite-plugin-css-injected-by-js": "3.5.2" }, diff --git a/yarn.lock b/yarn.lock index b15f31f7e6..b852c8bb45 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17904,7 +17904,7 @@ postcss-values-parser@^6.0.2: is-url-superb "^4.0.0" quote-unquote "^1.0.0" -postcss@^8.1.7, postcss@^8.2.9, postcss@^8.3.11, postcss@^8.4.12, postcss@^8.4.27, postcss@^8.4.29, postcss@^8.4.35, postcss@^8.4.5: +postcss@^8.1.7, postcss@^8.2.9, postcss@^8.3.11, postcss@^8.4.12, postcss@^8.4.27, postcss@^8.4.29, postcss@^8.4.5: version "8.4.41" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.41.tgz#d6104d3ba272d882fe18fc07d15dc2da62fa2681" integrity sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ== From 685657b8ebac4a46eb59514e7702398ea2cc5152 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Tue, 26 Nov 2024 19:50:18 +0000 Subject: [PATCH 78/88] migrate createrow step to use test builder --- .../src/automations/tests/createRow.spec.ts | 203 +++++++++++++++--- 1 file changed, 175 insertions(+), 28 deletions(-) diff --git a/packages/server/src/automations/tests/createRow.spec.ts b/packages/server/src/automations/tests/createRow.spec.ts index bcf9845669..bd78de2217 100644 --- a/packages/server/src/automations/tests/createRow.spec.ts +++ b/packages/server/src/automations/tests/createRow.spec.ts @@ -1,6 +1,7 @@ import * as setup from "./utilities" import { basicTableWithAttachmentField } from "../../tests/utilities/structures" import { objectStore } from "@budibase/backend-core" +import { createAutomationBuilder } from "./utilities/AutomationTestBuilder" async function uploadTestFile(filename: string) { let bucket = "testbucket" @@ -13,6 +14,7 @@ async function uploadTestFile(filename: string) { return presignedUrl } + describe("test the create row action", () => { let table: any let row: any @@ -31,30 +33,78 @@ describe("test the create row action", () => { afterAll(setup.afterAll) it("should be able to run the action", async () => { - const res = await setup.runStep(config, setup.actions.CREATE_ROW.stepId, { - row, + const result = await createAutomationBuilder({ + name: "Test Create Row Flow", + appId: config.getAppId(), + config, }) - expect(res.id).toBeDefined() - expect(res.revision).toBeDefined() - expect(res.success).toEqual(true) - const gottenRow = await config.api.row.get(table._id, res.id) + .appAction({ fields: { status: "new" } }) + .serverLog({ text: "Starting create row flow" }, { stepName: "StartLog" }) + .createRow({ row }, { stepName: "CreateRow" }) + .serverLog( + { text: "Row created with ID: {{ stepsByName.CreateRow.row._id }}" }, + { stepName: "CreationLog" } + ) + .run() + + expect(result.steps[1].outputs.success).toBeDefined() + expect(result.steps[1].outputs.id).toBeDefined() + expect(result.steps[1].outputs.revision).toBeDefined() + const gottenRow = await config.api.row.get( + table._id, + result.steps[1].outputs.id + ) expect(gottenRow.name).toEqual("test") expect(gottenRow.description).toEqual("test") + expect(result.steps[2].outputs.message).toContain( + "Row created with ID: " + result.steps[1].outputs.id + ) }) it("should return an error (not throw) when bad info provided", async () => { - const res = await setup.runStep(config, setup.actions.CREATE_ROW.stepId, { - row: { - tableId: "invalid", - invalid: "invalid", - }, + const result = await createAutomationBuilder({ + name: "Test Create Row Error Flow", + appId: config.getAppId(), + config, }) - expect(res.success).toEqual(false) + .appAction({ fields: { status: "error" } }) + .serverLog({ text: "Starting error test flow" }, { stepName: "StartLog" }) + .createRow( + { + row: { + tableId: "invalid", + invalid: "invalid", + }, + }, + { stepName: "CreateRow" } + ) + .run() + + expect(result.steps[1].outputs.success).toEqual(false) }) it("should check invalid inputs return an error", async () => { - const res = await setup.runStep(config, setup.actions.CREATE_ROW.stepId, {}) - expect(res.success).toEqual(false) + const result = await createAutomationBuilder({ + name: "Test Create Row Invalid Flow", + appId: config.getAppId(), + config, + }) + .appAction({ fields: { status: "invalid" } }) + .serverLog({ text: "Testing invalid input" }, { stepName: "StartLog" }) + .createRow({ row: {} }, { stepName: "CreateRow" }) + .filter({ + field: "{{ stepsByName.CreateRow.success }}", + condition: "equal", + value: true, + }) + .serverLog( + { text: "This log should not appear" }, + { stepName: "SkippedLog" } + ) + .run() + + expect(result.steps[1].outputs.success).toEqual(false) + expect(result.steps.length).toBeLessThan(4) }) it("should check that an attachment field is sent to storage and parsed", async () => { @@ -76,13 +126,33 @@ describe("test the create row action", () => { ] attachmentRow.file_attachment = attachmentObject - const res = await setup.runStep(config, setup.actions.CREATE_ROW.stepId, { - row: attachmentRow, + const result = await createAutomationBuilder({ + name: "Test Create Row Attachment Flow", + appId: config.getAppId(), + config, }) + .appAction({ fields: { type: "attachment" } }) + .serverLog( + { text: "Processing attachment upload" }, + { stepName: "StartLog" } + ) + .createRow({ row: attachmentRow }, { stepName: "CreateRow" }) + .filter({ + field: "{{ stepsByName.CreateRow.success }}", + condition: "equal", + value: true, + }) + .serverLog( + { + text: "Attachment uploaded with key: {{ stepsByName.CreateRow.row.file_attachment.0.key }}", + }, + { stepName: "UploadLog" } + ) + .run() - expect(res.success).toEqual(true) - expect(res.row.file_attachment[0]).toHaveProperty("key") - let s3Key = res.row.file_attachment[0].key + expect(result.steps[1].outputs.success).toEqual(true) + expect(result.steps[1].outputs.row.file_attachment[0]).toHaveProperty("key") + let s3Key = result.steps[1].outputs.row.file_attachment[0].key const client = objectStore.ObjectStore(objectStore.ObjectStoreBuckets.APPS) @@ -111,13 +181,53 @@ describe("test the create row action", () => { } attachmentRow.single_file_attachment = attachmentObject - const res = await setup.runStep(config, setup.actions.CREATE_ROW.stepId, { - row: attachmentRow, + const result = await createAutomationBuilder({ + name: "Test Create Row Single Attachment Flow", + appId: config.getAppId(), + config, }) + .appAction({ fields: { type: "single-attachment" } }) + .serverLog( + { text: "Processing single attachment" }, + { stepName: "StartLog" } + ) + .createRow({ row: attachmentRow }, { stepName: "CreateRow" }) + .branch({ + success: { + steps: stepBuilder => + stepBuilder + .serverLog( + { text: "Single attachment processed" }, + { stepName: "ProcessLog" } + ) + .serverLog( + { + text: "File key: {{ stepsByName.CreateRow.row.single_file_attachment.key }}", + }, + { stepName: "KeyLog" } + ), + condition: { + equal: { "{{ stepsByName.CreateRow.success }}": true }, + }, + }, + error: { + steps: stepBuilder => + stepBuilder.serverLog( + { text: "Failed to process attachment" }, + { stepName: "ErrorLog" } + ), + condition: { + equal: { "{{ stepsByName.CreateRow.success }}": false }, + }, + }, + }) + .run() - expect(res.success).toEqual(true) - expect(res.row.single_file_attachment).toHaveProperty("key") - let s3Key = res.row.single_file_attachment.key + expect(result.steps[1].outputs.success).toEqual(true) + expect(result.steps[1].outputs.row.single_file_attachment).toHaveProperty( + "key" + ) + let s3Key = result.steps[1].outputs.row.single_file_attachment.key const client = objectStore.ObjectStore(objectStore.ObjectStoreBuckets.APPS) @@ -146,13 +256,50 @@ describe("test the create row action", () => { } attachmentRow.single_file_attachment = attachmentObject - const res = await setup.runStep(config, setup.actions.CREATE_ROW.stepId, { - row: attachmentRow, + const result = await createAutomationBuilder({ + name: "Test Create Row Invalid Attachment Flow", + appId: config.getAppId(), + config, }) + .appAction({ fields: { type: "invalid-attachment" } }) + .serverLog( + { text: "Testing invalid attachment keys" }, + { stepName: "StartLog" } + ) + .createRow({ row: attachmentRow }, { stepName: "CreateRow" }) + .branch({ + success: { + steps: stepBuilder => + stepBuilder.serverLog( + { text: "Unexpected success" }, + { stepName: "UnexpectedLog" } + ), + condition: { + equal: { "{{ stepsByName.CreateRow.success }}": true }, + }, + }, + error: { + steps: stepBuilder => + stepBuilder + .serverLog( + { text: "Expected error occurred" }, + { stepName: "ErrorLog" } + ) + .serverLog( + { text: "Error: {{ stepsByName.CreateRow.response }}" }, + { stepName: "ErrorDetailsLog" } + ), + condition: { + equal: { "{{ stepsByName.CreateRow.success }}": false }, + }, + }, + }) + .run() - expect(res.success).toEqual(false) - expect(res.response).toEqual( + expect(result.steps[1].outputs.success).toEqual(false) + expect(result.steps[1].outputs.response).toEqual( 'Error: Attachments must have both "url" and "filename" keys. You have provided: wrongKey, anotherWrongKey' ) + expect(result.steps[2].outputs.status).toEqual("No branch condition met") }) }) From 99ceba956a0d42554e1faf4a2da4145003237c82 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Wed, 27 Nov 2024 10:01:16 +0100 Subject: [PATCH 79/88] Update yarn.lock --- yarn.lock | 5 ----- 1 file changed, 5 deletions(-) diff --git a/yarn.lock b/yarn.lock index b852c8bb45..359eb4e204 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12615,11 +12615,6 @@ husky@^8.0.3: resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184" integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg== -husky@^9.1.4: - version "9.1.7" - resolved "https://registry.yarnpkg.com/husky/-/husky-9.1.7.tgz#d46a38035d101b46a70456a850ff4201344c0b2d" - integrity sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA== - ical-generator@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ical-generator/-/ical-generator-4.1.0.tgz#2a336c951864c5583a2aa715d16f2edcdfd2d90b" From 8559a1c49d6e2067f37f751a7706571f3473bd28 Mon Sep 17 00:00:00 2001 From: Budibase Staging Release Bot <> Date: Wed, 27 Nov 2024 11:07:26 +0000 Subject: [PATCH 80/88] Bump version to 3.2.13 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index dc238bb392..fdd10e4bf1 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", - "version": "3.2.12", + "version": "3.2.13", "npmClient": "yarn", "concurrency": 20, "command": { From f12be3b703326e2ffeeb2077f786d28cf1d66ee6 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 27 Nov 2024 11:23:51 +0000 Subject: [PATCH 81/88] Updating OpenAPI specs, fixing an issue found when attempting to publish and automating this so don't need to manually check this again. --- .github/workflows/readme-openapi.yml | 28 +++++++++++++++++++++++++ packages/server/specs/openapi.json | 3 --- packages/server/specs/openapi.yaml | 3 --- packages/server/specs/resources/view.ts | 1 - 4 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/readme-openapi.yml diff --git a/.github/workflows/readme-openapi.yml b/.github/workflows/readme-openapi.yml new file mode 100644 index 0000000000..14e9887dd6 --- /dev/null +++ b/.github/workflows/readme-openapi.yml @@ -0,0 +1,28 @@ +name: ReadMe GitHub Action 🦉 + +on: + push: + branches: + - master + +jobs: + rdme-openapi: + runs-on: ubuntu-latest + steps: + - name: Check out repo + uses: actions/checkout@v3 + + - name: Use Node.js 20.x + uses: actions/setup-node@v4 + with: + node-version: 20.x + cache: yarn + - run: yarn --frozen-lockfile + + - name: update specs + run: cd packages/server && yarn specs + + - name: Run `openapi` command + uses: readmeio/rdme@v8 + with: + rdme: openapi specs/openapi.yaml --key=${{ secrets.README_API_KEY }} --id=6728a74f5918b50036c61841 diff --git a/packages/server/specs/openapi.json b/packages/server/specs/openapi.json index c47a14cf21..9d356b9931 100644 --- a/packages/server/specs/openapi.json +++ b/packages/server/specs/openapi.json @@ -2166,7 +2166,6 @@ "query": { "description": "Search parameters for view", "type": "object", - "required": [], "properties": { "logicalOperator": { "description": "When using groups this defines whether all of the filters must match, or only one of them.", @@ -2449,7 +2448,6 @@ "query": { "description": "Search parameters for view", "type": "object", - "required": [], "properties": { "logicalOperator": { "description": "When using groups this defines whether all of the filters must match, or only one of them.", @@ -2743,7 +2741,6 @@ "query": { "description": "Search parameters for view", "type": "object", - "required": [], "properties": { "logicalOperator": { "description": "When using groups this defines whether all of the filters must match, or only one of them.", diff --git a/packages/server/specs/openapi.yaml b/packages/server/specs/openapi.yaml index edfb29f432..9ad242f24c 100644 --- a/packages/server/specs/openapi.yaml +++ b/packages/server/specs/openapi.yaml @@ -1802,7 +1802,6 @@ components: query: description: Search parameters for view type: object - required: [] properties: logicalOperator: description: When using groups this defines whether all of the filters must @@ -2012,7 +2011,6 @@ components: query: description: Search parameters for view type: object - required: [] properties: logicalOperator: description: When using groups this defines whether all of the filters must @@ -2229,7 +2227,6 @@ components: query: description: Search parameters for view type: object - required: [] properties: logicalOperator: description: When using groups this defines whether all of the filters must diff --git a/packages/server/specs/resources/view.ts b/packages/server/specs/resources/view.ts index aeb2b97aa9..5becd67a37 100644 --- a/packages/server/specs/resources/view.ts +++ b/packages/server/specs/resources/view.ts @@ -142,7 +142,6 @@ layeredFilterGroup.items.properties.groups = filterGroup const viewQuerySchema = { description: "Search parameters for view", type: "object", - required: [], properties: { logicalOperator, onEmptyFilter: { From 75d7950161b2e15b1e22638ec9cf2e1af5db7d75 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Wed, 27 Nov 2024 13:44:19 +0100 Subject: [PATCH 82/88] Update pro submodule --- packages/pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pro b/packages/pro index 25dd40ee12..0f4af6db96 160000 --- a/packages/pro +++ b/packages/pro @@ -1 +1 @@ -Subproject commit 25dd40ee12b048307b558ebcedb36548d6e042cd +Subproject commit 0f4af6db96a8424faf217bcf8080d977f846c981 From 273aa2e6505d3a3a129e3851f1d171da42c7c7d0 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Wed, 27 Nov 2024 13:57:11 +0100 Subject: [PATCH 83/88] Update submodule --- packages/pro | 2 +- yarn.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/pro b/packages/pro index 0f4af6db96..4a3c11e4cf 160000 --- a/packages/pro +++ b/packages/pro @@ -1 +1 @@ -Subproject commit 0f4af6db96a8424faf217bcf8080d977f846c981 +Subproject commit 4a3c11e4cf15299af68ba149dbdcc24dd31aa3a4 diff --git a/yarn.lock b/yarn.lock index dd01832bba..80f16566f2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4082,7 +4082,7 @@ dependencies: slash "^4.0.0" -"@rollup/plugin-commonjs@16.0.0", "@rollup/plugin-commonjs@^16.0.0": +"@rollup/plugin-commonjs@^16.0.0": version "16.0.0" resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-16.0.0.tgz#169004d56cd0f0a1d0f35915d31a036b0efe281f" integrity sha512-LuNyypCP3msCGVQJ7ki8PqYdpjfEkE/xtFa5DqlF+7IBD0JsfMZ87C58heSwIMint58sAUZbt3ITqOmdQv/dXw== @@ -4168,7 +4168,7 @@ is-module "^1.0.0" resolve "^1.22.1" -"@rollup/plugin-replace@^5.0.2", "@rollup/plugin-replace@^5.0.3": +"@rollup/plugin-replace@^5.0.3": version "5.0.7" resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-5.0.7.tgz#150c9ee9db8031d9e4580a61a0edeaaed3d37687" integrity sha512-PqxSfuorkHz/SPpyngLyg5GCEkOcee9M1bkxiVDr41Pd61mqP1PLOoDPbpl44SB2mQGKwV/In74gqQmGITOhEQ== From 7b15d69cc449059d87b06930510d9155bae53019 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Wed, 27 Nov 2024 14:11:48 +0100 Subject: [PATCH 84/88] Update submodule --- packages/pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pro b/packages/pro index 4a3c11e4cf..21a6a658e0 160000 --- a/packages/pro +++ b/packages/pro @@ -1 +1 @@ -Subproject commit 4a3c11e4cf15299af68ba149dbdcc24dd31aa3a4 +Subproject commit 21a6a658e0765208fb6ebf21864497f2739dcb99 From 4369706b17ac2a07891e6c799d7338f418d8a4bb Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Thu, 28 Nov 2024 11:07:43 +0100 Subject: [PATCH 85/88] Update yarn.lock --- yarn.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn.lock b/yarn.lock index 359eb4e204..edf81d1f1e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4075,7 +4075,7 @@ resolved "https://registry.yarnpkg.com/@redis/time-series/-/time-series-1.0.4.tgz#af85eb080f6934580e4d3b58046026b6c2b18717" integrity sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng== -"@rollup/plugin-commonjs@16.0.0", "@rollup/plugin-commonjs@^16.0.0": +"@rollup/plugin-commonjs@^16.0.0": version "16.0.0" resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-16.0.0.tgz#169004d56cd0f0a1d0f35915d31a036b0efe281f" integrity sha512-LuNyypCP3msCGVQJ7ki8PqYdpjfEkE/xtFa5DqlF+7IBD0JsfMZ87C58heSwIMint58sAUZbt3ITqOmdQv/dXw== @@ -4153,7 +4153,7 @@ is-module "^1.0.0" resolve "^1.22.1" -"@rollup/plugin-replace@^5.0.2", "@rollup/plugin-replace@^5.0.3": +"@rollup/plugin-replace@^5.0.3": version "5.0.7" resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-5.0.7.tgz#150c9ee9db8031d9e4580a61a0edeaaed3d37687" integrity sha512-PqxSfuorkHz/SPpyngLyg5GCEkOcee9M1bkxiVDr41Pd61mqP1PLOoDPbpl44SB2mQGKwV/In74gqQmGITOhEQ== From 525b6f84bb5d81a4b14745cb365b2b2503f4ca96 Mon Sep 17 00:00:00 2001 From: melohagan <101575380+melohagan@users.noreply.github.com> Date: Thu, 28 Nov 2024 10:37:44 +0000 Subject: [PATCH 86/88] Remove references to day passes (#15079) * Remove references to day passes * lint * Point pro to branch with no day passes code * update yarn lock --- .../core/utilities/structures/licenses.ts | 6 -- .../tests/core/utilities/structures/quotas.ts | 3 - .../licensing/DayPassWarningModal.svelte | 81 ------------------- .../portal/licensing/LicensingOverlays.svelte | 15 ---- .../components/portal/licensing/constants.js | 2 - .../portal/licensing/licensingBanners.js | 40 --------- packages/builder/src/constants/index.js | 1 - .../src/pages/builder/apps/index.svelte | 2 +- .../pages/builder/portal/account/usage.svelte | 5 +- packages/pro | 2 +- packages/types/src/documents/global/quotas.ts | 1 - packages/types/src/documents/global/user.ts | 1 - packages/types/src/sdk/licensing/plan.ts | 2 - packages/types/src/sdk/licensing/quota.ts | 2 - .../src/api/routes/global/tests/self.spec.ts | 4 +- yarn.lock | 35 ++------ 16 files changed, 9 insertions(+), 193 deletions(-) delete mode 100644 packages/builder/src/components/portal/licensing/DayPassWarningModal.svelte diff --git a/packages/backend-core/tests/core/utilities/structures/licenses.ts b/packages/backend-core/tests/core/utilities/structures/licenses.ts index b4d209a7ee..77f6d57b09 100644 --- a/packages/backend-core/tests/core/utilities/structures/licenses.ts +++ b/packages/backend-core/tests/core/utilities/structures/licenses.ts @@ -22,7 +22,6 @@ export function price(): PurchasedPrice { currency: "usd", duration: PriceDuration.MONTHLY, priceId: "price_123", - dayPasses: undefined, isPerUser: true, } } @@ -50,11 +49,6 @@ export function quotas(): Quotas { value: 1, triggers: [], }, - dayPasses: { - name: "Queries", - value: 1, - triggers: [], - }, budibaseAICredits: { name: "Budibase AI Credits", value: 1, diff --git a/packages/backend-core/tests/core/utilities/structures/quotas.ts b/packages/backend-core/tests/core/utilities/structures/quotas.ts index 58817e4831..83c3a8a766 100644 --- a/packages/backend-core/tests/core/utilities/structures/quotas.ts +++ b/packages/backend-core/tests/core/utilities/structures/quotas.ts @@ -15,7 +15,6 @@ export const usage = (users: number = 0, creators: number = 0): QuotaUsage => { monthly: { "01-2023": { automations: 0, - dayPasses: 0, queries: 0, budibaseAICredits: 0, triggers: {}, @@ -45,14 +44,12 @@ export const usage = (users: number = 0, creators: number = 0): QuotaUsage => { }, "02-2023": { automations: 0, - dayPasses: 0, queries: 0, budibaseAICredits: 0, triggers: {}, }, current: { automations: 0, - dayPasses: 0, queries: 0, budibaseAICredits: 0, triggers: {}, diff --git a/packages/builder/src/components/portal/licensing/DayPassWarningModal.svelte b/packages/builder/src/components/portal/licensing/DayPassWarningModal.svelte deleted file mode 100644 index 341e427bf0..0000000000 --- a/packages/builder/src/components/portal/licensing/DayPassWarningModal.svelte +++ /dev/null @@ -1,81 +0,0 @@ - - - - {#if $auth.user.accountPortalAccess} - { - window.location.href = upgradeUrl - }} - > - - You have used {dayPassesUsed}% of - your plans Day Passes with {daysRemaining} day{daysRemaining == 1 - ? "" - : "s"} remaining. - - - - - {dayPassesBody} - - {:else} - - - You have used {dayPassesUsed}% of - your plans Day Passes with {daysRemaining} day{daysRemaining == 1 - ? "" - : "s"} remaining. - - - - - Please contact your account holder to upgrade. - - {/if} - - - diff --git a/packages/builder/src/components/portal/licensing/LicensingOverlays.svelte b/packages/builder/src/components/portal/licensing/LicensingOverlays.svelte index ab80418b6e..e2c52e3448 100644 --- a/packages/builder/src/components/portal/licensing/LicensingOverlays.svelte +++ b/packages/builder/src/components/portal/licensing/LicensingOverlays.svelte @@ -1,7 +1,6 @@ - { - const appAuth = get(auth) - const appLicensing = get(licensing) - if (get(licensing)?.usageMetrics["dayPasses"] >= 100) { - return { - key: "max_dayPasses", - type: BANNER_TYPES.NEGATIVE, - criteria: () => { - return true - }, - message: `Your apps are currently offline. You have exceeded your plans limit for Day Passes. ${ - appAuth.user.accountPortalAccess - ? "" - : "Please contact your account holder to upgrade." - }`, - ...upgradeAction(), - showCloseButton: false, - } - } - - return buildUsageInfoBanner( - "dayPasses", - "Day Passes", - ExpiringKeys.LICENSING_DAYPASS_WARNING_BANNER, - 90, - `You have used ${ - appLicensing?.usageMetrics["dayPasses"] - }% of your monthly usage of Day Passes with ${ - appLicensing?.quotaResetDaysRemaining - } day${ - get(licensing).quotaResetDaysRemaining == 1 ? "" : "s" - } remaining. All apps will be taken offline if this limit is reached. ${ - appAuth.user.accountPortalAccess - ? "" - : "Please contact your account holder to upgrade." - }` - ) -} - const buildPaymentFailedBanner = () => { return { key: "payment_Failed", @@ -166,7 +127,6 @@ const buildUsersAboveLimitBanner = EXPIRY_KEY => { export const getBanners = () => { return [ buildPaymentFailedBanner(), - buildDayPassBanner(ExpiringKeys.LICENSING_DAYPASS_WARNING_BANNER), buildUsageInfoBanner( "rows", "Rows", diff --git a/packages/builder/src/constants/index.js b/packages/builder/src/constants/index.js index 0d51f57c3e..3498183c8e 100644 --- a/packages/builder/src/constants/index.js +++ b/packages/builder/src/constants/index.js @@ -68,7 +68,6 @@ export const OnboardingType = { export const PlanModel = { PER_USER: "perUser", - DAY_PASS: "dayPass", } export const ChangelogURL = "https://docs.budibase.com/changelog" diff --git a/packages/builder/src/pages/builder/apps/index.svelte b/packages/builder/src/pages/builder/apps/index.svelte index 095bf2023b..632478748d 100644 --- a/packages/builder/src/pages/builder/apps/index.svelte +++ b/packages/builder/src/pages/builder/apps/index.svelte @@ -136,7 +136,7 @@ - {#if $licensing.usageMetrics?.dayPasses >= 100 || $licensing.errUserLimit} + {#if $licensing.errUserLimit}
spaceman diff --git a/packages/builder/src/pages/builder/portal/account/usage.svelte b/packages/builder/src/pages/builder/portal/account/usage.svelte index 7a1b1f8e14..cb0f5ea512 100644 --- a/packages/builder/src/pages/builder/portal/account/usage.svelte +++ b/packages/builder/src/pages/builder/portal/account/usage.svelte @@ -28,7 +28,7 @@ const upgradeUrl = `${$admin.accountPortalUrl}/portal/upgrade` const manageUrl = `${$admin.accountPortalUrl}/portal/billing` - const WARN_USAGE = ["Queries", "Automations", "Rows", "Day Passes", "Users"] + const WARN_USAGE = ["Queries", "Automations", "Rows", "Users"] const oneDayInSeconds = 86400 const EXCLUDE_QUOTAS = { @@ -36,9 +36,6 @@ Users: license => { return license.plan.model !== PlanModel.PER_USER }, - "Day Passes": license => { - return license.plan.model !== PlanModel.DAY_PASS - }, } function excludeQuota(name) { diff --git a/packages/pro b/packages/pro index 21a6a658e0..e8ef2205de 160000 --- a/packages/pro +++ b/packages/pro @@ -1 +1 @@ -Subproject commit 21a6a658e0765208fb6ebf21864497f2739dcb99 +Subproject commit e8ef2205de8bca5adcf18d07573096086aa9a606 diff --git a/packages/types/src/documents/global/quotas.ts b/packages/types/src/documents/global/quotas.ts index 4726dabf0d..a24fc8f9b0 100644 --- a/packages/types/src/documents/global/quotas.ts +++ b/packages/types/src/documents/global/quotas.ts @@ -44,7 +44,6 @@ export interface StaticUsage { export interface MonthlyUsage { [MonthlyQuotaName.QUERIES]: number [MonthlyQuotaName.AUTOMATIONS]: number - [MonthlyQuotaName.DAY_PASSES]: number [MonthlyQuotaName.BUDIBASE_AI_CREDITS]: number triggers: { [key in MonthlyQuotaName]?: QuotaTriggers diff --git a/packages/types/src/documents/global/user.ts b/packages/types/src/documents/global/user.ts index 1b242886b5..529223e88d 100644 --- a/packages/types/src/documents/global/user.ts +++ b/packages/types/src/documents/global/user.ts @@ -62,7 +62,6 @@ export interface User extends Document { password?: string status?: UserStatus createdAt?: number // override the default createdAt behaviour - users sdk historically set this to Date.now() - dayPassRecordedAt?: string userGroups?: string[] onboardedAt?: string freeTrialConfirmedAt?: string diff --git a/packages/types/src/sdk/licensing/plan.ts b/packages/types/src/sdk/licensing/plan.ts index af682cbad1..8cdd72dd5d 100644 --- a/packages/types/src/sdk/licensing/plan.ts +++ b/packages/types/src/sdk/licensing/plan.ts @@ -38,7 +38,6 @@ export interface AvailablePrice { export enum PlanModel { PER_USER = "perUser", PER_CREATOR_PER_USER = "per_creator_per_user", - DAY_PASS = "dayPass", } export interface PurchasedPlan { @@ -49,7 +48,6 @@ export interface PurchasedPlan { } export interface PurchasedPrice extends AvailablePrice { - dayPasses: number | undefined /** @deprecated - now at the plan level via model */ isPerUser: boolean } diff --git a/packages/types/src/sdk/licensing/quota.ts b/packages/types/src/sdk/licensing/quota.ts index 75fc18e8e6..ed541d2974 100644 --- a/packages/types/src/sdk/licensing/quota.ts +++ b/packages/types/src/sdk/licensing/quota.ts @@ -23,7 +23,6 @@ export enum StaticQuotaName { export enum MonthlyQuotaName { QUERIES = "queries", AUTOMATIONS = "automations", - DAY_PASSES = "dayPasses", BUDIBASE_AI_CREDITS = "budibaseAICredits", } @@ -63,7 +62,6 @@ export type PlanQuotas = { [key in PlanType]: Quotas | undefined } export type MonthlyQuotas = { [MonthlyQuotaName.QUERIES]: Quota [MonthlyQuotaName.AUTOMATIONS]: Quota - [MonthlyQuotaName.DAY_PASSES]: Quota [MonthlyQuotaName.BUDIBASE_AI_CREDITS]: Quota } diff --git a/packages/worker/src/api/routes/global/tests/self.spec.ts b/packages/worker/src/api/routes/global/tests/self.spec.ts index 277c11b081..bf34f14aa0 100644 --- a/packages/worker/src/api/routes/global/tests/self.spec.ts +++ b/packages/worker/src/api/routes/global/tests/self.spec.ts @@ -1,5 +1,5 @@ jest.mock("nodemailer") -import { TestConfiguration, mocks } from "../../../../tests" +import { TestConfiguration } from "../../../../tests" import { events } from "@budibase/backend-core" describe("/api/global/self", () => { @@ -39,7 +39,6 @@ describe("/api/global/self", () => { const dbUser = (await config.getUser(user.email))! user._rev = dbUser._rev - user.dayPassRecordedAt = mocks.date.MOCK_DATE.toISOString() expect(res.body._id).toBe(user._id) expect(events.user.updated).toHaveBeenCalledTimes(1) expect(events.user.updated).toHaveBeenCalledWith(dbUser) @@ -62,7 +61,6 @@ describe("/api/global/self", () => { const dbUser = (await config.getUser(user.email))! user._rev = dbUser._rev - user.dayPassRecordedAt = mocks.date.MOCK_DATE.toISOString() expect(dbUser.onboardedAt).toBe("2023-03-07T14:10:54.869Z") expect(dbUser.freeTrialConfirmedAt).toBe("2024-03-17T14:10:54.869Z") expect(res.body._id).toBe(user._id) diff --git a/yarn.lock b/yarn.lock index edf81d1f1e..90e41f0084 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4075,7 +4075,7 @@ resolved "https://registry.yarnpkg.com/@redis/time-series/-/time-series-1.0.4.tgz#af85eb080f6934580e4d3b58046026b6c2b18717" integrity sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng== -"@rollup/plugin-commonjs@^16.0.0": +"@rollup/plugin-commonjs@16.0.0", "@rollup/plugin-commonjs@^16.0.0": version "16.0.0" resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-16.0.0.tgz#169004d56cd0f0a1d0f35915d31a036b0efe281f" integrity sha512-LuNyypCP3msCGVQJ7ki8PqYdpjfEkE/xtFa5DqlF+7IBD0JsfMZ87C58heSwIMint58sAUZbt3ITqOmdQv/dXw== @@ -4153,7 +4153,7 @@ is-module "^1.0.0" resolve "^1.22.1" -"@rollup/plugin-replace@^5.0.3": +"@rollup/plugin-replace@^5.0.2", "@rollup/plugin-replace@^5.0.3": version "5.0.7" resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-5.0.7.tgz#150c9ee9db8031d9e4580a61a0edeaaed3d37687" integrity sha512-PqxSfuorkHz/SPpyngLyg5GCEkOcee9M1bkxiVDr41Pd61mqP1PLOoDPbpl44SB2mQGKwV/In74gqQmGITOhEQ== @@ -20226,16 +20226,7 @@ string-range@~1.2, string-range@~1.2.1: resolved "https://registry.yarnpkg.com/string-range/-/string-range-1.2.2.tgz#a893ed347e72299bc83befbbf2a692a8d239d5dd" integrity sha512-tYft6IFi8SjplJpxCUxyqisD3b+R2CSkomrtJYCkvuf1KuCAWgz7YXt4O0jip7efpfCemwHEzTEAO8EuOYgh3w== -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -20327,7 +20318,7 @@ stringify-object@^3.2.1: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -20341,13 +20332,6 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" @@ -22169,7 +22153,7 @@ worker-farm@1.7.0: dependencies: errno "~0.1.7" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -22187,15 +22171,6 @@ wrap-ansi@^5.1.0: string-width "^3.0.0" strip-ansi "^5.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From f51140801a5444bc9df73601d68fc471e6b7047b Mon Sep 17 00:00:00 2001 From: Budibase Staging Release Bot <> Date: Thu, 28 Nov 2024 12:46:08 +0000 Subject: [PATCH 87/88] Bump version to 3.2.14 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index fdd10e4bf1..be6673e7ae 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", - "version": "3.2.13", + "version": "3.2.14", "npmClient": "yarn", "concurrency": 20, "command": { From 20df29d78120b37f91ac7d4870b719b6dfb1731b Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Thu, 28 Nov 2024 14:19:45 +0100 Subject: [PATCH 88/88] Update yarn.lock for bb packages --- yarn.lock | 157 ++++++++++++++---------------------------------------- 1 file changed, 40 insertions(+), 117 deletions(-) diff --git a/yarn.lock b/yarn.lock index 90e41f0084..2e7a743310 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2196,7 +2196,7 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@budibase/backend-core@3.2.11": +"@budibase/backend-core@3.2.14": version "0.0.0" dependencies: "@budibase/nano" "10.1.5" @@ -2280,18 +2280,18 @@ through2 "^2.0.0" "@budibase/pro@npm:@budibase/pro@latest": - version "3.2.11" - resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-3.2.11.tgz#40d4929b3958dacca3f4c207718a4647c08a6100" - integrity sha512-xE1tx/C2cnbyR4s/6XkkweoQw6CW5fsQt++gzrrML8abgsODru+tA7M2NbWlKsEnVWHDQRvUVcXm4wqDeNNZ9g== + version "3.2.14" + resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-3.2.14.tgz#2ea1ef4372803304ac3a06ce77620ce54a09dd02" + integrity sha512-ski7NeXOdDIjC0vapo+hxr8/VnbDhmOLF5TdvoLBgviMk7ij2rNPI2dNs+6kQuVXAEVJPD6bJ4Ke0z2d5YcYrQ== dependencies: "@anthropic-ai/sdk" "^0.27.3" - "@budibase/backend-core" "3.2.11" - "@budibase/shared-core" "3.2.11" - "@budibase/string-templates" "3.2.11" - "@budibase/types" "3.2.11" + "@budibase/backend-core" "3.2.14" + "@budibase/shared-core" "3.2.14" + "@budibase/string-templates" "3.2.14" + "@budibase/types" "3.2.14" "@koa/router" "13.1.0" bull "4.10.1" - dd-trace "5.23.0" + dd-trace "5.26.0" joi "17.6.0" jsonwebtoken "9.0.2" lru-cache "^7.14.1" @@ -2301,13 +2301,13 @@ scim-patch "^0.8.1" scim2-parse-filter "^0.2.8" -"@budibase/shared-core@3.2.11": +"@budibase/shared-core@3.2.14": version "0.0.0" dependencies: "@budibase/types" "0.0.0" cron-validate "1.4.5" -"@budibase/string-templates@3.2.11": +"@budibase/string-templates@3.2.14": version "0.0.0" dependencies: "@budibase/handlebars-helpers" "^0.13.2" @@ -2315,7 +2315,7 @@ handlebars "^4.7.8" lodash.clonedeep "^4.5.0" -"@budibase/types@3.2.11": +"@budibase/types@3.2.14": version "0.0.0" dependencies: scim-patch "^0.8.1" @@ -2482,13 +2482,6 @@ resolved "https://registry.yarnpkg.com/@datadog/libdatadog/-/libdatadog-0.2.2.tgz#ac02c76ac9a38250dca740727c7cdf00244ce3d3" integrity sha512-rTWo96mEPTY5UbtGoFj8/wY0uKSViJhsPg/Z6aoFWBFXQ8b45Ix2e/yvf92AAwrhG+gPLTxEqTXh3kef2dP8Ow== -"@datadog/native-appsec@8.1.1": - version "8.1.1" - resolved "https://registry.yarnpkg.com/@datadog/native-appsec/-/native-appsec-8.1.1.tgz#76aa34697e6ecbd3d9ef7e6938d3cdcfa689b1f3" - integrity sha512-mf+Ym/AzET4FeUTXOs8hz0uLOSsVIUnavZPUx8YoKWK5lKgR2L+CLfEzOpjBwgFpDgbV8I1/vyoGelgGpsMKHA== - dependencies: - node-gyp-build "^3.9.0" - "@datadog/native-appsec@8.3.0": version "8.3.0" resolved "https://registry.yarnpkg.com/@datadog/native-appsec/-/native-appsec-8.3.0.tgz#91afd89d18d386be4da8a1b0e04500f2f8b5eb66" @@ -2496,14 +2489,6 @@ dependencies: node-gyp-build "^3.9.0" -"@datadog/native-iast-rewriter@2.4.1": - version "2.4.1" - resolved "https://registry.yarnpkg.com/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.4.1.tgz#e8211f78c818906513fb96a549374da0382c7623" - integrity sha512-j3auTmyyn63e2y+SL28CGNy/l+jXQyh+pxqoGTacWaY5FW/dvo5nGQepAismgJ3qJ8VhQfVWRdxBSiT7wu9clw== - dependencies: - lru-cache "^7.14.0" - node-gyp-build "^4.5.0" - "@datadog/native-iast-rewriter@2.5.0": version "2.5.0" resolved "https://registry.yarnpkg.com/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.5.0.tgz#b613defe86e78168f750d1f1662d4ffb3cf002e6" @@ -2512,13 +2497,6 @@ lru-cache "^7.14.0" node-gyp-build "^4.5.0" -"@datadog/native-iast-taint-tracking@3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-3.1.0.tgz#7b2ed7f8fad212d65e5ab03bcdea8b42a3051b2e" - integrity sha512-rw6qSjmxmu1yFHVvZLXFt/rVq2tUZXocNogPLB8n7MPpA0jijNGb109WokWw5ITImiW91GcGDuBW6elJDVKouQ== - dependencies: - node-gyp-build "^3.9.0" - "@datadog/native-iast-taint-tracking@3.2.0": version "3.2.0" resolved "https://registry.yarnpkg.com/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-3.2.0.tgz#9fb6823d82f934e12c06ea1baa7399ca80deb2ec" @@ -2526,14 +2504,6 @@ dependencies: node-gyp-build "^3.9.0" -"@datadog/native-metrics@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@datadog/native-metrics/-/native-metrics-2.0.0.tgz#65bf03313ee419956361e097551db36173e85712" - integrity sha512-YklGVwUtmKGYqFf1MNZuOHvTYdKuR4+Af1XkWcMD8BwOAjxmd9Z+97328rCOY8TFUJzlGUPaXzB8j2qgG/BMwA== - dependencies: - node-addon-api "^6.1.0" - node-gyp-build "^3.9.0" - "@datadog/native-metrics@^3.0.1": version "3.0.1" resolved "https://registry.yarnpkg.com/@datadog/native-metrics/-/native-metrics-3.0.1.tgz#dc276c93785c0377a048e316f23b7c8ff3acfa84" @@ -2542,17 +2512,6 @@ node-addon-api "^6.1.0" node-gyp-build "^3.9.0" -"@datadog/pprof@5.3.0": - version "5.3.0" - resolved "https://registry.yarnpkg.com/@datadog/pprof/-/pprof-5.3.0.tgz#c2f58d328ecced7f99887f1a559d7fe3aecb9219" - integrity sha512-53z2Q3K92T6Pf4vz4Ezh8kfkVEvLzbnVqacZGgcbkP//q0joFzO8q00Etw1S6NdnCX0XmX08ULaF4rUI5r14mw== - dependencies: - delay "^5.0.0" - node-gyp-build "<4.0" - p-limit "^3.1.0" - pprof-format "^2.1.0" - source-map "^0.7.4" - "@datadog/pprof@5.4.1": version "5.4.1" resolved "https://registry.yarnpkg.com/@datadog/pprof/-/pprof-5.4.1.tgz#08c9bcf5d8efb2eeafdfc9f5bb5402f79fb41266" @@ -3469,16 +3428,6 @@ resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796" integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg== -"@jsep-plugin/assignment@^1.2.1": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@jsep-plugin/assignment/-/assignment-1.3.0.tgz#fcfc5417a04933f7ceee786e8ab498aa3ce2b242" - integrity sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ== - -"@jsep-plugin/regex@^1.0.3": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@jsep-plugin/regex/-/regex-1.0.4.tgz#cb2fc423220fa71c609323b9ba7f7d344a755fcc" - integrity sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg== - "@koa/cors@5.0.0": version "5.0.0" resolved "https://registry.yarnpkg.com/@koa/cors/-/cors-5.0.0.tgz#0029b5f057fa0d0ae0e37dd2c89ece315a0daffd" @@ -9321,43 +9270,6 @@ dc-polyfill@^0.1.4: resolved "https://registry.yarnpkg.com/dc-polyfill/-/dc-polyfill-0.1.6.tgz#c2940fa68ffb24a7bf127cc6cfdd15b39f0e7f02" integrity sha512-UV33cugmCC49a5uWAApM+6Ev9ZdvIUMTrtCO9fj96TPGOQiea54oeO3tiEVdVeo3J9N2UdJEmbS4zOkkEA35uQ== -dd-trace@5.23.0: - version "5.23.0" - resolved "https://registry.yarnpkg.com/dd-trace/-/dd-trace-5.23.0.tgz#a0c11863406de440a6675648caf06e1d07d67ba8" - integrity sha512-nLvwSGpTMIk6S3sMSge6yFqqgqI573VgZc8MF31vl6K0ouJoE7OkVx9cmSVjS4CbSi525tcKq9z7tApsNLpVLQ== - dependencies: - "@datadog/native-appsec" "8.1.1" - "@datadog/native-iast-rewriter" "2.4.1" - "@datadog/native-iast-taint-tracking" "3.1.0" - "@datadog/native-metrics" "^2.0.0" - "@datadog/pprof" "5.3.0" - "@datadog/sketches-js" "^2.1.0" - "@opentelemetry/api" ">=1.0.0 <1.9.0" - "@opentelemetry/core" "^1.14.0" - crypto-randomuuid "^1.0.0" - dc-polyfill "^0.1.4" - ignore "^5.2.4" - import-in-the-middle "1.11.2" - int64-buffer "^0.1.9" - istanbul-lib-coverage "3.2.0" - jest-docblock "^29.7.0" - jsonpath-plus "^9.0.0" - koalas "^1.0.2" - limiter "1.1.5" - lodash.sortby "^4.7.0" - lru-cache "^7.14.0" - module-details-from-path "^1.0.3" - msgpack-lite "^0.1.26" - opentracing ">=0.12.1" - path-to-regexp "^0.1.10" - pprof-format "^2.1.0" - protobufjs "^7.2.5" - retry "^0.13.1" - rfdc "^1.3.1" - semver "^7.5.4" - shell-quote "^1.8.1" - tlhunter-sorted-set "^0.1.0" - dd-trace@5.26.0: version "5.26.0" resolved "https://registry.yarnpkg.com/dd-trace/-/dd-trace-5.26.0.tgz#cc55061f66742bf01d0d7dc9f75c0e4937c82f40" @@ -14128,11 +14040,6 @@ jsdom@^21.1.1: ws "^8.13.0" xml-name-validator "^4.0.0" -jsep@^1.3.8: - version "1.4.0" - resolved "https://registry.yarnpkg.com/jsep/-/jsep-1.4.0.tgz#19feccbfa51d8a79f72480b4b8e40ce2e17152f0" - integrity sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw== - jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -14236,15 +14143,6 @@ jsonparse@^1.2.0, jsonparse@^1.3.1: resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== -jsonpath-plus@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/jsonpath-plus/-/jsonpath-plus-9.0.0.tgz#bb8703ee481531142bca8dee9a42fe72b8358a7f" - integrity sha512-bqE77VIDStrOTV/czspZhTn+o27Xx9ZJRGVkdVShEtPoqsIx5yALv3lWVU6y+PqYvWPJNWE7ORCQheQkEe0DDA== - dependencies: - "@jsep-plugin/assignment" "^1.2.1" - "@jsep-plugin/regex" "^1.0.3" - jsep "^1.3.8" - jsonschema@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.4.0.tgz#1afa34c4bc22190d8e42271ec17ac8b3404f87b2" @@ -20226,7 +20124,16 @@ string-range@~1.2, string-range@~1.2.1: resolved "https://registry.yarnpkg.com/string-range/-/string-range-1.2.2.tgz#a893ed347e72299bc83befbbf2a692a8d239d5dd" integrity sha512-tYft6IFi8SjplJpxCUxyqisD3b+R2CSkomrtJYCkvuf1KuCAWgz7YXt4O0jip7efpfCemwHEzTEAO8EuOYgh3w== -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -20318,7 +20225,7 @@ stringify-object@^3.2.1: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -20332,6 +20239,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" @@ -22153,7 +22067,7 @@ worker-farm@1.7.0: dependencies: errno "~0.1.7" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -22171,6 +22085,15 @@ wrap-ansi@^5.1.0: string-width "^3.0.0" strip-ansi "^5.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"