quickbase-js 1.0.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +21 -0
  3. package/README.md +102 -0
  4. package/build.js +66 -0
  5. package/dist/quickbaseClient.d.ts +3888 -0
  6. package/dist/quickbaseClient.js +5812 -0
  7. package/dist/quickbaseClient.js.map +1 -0
  8. package/examples/react.js +22 -0
  9. package/examples/vanillajs.html +23 -0
  10. package/logGen.yaml +1820 -0
  11. package/package.json +72 -0
  12. package/playwright.config.ts +37 -0
  13. package/rollup.config.js +70 -0
  14. package/src/code-generation/fix-spec-definitions.ts +136 -0
  15. package/src/code-generation/fix-spec-main.ts +176 -0
  16. package/src/code-generation/fix-spec-paths.ts +163 -0
  17. package/src/code-generation/generate-unified-interface.ts +152 -0
  18. package/src/code-generation/output/quickbase-fixed.json +8435 -0
  19. package/src/code-generation/regenerate-client.ts +110 -0
  20. package/src/generated-unified/QuickbaseClient.ts +59 -0
  21. package/src/index.ts +1 -0
  22. package/src/log-gen.ts +122 -0
  23. package/src/quickbaseClient.ts +320 -0
  24. package/src/specs/QuickBase_RESTful_API_2025-03-04T06_22_39.725Z.json +46878 -0
  25. package/src/tokenCache.ts +51 -0
  26. package/src/utils.ts +5 -0
  27. package/test-artifacts/.last-run.json +4 -0
  28. package/test-artifacts/test-results.json +1801 -0
  29. package/test-results.json +2050 -0
  30. package/tests/playwright/qb/auth/cacheSwitching.test.ts +189 -0
  31. package/tests/playwright/qb/auth/fetchTempToken401.test.ts +217 -0
  32. package/tests/playwright/qb/auth/getAppWithUserToken.test.ts +151 -0
  33. package/tests/playwright/qb/auth/getTempToken.test.ts +180 -0
  34. package/tests/playwright/qb/auth/tokenPrefetch.test.ts +192 -0
  35. package/tests/playwright/qb/auth/tokenRenewal.test.ts +110 -0
  36. package/tests/setup.ts +19 -0
  37. package/tests/vitest/qb/apps/getApp.test.ts +46 -0
  38. package/tests/vitest/qb/fields/getFields.test.ts +234 -0
  39. package/tests/vitest/qb/index.ts +4 -0
  40. package/tests/vitest/qb/tables/getAppTables.test.ts +67 -0
  41. package/tests/vitest/unit/apps/getApp.test.ts +81 -0
  42. package/tests/vitest/unit/auth/fetchTempToken401.test.ts +59 -0
  43. package/tests/vitest/unit/auth/getTempToken.test.ts +83 -0
  44. package/tests/vitest/unit/auth/retryOn401.test.ts +72 -0
  45. package/tests/vitest/unit/auth/two401s.test.ts +77 -0
  46. package/tests/vitest/unit/fields/getFields.test.ts +115 -0
  47. package/tests/vitest/unit/index.ts +4 -0
  48. package/tests/vitest/unit/tables/getAppTables.test.ts +72 -0
  49. package/text.txt +104 -0
  50. package/tsconfig.json +28 -0
  51. package/versionrc.json +9 -0
  52. package/vitest.config.ts +21 -0
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "quickbase-js",
3
+ "main": "dist/quickbaseClient.js",
4
+ "types": "dist/quickbaseClient.d.ts",
5
+ "version": "1.0.1-beta.0",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "description": "QuickBase JavaScript client for frameworks and vanilla JS",
10
+ "module": "dist/quickbaseClient.js",
11
+ "type": "module",
12
+ "exports": {
13
+ ".": {
14
+ "import": "./dist/quickbaseClient.js",
15
+ "types": "./dist/quickbaseClient.d.ts"
16
+ }
17
+ },
18
+ "scripts": {
19
+ "release": "standard-version",
20
+ "release:beta": "standard-version --prerelease beta",
21
+ "release:alpha": "standard-version --prerelease alpha",
22
+ "fix-spec": "node --loader ts-node/esm src/code-generation/fix-spec-main.ts",
23
+ "regenerate": "node --loader ts-node/esm src/code-generation/regenerate-client.ts",
24
+ "generate-unified": "node --loader ts-node/esm src/code-generation/generate-unified-interface.ts",
25
+ "log-gen": "node --loader ts-node/esm src/log-gen.ts",
26
+ "build": "rimraf dist && rollup -c",
27
+ "build:prod": "rm -rf dist/* && NODE_ENV=production rollup -c",
28
+ "test": "vitest run tests/vitest/**/**/*.test.ts",
29
+ "test:pw:qb:all": "playwright test tests/playwright/qb --config playwright.config.ts",
30
+ "test:vitest:qb": "vitest run tests/vitest/qb/**/*.test.ts",
31
+ "test:vitest:qb:apps": "vitest run tests/vitest/qb/apps/**/*.test.ts",
32
+ "test:vitest:qb:auth": "vitest run tests/vitest/qb/auth/**/*.test.ts",
33
+ "test:vitest:qb:fields": "vitest run tests/vitest/qb/fields/**/*.test.ts",
34
+ "test:vitest:qb:tables": "vitest run tests/vitest/qb/tables/**/*.test.ts",
35
+ "test:pw:qb:auth": "playwright test tests/playwright/qb/auth",
36
+ "test::pw:qb:auth:temptoken": "playwright test tests/playwright/qb/auth/getTempToken.test.ts",
37
+ "test:pw:qb:auth:renewal": "playwright test tests/playwright/qb/auth/tokenRenewal.test.ts",
38
+ "test:pw:qb:auth:cache": "playwright test tests/playwright/qb/auth/cacheSwitching.test.ts",
39
+ "test:pw:qb:auth:temp401": "playwright test tests/playwright/qb/auth/fetchTempToken401.test.ts",
40
+ "test:pw:qb:auth:prefetch": "playwright test tests/playwright/qb/auth/tokenPrefetch.test.ts",
41
+ "test:pw:qb:auth:debug": "playwright test tests/playwright/qb/auth --headed --debug",
42
+ "test:pw:qb:auth:temp:debug": "playwright test tests/playwright/qb/auth/getTempToken.test.ts --headed --debug",
43
+ "test:pw:qb:auth:renewal:debug": "playwright test tests/playwright/qb/auth/tokenRenewal.test.ts --headed --debug --config=playwright.config.ts",
44
+ "test:pw:qb:auth:cache:debug": "playwright test tests/playwright/qb/auth/cacheSwitching.test.ts --headed --debug"
45
+ },
46
+ "dependencies": {
47
+ "typescript": "^5.8.2"
48
+ },
49
+ "devDependencies": {
50
+ "@openapitools/openapi-generator-cli": "^2.17.0",
51
+ "@playwright/test": "^1.51.0",
52
+ "@rollup/plugin-commonjs": "^28.0.3",
53
+ "@rollup/plugin-node-resolve": "^16.0.0",
54
+ "@rollup/plugin-terser": "^0.4.4",
55
+ "@rollup/plugin-typescript": "^12.1.2",
56
+ "@types/node": "^22.13.10",
57
+ "dotenv": "^16.4.7",
58
+ "glob": "^11.0.1",
59
+ "js-yaml": "^4.1.0",
60
+ "jsdom": "^26.0.0",
61
+ "node-fetch": "^3.3.2",
62
+ "openapi-types": "^12.1.3",
63
+ "rimraf": "^5.0.10",
64
+ "rollup": "^4.35.0",
65
+ "rollup-plugin-dts": "^6.1.1",
66
+ "standard-version": "^9.5.0",
67
+ "ts-morph": "^25.0.1",
68
+ "ts-node": "^10.9.2",
69
+ "tslib": "^2.8.1",
70
+ "vitest": "^3.0.8"
71
+ }
72
+ }
@@ -0,0 +1,37 @@
1
+ // playwright.config.ts
2
+ import { defineConfig, devices } from "@playwright/test";
3
+
4
+ const config = defineConfig({
5
+ fullyParallel: true,
6
+ workers: undefined, // Default: half of CPU cores (e.g., 2 on a 4-core machine)
7
+ // workers: 2, // Or explicitly set to 2 for controlled testing
8
+ testDir: "./tests/playwright",
9
+ timeout: 600000, // 10 minutes
10
+ retries: 2,
11
+ reporter: [
12
+ ["list"],
13
+ ["json", { outputFile: "test-artifacts/test-results.json" }],
14
+ ],
15
+ use: {
16
+ baseURL: "https://api.quickbase.com",
17
+ headless: true,
18
+ viewport: { width: 1280, height: 720 },
19
+ actionTimeout: 10000,
20
+ screenshot: "off",
21
+ },
22
+ outputDir: "test-artifacts",
23
+ projects: [
24
+ {
25
+ name: "chromium",
26
+ use: { ...devices["Desktop Chrome"] },
27
+ },
28
+ ],
29
+ });
30
+
31
+ console.log(
32
+ `Loading Playwright config with timeout: ${config.timeout}ms, workers: ${
33
+ config.workers || "default (half CPU cores)"
34
+ }`
35
+ );
36
+
37
+ export default config;
@@ -0,0 +1,70 @@
1
+ import typescript from "@rollup/plugin-typescript";
2
+ import terser from "@rollup/plugin-terser";
3
+ import nodeResolve from "@rollup/plugin-node-resolve";
4
+ import commonjs from "@rollup/plugin-commonjs";
5
+ import dts from "rollup-plugin-dts";
6
+
7
+ const isProd = process.env.NODE_ENV === "production";
8
+
9
+ export default [
10
+ {
11
+ input: "src/quickbaseClient.ts",
12
+ output: {
13
+ dir: "dist",
14
+ format: "esm",
15
+ sourcemap: true,
16
+ compact: isProd,
17
+ entryFileNames: "quickbaseClient.js",
18
+ },
19
+ external: [
20
+ "node:http",
21
+ "node:https",
22
+ "node:zlib",
23
+ "node:stream",
24
+ "node:buffer",
25
+ "node:util",
26
+ "node:url",
27
+ "node:net",
28
+ "node:fs",
29
+ "node:path",
30
+ "node-fetch",
31
+ ],
32
+ plugins: [
33
+ nodeResolve({ preferBuiltins: true }),
34
+ commonjs(),
35
+ typescript({
36
+ tsconfig: "./tsconfig.json",
37
+ declaration: false, // No .d.ts here, handled by dts plugin
38
+ }),
39
+ isProd && terser(),
40
+ ],
41
+ },
42
+ {
43
+ input: "src/quickbaseClient.ts",
44
+ output: {
45
+ file: "dist/quickbaseClient.d.ts",
46
+ format: "esm",
47
+ // Optional: sourcemap for .d.ts if needed for debugging
48
+ // sourcemap: true,
49
+ },
50
+ plugins: [
51
+ dts({
52
+ tsconfig: "./tsconfig.json",
53
+ // Ensure all referenced files are included
54
+ respectExternal: true,
55
+ }),
56
+ ],
57
+ },
58
+ ].map((config) => ({
59
+ ...config,
60
+ onwarn(warning, warn) {
61
+ if (
62
+ warning.code === "PLUGIN_WARNING" &&
63
+ warning.plugin === "typescript" &&
64
+ warning.message.includes("TS5096")
65
+ ) {
66
+ return;
67
+ }
68
+ warn(warning);
69
+ },
70
+ }));
@@ -0,0 +1,136 @@
1
+ export const definitions = {
2
+ App: {
3
+ type: "object",
4
+ properties: {
5
+ id: { type: "string" },
6
+ name: { type: "string" },
7
+ created: { type: "string", format: "date-time" },
8
+ updated: { type: "string", format: "date-time" },
9
+ description: { type: "string" },
10
+ timeZone: { type: "string" },
11
+ dateFormat: { type: "string" },
12
+ hasEveryoneOnTheInternet: { type: "boolean" },
13
+ memoryInfo: {
14
+ type: "object",
15
+ properties: {
16
+ estMemory: { type: "number" },
17
+ estMemoryInclDependentApps: { type: "number" },
18
+ },
19
+ },
20
+ securityProperties: {
21
+ type: "object",
22
+ properties: {
23
+ allowClone: { type: "boolean" },
24
+ allowExport: { type: "boolean" },
25
+ enableAppTokens: { type: "boolean" },
26
+ hideFromPublic: { type: "boolean" },
27
+ mustBeRealmApproved: { type: "boolean" },
28
+ useIPFilter: { type: "boolean" },
29
+ },
30
+ },
31
+ },
32
+ required: ["id", "name"],
33
+ },
34
+ Field: {
35
+ type: "object",
36
+ properties: {
37
+ id: { type: "number" },
38
+ label: { type: "string" },
39
+ fieldType: { type: "string" },
40
+ noWrap: { type: "boolean" },
41
+ bold: { type: "boolean" },
42
+ required: { type: "boolean" },
43
+ appearsByDefault: { type: "boolean" },
44
+ findEnabled: { type: "boolean" },
45
+ unique: { type: "boolean" },
46
+ doesDataCopy: { type: "boolean" },
47
+ fieldHelp: { type: "string" },
48
+ audited: { type: "boolean" },
49
+ properties: {
50
+ type: "object",
51
+ properties: {
52
+ primaryKey: { type: "boolean" },
53
+ foreignKey: { type: "boolean" },
54
+ numLines: { type: "number" },
55
+ maxLength: { type: "number" },
56
+ appendOnly: { type: "boolean" },
57
+ allowHTML: { type: "boolean" },
58
+ allowMentions: { type: "boolean" },
59
+ sortAsGiven: { type: "boolean" },
60
+ carryChoices: { type: "boolean" },
61
+ allowNewChoices: { type: "boolean" },
62
+ formula: { type: "string" },
63
+ defaultValue: { type: "string" },
64
+ },
65
+ },
66
+ permissions: {
67
+ type: "array",
68
+ items: {
69
+ type: "object",
70
+ properties: {
71
+ permissionType: { type: "string" },
72
+ role: { type: "string" },
73
+ roleId: { type: "number" },
74
+ },
75
+ },
76
+ },
77
+ },
78
+ required: ["id", "label", "fieldType"],
79
+ },
80
+ Table: {
81
+ type: "object",
82
+ properties: {
83
+ id: { type: "string" },
84
+ name: { type: "string" },
85
+ alias: { type: "string" },
86
+ created: { type: "string", format: "date-time" },
87
+ defaultSortFieldId: { type: "number" },
88
+ defaultSortOrder: { type: "string" },
89
+ description: { type: "string" },
90
+ keyFieldId: { type: "number" },
91
+ nextFieldId: { type: "number" },
92
+ nextRecordId: { type: "number" },
93
+ pluralRecordName: { type: "string" },
94
+ singleRecordName: { type: "string" },
95
+ sizeLimit: { type: "string" },
96
+ spaceRemaining: { type: "string" },
97
+ spaceUsed: { type: "string" },
98
+ updated: { type: "string", format: "date-time" },
99
+ },
100
+ required: ["id", "name"],
101
+ },
102
+ Record: {
103
+ type: "object",
104
+ properties: {
105
+ id: { type: "number" },
106
+ fields: {
107
+ type: "object",
108
+ additionalProperties: { type: "string" },
109
+ },
110
+ },
111
+ required: ["id"],
112
+ },
113
+ Upsert200Response: {
114
+ type: "object",
115
+ properties: {
116
+ id: { type: "number" },
117
+ status: { type: "string" },
118
+ },
119
+ required: ["id"],
120
+ },
121
+ ReportRunResponse: {
122
+ type: "object",
123
+ properties: {
124
+ id: { type: "string" },
125
+ data: { type: "object" }, // Placeholder
126
+ },
127
+ required: ["id"],
128
+ },
129
+ GetTempTokenDBID200Response: {
130
+ type: "object",
131
+ properties: {
132
+ temporaryAuthorization: { type: "string" },
133
+ },
134
+ required: ["temporaryAuthorization"],
135
+ },
136
+ };
@@ -0,0 +1,176 @@
1
+ #!/usr/bin/env node
2
+ import { promises as fs } from "fs";
3
+ import path from "path";
4
+ import { fileURLToPath } from "url";
5
+ import * as glob from "glob";
6
+ import { paths } from "./fix-spec-paths.ts";
7
+ import { definitions } from "./fix-spec-definitions.ts";
8
+
9
+ interface Parameter {
10
+ name: string;
11
+ in: string;
12
+ required?: boolean;
13
+ type?: string;
14
+ schema?: { type?: string; items?: any; $ref?: string; properties?: any };
15
+ example?: any;
16
+ }
17
+
18
+ interface Operation {
19
+ parameters?: Parameter[];
20
+ responses?: Record<string, { description: string; schema?: any }>;
21
+ operationId?: string;
22
+ summary?: string;
23
+ tags?: string[];
24
+ }
25
+
26
+ interface Spec {
27
+ paths: Record<string, Record<string, Operation>>;
28
+ definitions?: Record<string, any>;
29
+ operations?: any;
30
+ groups?: any;
31
+ components?: any;
32
+ }
33
+
34
+ function toCamelCase(str: string): string {
35
+ return str
36
+ .replace(/[-_](.)/g, (_, char) => char.toUpperCase())
37
+ .replace(/^./, (str) => str.toLowerCase());
38
+ }
39
+
40
+ function fixArraySchemas(spec: Spec) {
41
+ for (const pathKey in spec.paths) {
42
+ for (const method in spec.paths[pathKey]) {
43
+ const operation = spec.paths[pathKey][method];
44
+ if (operation.parameters) {
45
+ operation.parameters.forEach((param: Parameter) => {
46
+ if (param.schema) {
47
+ if (param.schema.type === "array" && !param.schema.items) {
48
+ console.log(
49
+ `Fixing missing items in ${pathKey}(${method}).${param.name}`
50
+ );
51
+ param.schema.items =
52
+ pathKey === "/records" && param.name === "generated"
53
+ ? { $ref: "#/definitions/Record" }
54
+ : { type: "string" };
55
+ }
56
+ if (param.schema.properties) {
57
+ for (const propKey in param.schema.properties) {
58
+ const prop = param.schema.properties[propKey];
59
+ if (prop.type === "array" && !prop.items) {
60
+ console.log(
61
+ `Fixing nested array in ${pathKey}(${method}).${param.name}.${propKey}`
62
+ );
63
+ prop.items =
64
+ propKey === "data" && pathKey === "/records"
65
+ ? { $ref: "#/definitions/Record" }
66
+ : { type: "string" };
67
+ }
68
+ }
69
+ }
70
+ }
71
+ });
72
+ }
73
+ if (operation.responses) {
74
+ for (const status in operation.responses) {
75
+ const response = operation.responses[status];
76
+ if (response.schema) {
77
+ if (response.schema.type === "array" && !response.schema.items) {
78
+ console.log(
79
+ `Fixing missing items in ${pathKey}(${method}).responses.${status}`
80
+ );
81
+ response.schema.items =
82
+ pathKey === "/records"
83
+ ? { $ref: "#/definitions/Upsert200Response" }
84
+ : { type: "string" };
85
+ }
86
+ if (response.schema.properties) {
87
+ for (const propKey in response.schema.properties) {
88
+ const prop = response.schema.properties[propKey];
89
+ if (prop.type === "array" && !prop.items) {
90
+ console.log(
91
+ `Fixing nested array in ${pathKey}(${method}).responses.${status}.${propKey}`
92
+ );
93
+ prop.items =
94
+ propKey === "data" && pathKey === "/records"
95
+ ? { $ref: "#/definitions/Upsert200Response" }
96
+ : { type: "string" };
97
+ }
98
+ }
99
+ }
100
+ }
101
+ }
102
+ }
103
+ }
104
+ }
105
+ }
106
+
107
+ async function fixQuickBaseSpec(): Promise<void> {
108
+ try {
109
+ const CODEGEN_DIR = path.dirname(fileURLToPath(import.meta.url));
110
+ const SPECS_DIR = path.join(CODEGEN_DIR, "..", "specs");
111
+ const OUTPUT_DIR = path.join(CODEGEN_DIR, "output");
112
+ console.log("Finding latest QuickBase RESTful API spec...");
113
+ const specFiles = glob.sync(
114
+ path.join(SPECS_DIR, "QuickBase_RESTful_*.json")
115
+ );
116
+ if (specFiles.length === 0) {
117
+ console.error(
118
+ "No QuickBase_RESTful_*.json files found in specs/ folder."
119
+ );
120
+ process.exit(1);
121
+ }
122
+ const inputFile = specFiles.sort().pop() as string;
123
+ const outputFile = path.join(OUTPUT_DIR, "quickbase-fixed.json");
124
+
125
+ console.log(`Reading ${path.basename(inputFile)} from specs/...`);
126
+ const specContent = await fs.readFile(inputFile, "utf8");
127
+ const spec: Spec = JSON.parse(specContent);
128
+
129
+ console.log("Fixing parameters...");
130
+ for (const pathKey in spec.paths) {
131
+ for (const method in spec.paths[pathKey]) {
132
+ const operation = spec.paths[pathKey][method];
133
+ if (operation.parameters) {
134
+ operation.parameters = operation.parameters
135
+ .filter(
136
+ (param) =>
137
+ !["QB-Realm-Hostname", "Authorization", "User-Agent"].includes(
138
+ param.name
139
+ )
140
+ )
141
+ .map((param: Parameter) => {
142
+ param.name = toCamelCase(param.name);
143
+ if ("example" in param) delete param.example;
144
+ if ("schema" in param && param.in !== "body") delete param.schema;
145
+ if (!param.type && param.in !== "body") param.type = "string";
146
+ return param;
147
+ });
148
+ }
149
+ }
150
+ }
151
+
152
+ console.log("Applying endpoint fixes...");
153
+ spec.paths = { ...spec.paths, ...paths }; // Merge original and custom paths
154
+
155
+ console.log("Fixing array schemas...");
156
+ fixArraySchemas(spec);
157
+
158
+ console.log("Applying definitions...");
159
+ spec.definitions = { ...spec.definitions, ...definitions }; // Merge definitions
160
+
161
+ console.log("Removing unexpected top-level attributes...");
162
+ delete spec.operations;
163
+ delete spec.groups;
164
+ delete spec.components;
165
+
166
+ console.log(`Writing fixed spec to ${path.basename(outputFile)}...`);
167
+ await fs.mkdir(OUTPUT_DIR, { recursive: true });
168
+ await fs.writeFile(outputFile, JSON.stringify(spec, null, 2), "utf8");
169
+ console.log("Spec fixed successfully!");
170
+ } catch (error) {
171
+ console.error("Failed to fix spec:", error);
172
+ process.exit(1);
173
+ }
174
+ }
175
+
176
+ fixQuickBaseSpec();
@@ -0,0 +1,163 @@
1
+ // src/code-generation/fix-spec-paths.ts
2
+ export const paths = {
3
+ "/apps/{appId}": {
4
+ get: {
5
+ operationId: "getApp",
6
+ summary: "Get an app by ID",
7
+ tags: ["Apps"],
8
+ parameters: [
9
+ {
10
+ name: "appId",
11
+ in: "path",
12
+ required: true,
13
+ type: "string",
14
+ },
15
+ ],
16
+ responses: {
17
+ 200: {
18
+ description: "Success",
19
+ schema: { $ref: "#/definitions/App" },
20
+ },
21
+ },
22
+ },
23
+ },
24
+ "/fields": {
25
+ get: {
26
+ operationId: "getFields",
27
+ summary: "Get all fields for a table",
28
+ tags: ["Fields"],
29
+ parameters: [
30
+ {
31
+ name: "tableId",
32
+ in: "query",
33
+ required: true,
34
+ type: "string",
35
+ },
36
+ {
37
+ name: "includeFieldPerms",
38
+ in: "query",
39
+ required: false,
40
+ type: "boolean",
41
+ },
42
+ ],
43
+ responses: {
44
+ 200: {
45
+ description: "Success",
46
+ schema: {
47
+ type: "array",
48
+ items: { $ref: "#/definitions/Field" },
49
+ },
50
+ },
51
+ },
52
+ },
53
+ },
54
+ "/tables": {
55
+ get: {
56
+ operationId: "getAppTables",
57
+ summary: "Get all tables for an app",
58
+ tags: ["Tables"],
59
+ parameters: [
60
+ {
61
+ name: "appId",
62
+ in: "query",
63
+ required: true,
64
+ type: "string",
65
+ },
66
+ ],
67
+ responses: {
68
+ 200: {
69
+ description: "Success",
70
+ schema: {
71
+ type: "array",
72
+ items: { $ref: "#/definitions/Table" },
73
+ },
74
+ },
75
+ },
76
+ },
77
+ },
78
+ "/records/query": {
79
+ post: {
80
+ operationId: "upsertRecords",
81
+ summary: "Upsert records",
82
+ tags: ["Records"],
83
+ parameters: [
84
+ {
85
+ name: "generated",
86
+ in: "body",
87
+ required: true,
88
+ schema: {
89
+ type: "array",
90
+ items: { $ref: "#/definitions/Record" },
91
+ },
92
+ },
93
+ ],
94
+ responses: {
95
+ 200: {
96
+ description: "Success",
97
+ schema: {
98
+ type: "array",
99
+ items: { $ref: "#/definitions/Upsert200Response" },
100
+ },
101
+ },
102
+ 207: {
103
+ description: "Multi-Status (partial success)",
104
+ schema: {
105
+ type: "array",
106
+ items: { $ref: "#/definitions/Upsert207Response" }, // Corrected from Upsert200Response
107
+ },
108
+ },
109
+ },
110
+ },
111
+ },
112
+ "/reports/{reportId}/run": {
113
+ post: {
114
+ operationId: "runReport",
115
+ summary: "Run a report",
116
+ tags: ["Reports"],
117
+ parameters: [
118
+ {
119
+ name: "reportId",
120
+ in: "path",
121
+ required: true,
122
+ type: "string",
123
+ },
124
+ {
125
+ name: "generated",
126
+ in: "body",
127
+ required: true,
128
+ schema: { type: "object" },
129
+ },
130
+ ],
131
+ responses: {
132
+ 200: {
133
+ description: "Success",
134
+ schema: {
135
+ type: "array",
136
+ items: { $ref: "#/definitions/ReportRunResponse" },
137
+ },
138
+ },
139
+ },
140
+ },
141
+ },
142
+ "/auth/temporary/{dbid}": {
143
+ get: {
144
+ operationId: "getTempTokenDBID",
145
+ summary: "Get a temporary authorization token for a specific dbid",
146
+ tags: ["Auth"],
147
+ parameters: [
148
+ {
149
+ name: "dbid",
150
+ in: "path",
151
+ required: true,
152
+ type: "string",
153
+ },
154
+ ],
155
+ responses: {
156
+ 200: {
157
+ description: "Success",
158
+ schema: { $ref: "#/definitions/GetTempTokenDBID200Response" },
159
+ },
160
+ },
161
+ },
162
+ },
163
+ };