quickbase-js 0.1.0-beta.10

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 (165) hide show
  1. package/CHANGELOG.md +211 -0
  2. package/LICENSE +21 -0
  3. package/README.md +179 -0
  4. package/api-examples.md +49 -0
  5. package/build-common.js +131 -0
  6. package/build-esm.js +71 -0
  7. package/build-umd.js +69 -0
  8. package/dist/esm/quickbase.d.ts +8081 -0
  9. package/dist/esm/quickbase.js +7928 -0
  10. package/dist/esm/quickbase.js.map +1 -0
  11. package/dist/esm/quickbase.min.js +2 -0
  12. package/dist/esm/quickbase.min.js.map +1 -0
  13. package/dist/umd/quickbase.umd.js +8504 -0
  14. package/dist/umd/quickbase.umd.js.map +1 -0
  15. package/dist/umd/quickbase.umd.min.js +2 -0
  16. package/dist/umd/quickbase.umd.min.js.map +1 -0
  17. package/docs/.vitepress/cache/deps/@theme_index.js +275 -0
  18. package/docs/.vitepress/cache/deps/@theme_index.js.map +7 -0
  19. package/docs/.vitepress/cache/deps/_metadata.json +40 -0
  20. package/docs/.vitepress/cache/deps/chunk-5A67QEFC.js +12542 -0
  21. package/docs/.vitepress/cache/deps/chunk-5A67QEFC.js.map +7 -0
  22. package/docs/.vitepress/cache/deps/chunk-7D4P4MMP.js +9719 -0
  23. package/docs/.vitepress/cache/deps/chunk-7D4P4MMP.js.map +7 -0
  24. package/docs/.vitepress/cache/deps/package.json +3 -0
  25. package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js +4504 -0
  26. package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map +7 -0
  27. package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js +583 -0
  28. package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js.map +7 -0
  29. package/docs/.vitepress/cache/deps/vue.js +343 -0
  30. package/docs/.vitepress/cache/deps/vue.js.map +7 -0
  31. package/docs/.vitepress/config.mts +26 -0
  32. package/docs/api-examples.md +49 -0
  33. package/docs/index.md +59 -0
  34. package/docs/markdown-examples.md +85 -0
  35. package/docs-data/api-docs.json +4143 -0
  36. package/examples/quicbase-jsCDN.html +36 -0
  37. package/examples/react.js +48 -0
  38. package/examples/vanillajs.html +47 -0
  39. package/index.md +25 -0
  40. package/markdown-examples.md +85 -0
  41. package/open-api/fix-spec-main.ts +133 -0
  42. package/open-api/generate-unified-interface.ts +104 -0
  43. package/open-api/generateDocsJson.ts +24 -0
  44. package/open-api/output/quickbase-fixed.json +11191 -0
  45. package/open-api/post-process-generated.ts +226 -0
  46. package/open-api/regenerate-client.ts +117 -0
  47. package/open-api/schema/enhance-general.ts +111 -0
  48. package/open-api/schema/fix-arrays.ts +68 -0
  49. package/open-api/schema/tags/apps.ts +90 -0
  50. package/open-api/schema/tags/fields.ts +471 -0
  51. package/open-api/schema/tags/groups.ts +51 -0
  52. package/open-api/schema/tags/index.ts +66 -0
  53. package/open-api/schema/tags/records.ts +115 -0
  54. package/open-api/schema/tags/tables.ts +211 -0
  55. package/open-api/schema/tags/users.ts +47 -0
  56. package/open-api/types/spec.ts +42 -0
  57. package/open-api/utils/common.ts +29 -0
  58. package/open-api/utils/generateJsDoc.ts +74 -0
  59. package/open-api/utils/infer-schema.ts +40 -0
  60. package/open-api/utils/naming.ts +10 -0
  61. package/open-api/utils/sharedUtils.ts +352 -0
  62. package/package.json +96 -0
  63. package/playwright.config.ts +37 -0
  64. package/rollup.config.js +114 -0
  65. package/specs/QuickBase_RESTful_API_2025-03-04T06_22_39.725Z.json +46878 -0
  66. package/specs/split/apps.json +1315 -0
  67. package/specs/split/auth.json +191 -0
  68. package/specs/split/fields.json +3869 -0
  69. package/specs/split/records.json +754 -0
  70. package/specs/split/reports.json +619 -0
  71. package/specs/split/tables.json +1605 -0
  72. package/src/RateLimitError.ts +12 -0
  73. package/src/ThrottleBucket.ts +41 -0
  74. package/src/authorizationStrategy.ts +283 -0
  75. package/src/generated-unified/QuickbaseClient.ts +1135 -0
  76. package/src/generated-unified/missing-types-report.json +3 -0
  77. package/src/index.ts +1 -0
  78. package/src/invokeMethod.ts +245 -0
  79. package/src/quickbaseClient.ts +194 -0
  80. package/src/rateLimiter.ts +25 -0
  81. package/src/tokenCache.ts +35 -0
  82. package/src/utils.ts +50 -0
  83. package/tests/playwright/qb/auth/cacheSwitching.test.ts +159 -0
  84. package/tests/playwright/qb/auth/fetchTempToken401.test.ts +219 -0
  85. package/tests/playwright/qb/auth/getAppWithTempToken.test.ts +162 -0
  86. package/tests/playwright/qb/auth/getAppWithUserToken.test.ts +153 -0
  87. package/tests/playwright/qb/auth/getTempToken.test.ts +152 -0
  88. package/tests/playwright/qb/auth/tempTokenPrefetch.test.ts +179 -0
  89. package/tests/playwright/qb/auth/tempTokenRenewal.test.ts +133 -0
  90. package/tests/setup.ts +53 -0
  91. package/tests/vitest/qb/apps/copyApp.test.ts +76 -0
  92. package/tests/vitest/qb/apps/createApp.test.ts +64 -0
  93. package/tests/vitest/qb/apps/deleteApp.test.ts +76 -0
  94. package/tests/vitest/qb/apps/getApp.test.ts +44 -0
  95. package/tests/vitest/qb/apps/getAppEvents.test.ts +67 -0
  96. package/tests/vitest/qb/apps/updateApp.test.ts +58 -0
  97. package/tests/vitest/qb/auth/mockQuickbaseServer.ts +60 -0
  98. package/tests/vitest/qb/auth/retryUserToken401.test.ts +73 -0
  99. package/tests/vitest/qb/auth/ssoTokenIntegrationWithServer.test.ts +65 -0
  100. package/tests/vitest/qb/fields/createField.test.ts +77 -0
  101. package/tests/vitest/qb/fields/deleteFields.test.ts +83 -0
  102. package/tests/vitest/qb/fields/getField.test.ts +85 -0
  103. package/tests/vitest/qb/fields/getFieldUsage.test.ts +82 -0
  104. package/tests/vitest/qb/fields/getFields.test.ts +232 -0
  105. package/tests/vitest/qb/fields/getFieldsUsage.test.ts +77 -0
  106. package/tests/vitest/qb/fields/updateField.test.ts +93 -0
  107. package/tests/vitest/qb/formulas/runFormula.test.ts +96 -0
  108. package/tests/vitest/qb/index.ts +29 -0
  109. package/tests/vitest/qb/records/deleteRecords.test.ts +110 -0
  110. package/tests/vitest/qb/records/runQuery.test.ts +146 -0
  111. package/tests/vitest/qb/records/upsert.test.ts +102 -0
  112. package/tests/vitest/qb/tables/createRelationship.test.ts +102 -0
  113. package/tests/vitest/qb/tables/createTable.test.ts +55 -0
  114. package/tests/vitest/qb/tables/deleteRelationship.test.ts +143 -0
  115. package/tests/vitest/qb/tables/deleteTable.test.ts +50 -0
  116. package/tests/vitest/qb/tables/getAppTables.test.ts +46 -0
  117. package/tests/vitest/qb/tables/getRelationships.test.ts +80 -0
  118. package/tests/vitest/qb/tables/getTable.test.ts +26 -0
  119. package/tests/vitest/qb/tables/updateRelationship.test.ts +250 -0
  120. package/tests/vitest/qb/tables/updateTable.test.ts +48 -0
  121. package/tests/vitest/unit/ThrottleBucket.test.ts +95 -0
  122. package/tests/vitest/unit/apps/copyApp.test.ts +581 -0
  123. package/tests/vitest/unit/apps/createApp.test.ts +186 -0
  124. package/tests/vitest/unit/apps/deleteApp.test.ts +216 -0
  125. package/tests/vitest/unit/apps/getApp.test.ts +128 -0
  126. package/tests/vitest/unit/apps/getAppEvents.test.ts +193 -0
  127. package/tests/vitest/unit/apps/updateApp.test.ts +412 -0
  128. package/tests/vitest/unit/auth/fetchTempToken401.test.ts +63 -0
  129. package/tests/vitest/unit/auth/getTempToken.test.ts +119 -0
  130. package/tests/vitest/unit/auth/retryTempToken401.test.ts +95 -0
  131. package/tests/vitest/unit/auth/retryTempTokenMaxRetries.test.ts +206 -0
  132. package/tests/vitest/unit/auth/retryUserToken401.test.ts +69 -0
  133. package/tests/vitest/unit/auth/ssoTokenRefresh.test.ts +325 -0
  134. package/tests/vitest/unit/fields/createField.test.ts +451 -0
  135. package/tests/vitest/unit/fields/deleteFields.test.ts +141 -0
  136. package/tests/vitest/unit/fields/getField.test.ts +189 -0
  137. package/tests/vitest/unit/fields/getFieldUsage.test.ts +180 -0
  138. package/tests/vitest/unit/fields/getFields.test.ts +122 -0
  139. package/tests/vitest/unit/fields/getFieldsUsage.test.ts +160 -0
  140. package/tests/vitest/unit/fields/updateField.test.ts +285 -0
  141. package/tests/vitest/unit/formulas/runFormula.test.ts +205 -0
  142. package/tests/vitest/unit/index.ts +34 -0
  143. package/tests/vitest/unit/quickbaseClientHttpMethods.test.ts +139 -0
  144. package/tests/vitest/unit/rateLimit.test.ts +191 -0
  145. package/tests/vitest/unit/records/deleteRecords.test.ts +112 -0
  146. package/tests/vitest/unit/records/runQuery.test.ts +102 -0
  147. package/tests/vitest/unit/records/upsert.test.ts +234 -0
  148. package/tests/vitest/unit/tables/createRelationship.test.ts +212 -0
  149. package/tests/vitest/unit/tables/createTable.test.ts +70 -0
  150. package/tests/vitest/unit/tables/deleteRelationship.test.ts +97 -0
  151. package/tests/vitest/unit/tables/deleteTable.test.ts +77 -0
  152. package/tests/vitest/unit/tables/getAppTables.test.ts +85 -0
  153. package/tests/vitest/unit/tables/getRelationships.test.ts +259 -0
  154. package/tests/vitest/unit/tables/getTable.test.ts +233 -0
  155. package/tests/vitest/unit/tables/updateRelationship.test.ts +307 -0
  156. package/tests/vitest/unit/tables/updateTable.test.ts +80 -0
  157. package/tests/vitest/unit/tokenLifespan.test.ts +204 -0
  158. package/tests/vitest/unit/umd.test.ts +8 -0
  159. package/tools/log-gen.ts +251 -0
  160. package/tools/log-gen.yaml +4777 -0
  161. package/tools/openapi-jars/openapi-generator-cli-7.12.0.jar +0 -0
  162. package/tsconfig.build.json +17 -0
  163. package/tsconfig.json +32 -0
  164. package/versionrc.json +9 -0
  165. package/vitest.config.ts +27 -0
@@ -0,0 +1,352 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { OpenAPIV2 } from "openapi-types";
4
+ import { join } from "path";
5
+ import { existsSync, readdirSync, readFileSync } from "fs";
6
+ import { Project, PropertySignature, ts } from "ts-morph"; // Import ts from ts-morph
7
+ import { simplifyName } from "../../src/utils.ts";
8
+
9
+ // (Existing interfaces remain unchanged)
10
+ export interface PropertyDetail {
11
+ name: string;
12
+ type: string;
13
+ required: boolean;
14
+ jsdoc?: string;
15
+ properties?: PropertyDetail[];
16
+ }
17
+
18
+ export interface ParamDetail {
19
+ name: string;
20
+ type: string;
21
+ required: boolean;
22
+ properties: PropertyDetail[];
23
+ description?: string;
24
+ }
25
+
26
+ export interface JsDocOptions {
27
+ summary: string;
28
+ opId: string;
29
+ paramDetails: ParamDetail[];
30
+ returnType: string;
31
+ returnTypeDetails: PropertyDetail[];
32
+ docLink: string;
33
+ }
34
+
35
+ export function mapOpenApiTypeToTs(
36
+ openApiType: string | string[] | undefined
37
+ ): string {
38
+ const type = Array.isArray(openApiType)
39
+ ? openApiType[0]
40
+ : openApiType || "any";
41
+ switch (type.toLowerCase()) {
42
+ case "integer":
43
+ case "int":
44
+ case "number":
45
+ return "number";
46
+ case "string":
47
+ return "string";
48
+ case "boolean":
49
+ return "boolean";
50
+ default:
51
+ return "any";
52
+ }
53
+ }
54
+
55
+ export function mapRefToType(
56
+ schema: OpenAPIV2.SchemaObject | OpenAPIV2.ReferenceObject | undefined,
57
+ modelImports: Set<string>,
58
+ spec: OpenAPIV2.Document,
59
+ depth: number = 0,
60
+ availableModels: string[],
61
+ missingTypes: Set<string>
62
+ ): string {
63
+ if (!schema) return "any";
64
+ if ("$ref" in schema && schema.$ref) {
65
+ const refParts = schema.$ref.split("/");
66
+ const model = refParts[refParts.length - 1];
67
+ const pascalModel = model.charAt(0).toUpperCase() + model.slice(1);
68
+ if (availableModels.includes(pascalModel)) {
69
+ modelImports.add(pascalModel);
70
+ return pascalModel;
71
+ }
72
+ missingTypes.add(pascalModel);
73
+ console.warn(`Type ${pascalModel} not found, defaulting to 'any'`);
74
+ return "any";
75
+ }
76
+ if ("type" in schema) {
77
+ if (schema.type === "object" && schema.properties) {
78
+ const props = schema.properties;
79
+ const propTypes = Object.entries(props).map(([key, prop]) => {
80
+ const propSchema = prop as OpenAPIV2.SchemaObject;
81
+ const propType = mapRefToType(
82
+ propSchema,
83
+ modelImports,
84
+ spec,
85
+ depth + 1,
86
+ availableModels,
87
+ missingTypes
88
+ );
89
+ return `${key}${propSchema.required ? "" : "?"}: ${propType}`;
90
+ });
91
+ return `{ ${propTypes.join("; ")} }`;
92
+ }
93
+ if (schema.type === "array" && schema.items) {
94
+ const items = schema.items as
95
+ | OpenAPIV2.SchemaObject
96
+ | OpenAPIV2.ReferenceObject;
97
+ const itemType = mapRefToType(
98
+ items,
99
+ modelImports,
100
+ spec,
101
+ depth + 1,
102
+ availableModels,
103
+ missingTypes
104
+ );
105
+ return `${itemType}[]`;
106
+ }
107
+ return mapOpenApiTypeToTs(schema.type);
108
+ }
109
+ return "any";
110
+ }
111
+
112
+ export function parseInterfaceProperties(
113
+ modelName: string,
114
+ modelsDir: string,
115
+ availableModels?: string[],
116
+ depth: number = 0,
117
+ visited: Set<string> = new Set()
118
+ ): PropertyDetail[] {
119
+ if (availableModels && (depth > 10 || visited.has(modelName))) {
120
+ console.warn(
121
+ `Recursion limit reached or circular reference detected for ${modelName}`
122
+ );
123
+ return [];
124
+ }
125
+ if (availableModels) visited.add(modelName);
126
+
127
+ const project = new Project();
128
+ const filePath = join(modelsDir, `${modelName}.ts`);
129
+ if (!existsSync(filePath)) {
130
+ console.warn(`Model file ${filePath} not found for ${modelName}`);
131
+ return [];
132
+ }
133
+ const sourceFile = project.addSourceFileAtPath(filePath);
134
+
135
+ // Try to get the interface first
136
+ let interfaceDec = sourceFile.getInterface(modelName);
137
+ if (!interfaceDec) {
138
+ // If no interface, check for a type alias (e.g., array type)
139
+ const typeAlias = sourceFile.getTypeAlias(modelName);
140
+ if (typeAlias) {
141
+ const typeNode = typeAlias.getTypeNode();
142
+ if (typeNode && typeNode.getKindName() === "ArrayType") {
143
+ const elementType = typeNode.getFirstChildByKindOrThrow(
144
+ ts.SyntaxKind.TypeReference // Use ts.SyntaxKind from ts-morph
145
+ );
146
+ const innerType = elementType.getText(); // e.g., "GetFields200ResponseItemsInner"
147
+ if (availableModels?.includes(innerType)) {
148
+ console.log(
149
+ `Detected array type alias ${modelName}, parsing inner type ${innerType}`
150
+ );
151
+ // Recursively parse the inner interface
152
+ return parseInterfaceProperties(
153
+ innerType,
154
+ modelsDir,
155
+ availableModels,
156
+ depth + 1,
157
+ visited
158
+ );
159
+ } else {
160
+ console.warn(
161
+ `Inner type ${innerType} not found in available models for ${modelName}`
162
+ );
163
+ return [];
164
+ }
165
+ }
166
+ }
167
+ console.warn(
168
+ `Interface or supported type alias ${modelName} not found in ${filePath}`
169
+ );
170
+ return [];
171
+ }
172
+
173
+ // Parse properties of the interface
174
+ return interfaceDec.getProperties().map((prop: PropertySignature) => {
175
+ const jsDocs = prop.getJsDocs();
176
+ const jsdocText =
177
+ jsDocs.length > 0 ? jsDocs[0].getDescription().trim() : undefined;
178
+ const propType = prop.getType().getText(prop);
179
+ let properties: PropertyDetail[] | undefined = undefined;
180
+
181
+ if (availableModels) {
182
+ const arrayMatch = propType.match(/(.+)\[\]$/);
183
+ if (arrayMatch) {
184
+ const innerType = arrayMatch[1].trim();
185
+ if (availableModels.includes(innerType) && !innerType.includes("[]")) {
186
+ properties = parseInterfaceProperties(
187
+ innerType,
188
+ modelsDir,
189
+ availableModels,
190
+ depth + 1,
191
+ visited
192
+ );
193
+ }
194
+ }
195
+ }
196
+
197
+ return {
198
+ name: prop.getName(),
199
+ type: propType,
200
+ required: !prop.hasQuestionToken(),
201
+ jsdoc: jsdocText,
202
+ properties: properties && properties.length > 0 ? properties : undefined,
203
+ };
204
+ });
205
+ }
206
+
207
+ export interface OperationDoc {
208
+ name: string;
209
+ summary: string;
210
+ method: string;
211
+ path: string;
212
+ parameters: ParamDetail[];
213
+ returns: string;
214
+ returnTypeDetails: PropertyDetail[] | undefined;
215
+ docLink: string;
216
+ }
217
+
218
+ export function parseOpenApiOperations(
219
+ specFile: string,
220
+ modelsDir: string
221
+ ): {
222
+ operations: OperationDoc[];
223
+ modelImports: Set<string>;
224
+ missingTypes: Set<string>;
225
+ } {
226
+ if (!existsSync(specFile)) {
227
+ throw new Error(
228
+ `Spec file ${specFile} not found. Run 'npm run fix-spec' first.`
229
+ );
230
+ }
231
+ const spec: OpenAPIV2.Document = JSON.parse(readFileSync(specFile, "utf8"));
232
+ const availableModels = readdirSync(modelsDir)
233
+ .filter((file) => file.endsWith(".ts") && !file.startsWith("index"))
234
+ .map((file) => file.replace(".ts", ""));
235
+ const modelImports = new Set<string>();
236
+ const missingTypes = new Set<string>();
237
+ const operations: OperationDoc[] = [];
238
+ for (const [path, methodsObj] of Object.entries(
239
+ spec.paths as OpenAPIV2.PathsObject
240
+ )) {
241
+ if (!methodsObj) continue;
242
+ for (const [method, operation] of Object.entries(
243
+ methodsObj as OpenAPIV2.PathItemObject
244
+ )) {
245
+ const op = operation as OpenAPIV2.OperationObject | undefined;
246
+ if (!op || !op.operationId) continue;
247
+ const opId = simplifyName(op.operationId);
248
+ console.log(`Processing operation ${opId} (${method} ${path})`);
249
+ const paramDetails = (op.parameters || [])
250
+ .filter(
251
+ (p) =>
252
+ !["QB-Realm-Hostname", "Authorization", "User-Agent"].includes(
253
+ (p as OpenAPIV2.ParameterObject).name || ""
254
+ )
255
+ )
256
+ .map((p) => {
257
+ const param = p as OpenAPIV2.ParameterObject;
258
+ let type = "any";
259
+ let properties: PropertyDetail[] | undefined = undefined;
260
+ if ("schema" in p && p.schema) {
261
+ type = mapRefToType(
262
+ p.schema,
263
+ modelImports,
264
+ spec,
265
+ 1,
266
+ availableModels,
267
+ missingTypes
268
+ );
269
+ if ("$ref" in p.schema && p.schema.$ref) {
270
+ const refParts = p.schema.$ref.split("/");
271
+ const model = refParts[refParts.length - 1];
272
+ const pascalModel =
273
+ model.charAt(0).toUpperCase() + model.slice(1);
274
+ properties = parseInterfaceProperties(
275
+ pascalModel,
276
+ modelsDir,
277
+ availableModels
278
+ );
279
+ } else if (type !== "any" && availableModels.includes(type)) {
280
+ properties = parseInterfaceProperties(
281
+ type,
282
+ modelsDir,
283
+ availableModels
284
+ );
285
+ }
286
+ } else if ("type" in p) {
287
+ type = mapOpenApiTypeToTs(p.type);
288
+ }
289
+ return {
290
+ name: param.in === "body" ? "body" : param.name,
291
+ type,
292
+ required: param.required || false,
293
+ description: param.description || "",
294
+ properties: properties || [],
295
+ };
296
+ });
297
+ const returnTypes = ["200", "207"]
298
+ .map(
299
+ (code) => (op.responses?.[code] as OpenAPIV2.ResponseObject)?.schema
300
+ )
301
+ .filter(Boolean)
302
+ .map((schema) =>
303
+ mapRefToType(
304
+ schema!,
305
+ modelImports,
306
+ spec,
307
+ 1,
308
+ availableModels,
309
+ missingTypes
310
+ )
311
+ );
312
+ const returnType =
313
+ returnTypes.length > 1
314
+ ? returnTypes.join(" | ")
315
+ : returnTypes[0] || "void";
316
+ const returnTypeDetailsRaw = returnTypes
317
+ .filter((type) => type !== "void" && availableModels.includes(type))
318
+ .map((type) =>
319
+ parseInterfaceProperties(type, modelsDir, availableModels)
320
+ )
321
+ .flat();
322
+ const returnTypeDetails =
323
+ returnTypeDetailsRaw.length > 0
324
+ ? returnTypeDetailsRaw.map((prop) => ({
325
+ ...prop,
326
+ properties:
327
+ prop.properties && prop.properties.length > 0
328
+ ? [...prop.properties]
329
+ : undefined,
330
+ }))
331
+ : undefined;
332
+ operations.push({
333
+ name: opId,
334
+ summary: op.summary || "No description.",
335
+ method: method.toUpperCase(),
336
+ path,
337
+ parameters: paramDetails,
338
+ returns: returnType,
339
+ returnTypeDetails,
340
+ docLink: `https://developer.quickbase.com/operation/${op.operationId}`,
341
+ });
342
+ }
343
+ }
344
+ return { operations, modelImports, missingTypes };
345
+ }
346
+
347
+ // New shared function
348
+ export function getPropertyDescription(prop: PropertyDetail): string {
349
+ return prop.jsdoc
350
+ ? prop.jsdoc.replace(/@type\s*{[^}]+}\s*@memberof\s*\w+/, "").trim()
351
+ : `Type: ${prop.type}`;
352
+ }
package/package.json ADDED
@@ -0,0 +1,96 @@
1
+ {
2
+ "name": "quickbase-js",
3
+ "version": "0.1.0-beta.10",
4
+ "description": "QuickBase JavaScript client for frameworks and vanilla JS",
5
+ "type": "module",
6
+ "main": "dist/esm/quickbase.js",
7
+ "module": "dist/esm/quickbase.js",
8
+ "types": "dist/esm/quickbase.d.ts",
9
+ "publishConfig": {
10
+ "access": "public"
11
+ },
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/esm/quickbase.d.ts",
15
+ "import": {
16
+ "minified": "./dist/esm/quickbase.min.js",
17
+ "default": "./dist/esm/quickbase.js"
18
+ },
19
+ "require": {
20
+ "minified": "./dist/umd/quickbase.umd.min.js",
21
+ "default": "./dist/umd/quickbase.umd.js"
22
+ },
23
+ "umd:types": "./dist/umd/quickbase.umd.d.ts"
24
+ }
25
+ },
26
+ "scripts": {
27
+ "build": "npm run build:esm && npm run build:umd",
28
+ "build:esm": "rimraf dist/esm dist/temp dist/temp-src && node --import 'data:text/javascript,import { register } from \"node:module\"; import { pathToFileURL } from \"node:url\"; register(\"ts-node/esm\", pathToFileURL(\"./\"));' build-esm.js",
29
+ "build:umd": "rimraf dist/umd dist/temp dist/temp-src && node --import 'data:text/javascript,import { register } from \"node:module\"; import { pathToFileURL } from \"node:url\"; register(\"ts-node/esm\", pathToFileURL(\"./\"));' build-umd.js",
30
+ "release": "standard-version",
31
+ "release:beta": "standard-version --prerelease beta",
32
+ "release:alpha": "standard-version --prerelease alpha",
33
+ "release:push": "npm run release:beta && git push --follow-tags origin main",
34
+ "release:publish": "npm run release:push && npm publish --tag beta",
35
+ "release:stable": "standard-version && git push --follow-tags origin main && npm publish",
36
+ "gen:fixspec": "node --import 'data:text/javascript,import { register } from \"node:module\"; import { pathToFileURL } from \"node:url\"; register(\"ts-node/esm\", pathToFileURL(\"./\"));' open-api/fix-spec-main.ts",
37
+ "gen:openapi": "rimraf src/generated && node --import 'data:text/javascript,import { register } from \"node:module\"; import { pathToFileURL } from \"node:url\"; register(\"ts-node/esm\", pathToFileURL(\"./\"));' open-api/regenerate-client.ts",
38
+ "gen:openapi:post": "node --import 'data:text/javascript,import { register } from \"node:module\"; import { pathToFileURL } from \"node:url\"; register(\"ts-node/esm\", pathToFileURL(\"./\"));' open-api/post-process-generated.ts",
39
+ "gen:unified": "node --import 'data:text/javascript,import { register } from \"node:module\"; import { pathToFileURL } from \"node:url\"; register(\"ts-node/esm\", pathToFileURL(\"./\"));' open-api/generate-unified-interface.ts",
40
+ "gen:docsdata": "node --import 'data:text/javascript,import { register } from \"node:module\"; import { pathToFileURL } from \"node:url\"; register(\"ts-node/esm\", pathToFileURL(\"./\"));' open-api/generateDocsJson.ts",
41
+ "docs:dev": "vitepress dev docs",
42
+ "docs:build": "vitepress build docs",
43
+ "docs:preview": "vitepress preview docs",
44
+ "gen:all": "npm run gen:fixspec && npm run gen:openapi && npm run gen:openapi:post && npm run gen:unified && npm run gen:docsdata && npm run docs:build",
45
+ "log-gen": "node --import 'data:text/javascript,import { register } from \"node:module\"; import { pathToFileURL } from \"node:url\"; register(\"ts-node/esm\", pathToFileURL(\"./\"));' tools/log-gen.ts",
46
+ "test:all": "vitest run tests/vitest/**/**/*.test.ts --reporter=basic && playwright test tests/playwright/qb --config playwright.config.ts --reporter=dot --quiet",
47
+ "test:pw:qb:all": "playwright test tests/playwright/qb --config playwright.config.ts",
48
+ "test:vitest:all": "vitest run tests/vitest/**/**/*.test.ts",
49
+ "test:vitest:qb": "vitest run tests/vitest/qb/**/*.test.ts",
50
+ "test:vitest:unit": "vitest run tests/vitest/unit/**/*.test.ts",
51
+ "test:vitest:qb:apps": "vitest run tests/vitest/qb/apps/*.test.ts",
52
+ "test:vitest:qb:auth": "vitest run tests/vitest/qb/auth/*.test.ts",
53
+ "test:vitest:qb:fields": "vitest run tests/vitest/qb/fields/*.test.ts",
54
+ "test:vitest:qb:records": "vitest run tests/vitest/qb/records/*.test.ts",
55
+ "test:vitest:qb:tables": "vitest run tests/vitest/qb/tables/*.test.ts",
56
+ "test:vitest:unit:apps": "vitest run tests/vitest/unit/apps/*.test.ts",
57
+ "test:vitest:unit:auth": "vitest run tests/vitest/unit/auth/*.test.ts",
58
+ "test:vitest:unit:fields": "vitest run tests/vitest/unit/fields/*.test.ts",
59
+ "test:vitest:unit:formulas": "vitest run tests/vitest/unit/formulas/*.test.ts",
60
+ "test:vitest:unit:records": "vitest run tests/vitest/unit/records/*.test.ts",
61
+ "test:vitest:unit:tables": "vitest run tests/vitest/unit/tables/*.test.ts",
62
+ "test:pw:qb:auth": "playwright test tests/playwright/qb/auth"
63
+ },
64
+ "devDependencies": {
65
+ "@openapitools/openapi-generator-cli": "^2.18.4",
66
+ "@playwright/test": "^1.51.0",
67
+ "@rollup/plugin-commonjs": "^28.0.3",
68
+ "@rollup/plugin-node-resolve": "^16.0.1",
69
+ "@rollup/plugin-terser": "^0.4.4",
70
+ "@rollup/plugin-typescript": "^12.1.2",
71
+ "@types/fast-json-patch": "^1.0.4",
72
+ "@types/js-yaml": "^4.0.9",
73
+ "@types/node": "^22.13.10",
74
+ "dotenv": "^16.4.7",
75
+ "express": "^4.21.2",
76
+ "fast-json-patch": "^3.1.1",
77
+ "glob": "^10.4.5",
78
+ "js-yaml": "^4.1.0",
79
+ "jsdom": "^26.0.0",
80
+ "node-fetch": "^3.3.2",
81
+ "openapi-schema-validator": "^12.1.3",
82
+ "openapi-types": "^12.1.3",
83
+ "openapi-typescript": "^7.6.1",
84
+ "rimraf": "^5.0.10",
85
+ "rollup": "^4.35.0",
86
+ "rollup-plugin-dts": "^6.1.1",
87
+ "standard-version": "^9.5.0",
88
+ "ts-morph": "^25.0.1",
89
+ "ts-node": "^10.9.2",
90
+ "tslib": "^2.8.1",
91
+ "typescript": "^5.8.2",
92
+ "undici-types": "^7.5.0",
93
+ "vitepress": "^1.6.3",
94
+ "vitest": "^3.0.8"
95
+ }
96
+ }
@@ -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: Testing temp token authorization in browser. Be patient, this could take at least 5min. Workers: ${
33
+ config.workers || "default (half CPU cores)"
34
+ }`
35
+ );
36
+
37
+ export default config;
@@ -0,0 +1,114 @@
1
+ import terser from "@rollup/plugin-terser";
2
+ import nodeResolve from "@rollup/plugin-node-resolve";
3
+ import commonjs from "@rollup/plugin-commonjs";
4
+ import dts from "rollup-plugin-dts";
5
+ import typescript from "@rollup/plugin-typescript";
6
+
7
+ const isProd = process.env.NODE_ENV === "production";
8
+
9
+ // External dependencies for both ESM and UMD builds
10
+ const external = [
11
+ "node:http",
12
+ "node:https",
13
+ "node:zlib",
14
+ "node:stream",
15
+ "node:buffer",
16
+ "node:util",
17
+ "node:url",
18
+ "node:net",
19
+ "node:fs",
20
+ "node:path",
21
+ "node-fetch",
22
+ ];
23
+
24
+ // Global mappings for UMD (browser) build
25
+ const globals = {
26
+ "node-fetch": "fetch", // Map node-fetch to window.fetch in browsers
27
+ };
28
+
29
+ export default [
30
+ // ESM Build
31
+ {
32
+ input: "src/quickbaseClient.ts",
33
+ output: {
34
+ dir: "dist/esm",
35
+ format: "esm",
36
+ sourcemap: true,
37
+ entryFileNames: "quickbase.js",
38
+ },
39
+ external,
40
+ plugins: [
41
+ nodeResolve({ preferBuiltins: true }), // Node.js resolution
42
+ commonjs(), // Convert CommonJS to ESM
43
+ typescript({
44
+ tsconfig: "./tsconfig.json",
45
+ noEmitOnError: true, // Fail on TypeScript errors
46
+ // Use Rollup to emit JavaScript, overriding noEmit for this build
47
+ }),
48
+ isProd && terser(), // Minification for production
49
+ ],
50
+ },
51
+ // UMD Build
52
+ {
53
+ input: "src/quickbaseClient.ts",
54
+ output: {
55
+ file: "dist/umd/quickbase.umd.js",
56
+ format: "umd",
57
+ name: "QuickbaseJS", // Global name for browser
58
+ sourcemap: true,
59
+ globals,
60
+ },
61
+ external,
62
+ plugins: [
63
+ nodeResolve({ preferBuiltins: true, browser: true }), // Browser-first resolution
64
+ commonjs(), // Convert CommonJS to UMD
65
+ typescript({
66
+ tsconfig: "./tsconfig.json",
67
+ noEmitOnError: true, // Fail on TypeScript errors
68
+ // Use Rollup to emit JavaScript, overriding noEmit for this build
69
+ }),
70
+ isProd && terser(), // Minification for production
71
+ ],
72
+ },
73
+ // ESM Declarations
74
+ {
75
+ input: "src/quickbaseClient.ts",
76
+ output: {
77
+ file: "dist/esm/quickbase.d.ts",
78
+ format: "esm",
79
+ },
80
+ plugins: [
81
+ dts({
82
+ tsconfig: "./tsconfig.json",
83
+ respectExternal: true, // Include external dependencies in declarations
84
+ }),
85
+ ],
86
+ },
87
+ // UMD Declarations
88
+ {
89
+ input: "src/quickbaseClient.ts",
90
+ output: {
91
+ file: "dist/umd/quickbase.umd.d.ts",
92
+ format: "umd",
93
+ },
94
+ plugins: [
95
+ dts({
96
+ tsconfig: "./tsconfig.json",
97
+ respectExternal: true, // Include external dependencies in declarations
98
+ }),
99
+ ],
100
+ },
101
+ ].map((config) => ({
102
+ ...config,
103
+ onwarn(warning, warn) {
104
+ // Suppress TypeScript plugin warnings
105
+ if (
106
+ warning.code === "PLUGIN_WARNING" &&
107
+ warning.plugin === "typescript" &&
108
+ warning.message.includes("TS5096")
109
+ ) {
110
+ return;
111
+ }
112
+ warn(warning);
113
+ },
114
+ }));