quickbase-js 1.1.0-beta.0 → 1.1.0-beta.2
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.
- package/CHANGELOG.md +16 -0
- package/dist/quickbase.d.ts +356 -6
- package/dist/quickbase.js +363 -20
- package/dist/quickbase.js.map +1 -1
- package/examples/react.js +42 -16
- package/examples/vanillajs.html +32 -8
- package/log-gen.yaml +146 -198
- package/package.json +4 -4
- package/src/code-generation/fix-spec-definitions.ts +99 -41
- package/src/code-generation/fix-spec-paths.ts +6 -19
- package/src/code-generation/generate-unified-interface.ts +1 -8
- package/src/code-generation/output/quickbase-fixed.json +142 -21
- package/src/generated-unified/QuickbaseClient.ts +3 -3
- package/tests/playwright/qb/auth/cacheSwitching.test.ts +2 -2
- package/tests/setup.ts +29 -9
- package/tests/vitest/qb/fields/getFields.test.ts +3 -5
- package/tests/vitest/qb/records/runQuery.test.ts +82 -0
- package/tests/vitest/unit/apps/getApp.test.ts +17 -12
- package/tests/vitest/unit/auth/fetchTempToken401.test.ts +29 -4
- package/tests/vitest/unit/auth/getTempToken.test.ts +30 -17
- package/tests/vitest/unit/auth/retryOn401.test.ts +39 -5
- package/tests/vitest/unit/fields/getFields.test.ts +14 -7
- package/tests/vitest/unit/records/deleteRecords.test.ts +28 -34
- package/tests/vitest/unit/records/runQuery.test.ts +102 -0
- package/tests/vitest/unit/records/upsert.test.ts +31 -41
- package/tests/vitest/unit/tables/createTable.test.ts +18 -10
- package/tests/vitest/unit/tables/deleteTable.test.ts +28 -19
- package/tests/vitest/unit/tables/getAppTables.test.ts +41 -28
- package/tests/vitest/unit/tables/getTable.test.ts +53 -32
- package/tests/vitest/unit/tables/updateTable.test.ts +17 -11
- package/vitest.config.ts +5 -0
|
@@ -79,10 +79,7 @@ export const definitions = {
|
|
|
79
79
|
type: "string",
|
|
80
80
|
description: "The unique identifier for this application.",
|
|
81
81
|
},
|
|
82
|
-
name: {
|
|
83
|
-
type: "string",
|
|
84
|
-
description: "The app name.",
|
|
85
|
-
},
|
|
82
|
+
name: { type: "string", description: "The app name." },
|
|
86
83
|
description: {
|
|
87
84
|
type: "string",
|
|
88
85
|
description: "The description for the app.",
|
|
@@ -197,10 +194,7 @@ export const definitions = {
|
|
|
197
194
|
type: "string",
|
|
198
195
|
description: "The unique identifier (dbid) of the table.",
|
|
199
196
|
},
|
|
200
|
-
name: {
|
|
201
|
-
type: "string",
|
|
202
|
-
description: "The name of the table.",
|
|
203
|
-
},
|
|
197
|
+
name: { type: "string", description: "The name of the table." },
|
|
204
198
|
alias: {
|
|
205
199
|
type: "string",
|
|
206
200
|
description: "The automatically-created table alias for the table.",
|
|
@@ -275,10 +269,7 @@ export const definitions = {
|
|
|
275
269
|
UpdateTableRequest: {
|
|
276
270
|
type: "object",
|
|
277
271
|
properties: {
|
|
278
|
-
name: {
|
|
279
|
-
type: "string",
|
|
280
|
-
description: "The new name for the table.",
|
|
281
|
-
},
|
|
272
|
+
name: { type: "string", description: "The new name for the table." },
|
|
282
273
|
singleRecordName: {
|
|
283
274
|
type: "string",
|
|
284
275
|
description:
|
|
@@ -301,10 +292,7 @@ export const definitions = {
|
|
|
301
292
|
DeleteTableResponse: {
|
|
302
293
|
type: "object",
|
|
303
294
|
properties: {
|
|
304
|
-
deletedTableId: {
|
|
305
|
-
type: "string",
|
|
306
|
-
description: "The deleted table id.",
|
|
307
|
-
},
|
|
295
|
+
deletedTableId: { type: "string", description: "The deleted table id." },
|
|
308
296
|
},
|
|
309
297
|
},
|
|
310
298
|
Record: {
|
|
@@ -358,9 +346,7 @@ export const definitions = {
|
|
|
358
346
|
type: "object",
|
|
359
347
|
additionalProperties: {
|
|
360
348
|
type: "object",
|
|
361
|
-
properties: {
|
|
362
|
-
value: { type: "any" },
|
|
363
|
-
},
|
|
349
|
+
properties: { value: { type: "any" } },
|
|
364
350
|
},
|
|
365
351
|
},
|
|
366
352
|
description: "Array of upserted records with field IDs and values.",
|
|
@@ -401,9 +387,7 @@ export const definitions = {
|
|
|
401
387
|
type: "object",
|
|
402
388
|
additionalProperties: {
|
|
403
389
|
type: "object",
|
|
404
|
-
properties: {
|
|
405
|
-
value: { type: "any" },
|
|
406
|
-
},
|
|
390
|
+
properties: { value: { type: "any" } },
|
|
407
391
|
},
|
|
408
392
|
},
|
|
409
393
|
description: "Array of successfully upserted records (may be empty).",
|
|
@@ -411,29 +395,15 @@ export const definitions = {
|
|
|
411
395
|
metadata: {
|
|
412
396
|
type: "object",
|
|
413
397
|
properties: {
|
|
414
|
-
createdRecordIds: {
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
},
|
|
418
|
-
updatedRecordIds: {
|
|
419
|
-
type: "array",
|
|
420
|
-
items: { type: "integer" },
|
|
421
|
-
},
|
|
422
|
-
unchangedRecordIds: {
|
|
423
|
-
type: "array",
|
|
424
|
-
items: { type: "integer" },
|
|
425
|
-
},
|
|
398
|
+
createdRecordIds: { type: "array", items: { type: "integer" } },
|
|
399
|
+
updatedRecordIds: { type: "array", items: { type: "integer" } },
|
|
400
|
+
unchangedRecordIds: { type: "array", items: { type: "integer" } },
|
|
426
401
|
lineErrors: {
|
|
427
402
|
type: "object",
|
|
428
|
-
additionalProperties: {
|
|
429
|
-
type: "array",
|
|
430
|
-
items: { type: "string" },
|
|
431
|
-
},
|
|
403
|
+
additionalProperties: { type: "array", items: { type: "string" } },
|
|
432
404
|
description: "Errors by line number (1-based index).",
|
|
433
405
|
},
|
|
434
|
-
totalNumberOfRecordsProcessed: {
|
|
435
|
-
type: "integer",
|
|
436
|
-
},
|
|
406
|
+
totalNumberOfRecordsProcessed: { type: "integer" },
|
|
437
407
|
},
|
|
438
408
|
required: ["totalNumberOfRecordsProcessed"],
|
|
439
409
|
},
|
|
@@ -482,4 +452,92 @@ export const definitions = {
|
|
|
482
452
|
required: ["numberDeleted"],
|
|
483
453
|
description: "Response body for successful deletion of records.",
|
|
484
454
|
},
|
|
455
|
+
RunQueryRequest: {
|
|
456
|
+
type: "object",
|
|
457
|
+
required: ["from"],
|
|
458
|
+
properties: {
|
|
459
|
+
from: { type: "string", description: "Table ID (dbid)" },
|
|
460
|
+
select: {
|
|
461
|
+
type: "array",
|
|
462
|
+
items: { type: "integer" },
|
|
463
|
+
description: "Field IDs to return",
|
|
464
|
+
},
|
|
465
|
+
where: { type: "string", description: "Query string" },
|
|
466
|
+
sortBy: {
|
|
467
|
+
type: "array",
|
|
468
|
+
items: {
|
|
469
|
+
type: "object",
|
|
470
|
+
properties: {
|
|
471
|
+
fieldId: { type: "integer" },
|
|
472
|
+
order: { type: "string", enum: ["ASC", "DESC"] },
|
|
473
|
+
},
|
|
474
|
+
},
|
|
475
|
+
description: "Sort criteria",
|
|
476
|
+
},
|
|
477
|
+
groupBy: {
|
|
478
|
+
type: "array",
|
|
479
|
+
items: {
|
|
480
|
+
type: "object",
|
|
481
|
+
properties: {
|
|
482
|
+
fieldId: { type: "integer" },
|
|
483
|
+
grouping: { type: "string", enum: ["equal-values"] },
|
|
484
|
+
},
|
|
485
|
+
},
|
|
486
|
+
description: "Grouping criteria",
|
|
487
|
+
},
|
|
488
|
+
options: {
|
|
489
|
+
type: "object",
|
|
490
|
+
properties: {
|
|
491
|
+
skip: { type: "integer", description: "Number of records to skip" },
|
|
492
|
+
top: {
|
|
493
|
+
type: "integer",
|
|
494
|
+
description: "Max number of records to return",
|
|
495
|
+
},
|
|
496
|
+
compareWithAppLocalTime: {
|
|
497
|
+
type: "boolean",
|
|
498
|
+
description: "Compare times with app local time",
|
|
499
|
+
},
|
|
500
|
+
},
|
|
501
|
+
},
|
|
502
|
+
},
|
|
503
|
+
},
|
|
504
|
+
RunQueryResponse: {
|
|
505
|
+
type: "object",
|
|
506
|
+
properties: {
|
|
507
|
+
data: {
|
|
508
|
+
type: "array",
|
|
509
|
+
items: {
|
|
510
|
+
type: "object",
|
|
511
|
+
additionalProperties: {
|
|
512
|
+
type: "object",
|
|
513
|
+
properties: { value: { type: "any" } },
|
|
514
|
+
},
|
|
515
|
+
},
|
|
516
|
+
description: "Array of record data with field IDs as keys",
|
|
517
|
+
},
|
|
518
|
+
fields: {
|
|
519
|
+
type: "array",
|
|
520
|
+
items: {
|
|
521
|
+
type: "object",
|
|
522
|
+
properties: {
|
|
523
|
+
id: { type: "integer" },
|
|
524
|
+
label: { type: "string" },
|
|
525
|
+
type: { type: "string" },
|
|
526
|
+
},
|
|
527
|
+
},
|
|
528
|
+
description: "Field metadata",
|
|
529
|
+
},
|
|
530
|
+
metadata: {
|
|
531
|
+
type: "object",
|
|
532
|
+
properties: {
|
|
533
|
+
numFields: { type: "integer" },
|
|
534
|
+
numRecords: { type: "integer" },
|
|
535
|
+
skip: { type: "integer" },
|
|
536
|
+
top: { type: "integer" },
|
|
537
|
+
totalRecords: { type: "integer" },
|
|
538
|
+
},
|
|
539
|
+
description: "Query metadata",
|
|
540
|
+
},
|
|
541
|
+
},
|
|
542
|
+
},
|
|
485
543
|
};
|
|
@@ -280,34 +280,21 @@ export const paths = {
|
|
|
280
280
|
},
|
|
281
281
|
"/records/query": {
|
|
282
282
|
post: {
|
|
283
|
-
operationId: "
|
|
284
|
-
summary: "
|
|
283
|
+
operationId: "runQuery",
|
|
284
|
+
summary: "Query records in a table",
|
|
285
285
|
tags: ["Records"],
|
|
286
286
|
parameters: [
|
|
287
287
|
{
|
|
288
|
-
name: "
|
|
288
|
+
name: "body",
|
|
289
289
|
in: "body",
|
|
290
290
|
required: true,
|
|
291
|
-
schema: {
|
|
292
|
-
type: "array",
|
|
293
|
-
items: { $ref: "#/definitions/Record" },
|
|
294
|
-
},
|
|
291
|
+
schema: { $ref: "#/definitions/RunQueryRequest" },
|
|
295
292
|
},
|
|
296
293
|
],
|
|
297
294
|
responses: {
|
|
298
295
|
200: {
|
|
299
|
-
description: "Success",
|
|
300
|
-
schema: {
|
|
301
|
-
type: "array",
|
|
302
|
-
items: { $ref: "#/definitions/Upsert200Response" },
|
|
303
|
-
},
|
|
304
|
-
},
|
|
305
|
-
207: {
|
|
306
|
-
description: "Multi-Status (partial success)",
|
|
307
|
-
schema: {
|
|
308
|
-
type: "array",
|
|
309
|
-
items: { $ref: "#/definitions/Upsert207Response" },
|
|
310
|
-
},
|
|
296
|
+
description: "Success - records returned",
|
|
297
|
+
schema: { $ref: "#/definitions/RunQueryResponse" },
|
|
311
298
|
},
|
|
312
299
|
},
|
|
313
300
|
},
|
|
@@ -48,20 +48,15 @@ function generateInterface() {
|
|
|
48
48
|
})
|
|
49
49
|
.map((p) => {
|
|
50
50
|
const param = p as OpenAPIV2.ParameterObject;
|
|
51
|
-
|
|
51
|
+
const type = param.type
|
|
52
52
|
? mapOpenApiTypeToTs(param.type)
|
|
53
53
|
: param.schema
|
|
54
54
|
? mapRefToType(param.schema, modelImports)
|
|
55
55
|
: "any";
|
|
56
|
-
// Special handling for upsertRecords 'generated' parameter
|
|
57
|
-
if (opId === "upsertRecords" && param.name === "generated") {
|
|
58
|
-
type = "{ [key: string]: string }[]";
|
|
59
|
-
}
|
|
60
56
|
return `${param.name}${param.required ? "" : "?"}: ${type}`;
|
|
61
57
|
})
|
|
62
58
|
.join("; ");
|
|
63
59
|
|
|
64
|
-
// Handle responses, ensuring distinct types for 200 and 207
|
|
65
60
|
const successResponses = ["200", "207"]
|
|
66
61
|
.map((code) => ({
|
|
67
62
|
code,
|
|
@@ -73,7 +68,6 @@ function generateInterface() {
|
|
|
73
68
|
const returnTypes = successResponses.map(({ response }) =>
|
|
74
69
|
mapRefToType(response!.schema, modelImports)
|
|
75
70
|
);
|
|
76
|
-
// Deduplicate return types and join with " | ", default to "void" if empty
|
|
77
71
|
const uniqueReturnTypes = [...new Set(returnTypes)];
|
|
78
72
|
const returnType =
|
|
79
73
|
uniqueReturnTypes.length > 0 ? uniqueReturnTypes.join(" | ") : "void";
|
|
@@ -84,7 +78,6 @@ function generateInterface() {
|
|
|
84
78
|
}
|
|
85
79
|
}
|
|
86
80
|
|
|
87
|
-
// Generate import statements for all model types
|
|
88
81
|
const importStatement =
|
|
89
82
|
modelImports.size > 0
|
|
90
83
|
? `import { ${Array.from(modelImports)
|
|
@@ -4095,41 +4095,26 @@
|
|
|
4095
4095
|
},
|
|
4096
4096
|
"/records/query": {
|
|
4097
4097
|
"post": {
|
|
4098
|
-
"operationId": "
|
|
4099
|
-
"summary": "
|
|
4098
|
+
"operationId": "runQuery",
|
|
4099
|
+
"summary": "Query records in a table",
|
|
4100
4100
|
"tags": [
|
|
4101
4101
|
"Records"
|
|
4102
4102
|
],
|
|
4103
4103
|
"parameters": [
|
|
4104
4104
|
{
|
|
4105
|
-
"name": "
|
|
4105
|
+
"name": "body",
|
|
4106
4106
|
"in": "body",
|
|
4107
4107
|
"required": true,
|
|
4108
4108
|
"schema": {
|
|
4109
|
-
"
|
|
4110
|
-
"items": {
|
|
4111
|
-
"$ref": "#/definitions/Record"
|
|
4112
|
-
}
|
|
4109
|
+
"$ref": "#/definitions/RunQueryRequest"
|
|
4113
4110
|
}
|
|
4114
4111
|
}
|
|
4115
4112
|
],
|
|
4116
4113
|
"responses": {
|
|
4117
4114
|
"200": {
|
|
4118
|
-
"description": "Success",
|
|
4119
|
-
"schema": {
|
|
4120
|
-
"type": "array",
|
|
4121
|
-
"items": {
|
|
4122
|
-
"$ref": "#/definitions/Upsert200Response"
|
|
4123
|
-
}
|
|
4124
|
-
}
|
|
4125
|
-
},
|
|
4126
|
-
"207": {
|
|
4127
|
-
"description": "Multi-Status (partial success)",
|
|
4115
|
+
"description": "Success - records returned",
|
|
4128
4116
|
"schema": {
|
|
4129
|
-
"
|
|
4130
|
-
"items": {
|
|
4131
|
-
"$ref": "#/definitions/Upsert207Response"
|
|
4132
|
-
}
|
|
4117
|
+
"$ref": "#/definitions/RunQueryResponse"
|
|
4133
4118
|
}
|
|
4134
4119
|
}
|
|
4135
4120
|
}
|
|
@@ -7954,6 +7939,142 @@
|
|
|
7954
7939
|
"numberDeleted"
|
|
7955
7940
|
],
|
|
7956
7941
|
"description": "Response body for successful deletion of records."
|
|
7942
|
+
},
|
|
7943
|
+
"RunQueryRequest": {
|
|
7944
|
+
"type": "object",
|
|
7945
|
+
"required": [
|
|
7946
|
+
"from"
|
|
7947
|
+
],
|
|
7948
|
+
"properties": {
|
|
7949
|
+
"from": {
|
|
7950
|
+
"type": "string",
|
|
7951
|
+
"description": "Table ID (dbid)"
|
|
7952
|
+
},
|
|
7953
|
+
"select": {
|
|
7954
|
+
"type": "array",
|
|
7955
|
+
"items": {
|
|
7956
|
+
"type": "integer"
|
|
7957
|
+
},
|
|
7958
|
+
"description": "Field IDs to return"
|
|
7959
|
+
},
|
|
7960
|
+
"where": {
|
|
7961
|
+
"type": "string",
|
|
7962
|
+
"description": "Query string"
|
|
7963
|
+
},
|
|
7964
|
+
"sortBy": {
|
|
7965
|
+
"type": "array",
|
|
7966
|
+
"items": {
|
|
7967
|
+
"type": "object",
|
|
7968
|
+
"properties": {
|
|
7969
|
+
"fieldId": {
|
|
7970
|
+
"type": "integer"
|
|
7971
|
+
},
|
|
7972
|
+
"order": {
|
|
7973
|
+
"type": "string",
|
|
7974
|
+
"enum": [
|
|
7975
|
+
"ASC",
|
|
7976
|
+
"DESC"
|
|
7977
|
+
]
|
|
7978
|
+
}
|
|
7979
|
+
}
|
|
7980
|
+
},
|
|
7981
|
+
"description": "Sort criteria"
|
|
7982
|
+
},
|
|
7983
|
+
"groupBy": {
|
|
7984
|
+
"type": "array",
|
|
7985
|
+
"items": {
|
|
7986
|
+
"type": "object",
|
|
7987
|
+
"properties": {
|
|
7988
|
+
"fieldId": {
|
|
7989
|
+
"type": "integer"
|
|
7990
|
+
},
|
|
7991
|
+
"grouping": {
|
|
7992
|
+
"type": "string",
|
|
7993
|
+
"enum": [
|
|
7994
|
+
"equal-values"
|
|
7995
|
+
]
|
|
7996
|
+
}
|
|
7997
|
+
}
|
|
7998
|
+
},
|
|
7999
|
+
"description": "Grouping criteria"
|
|
8000
|
+
},
|
|
8001
|
+
"options": {
|
|
8002
|
+
"type": "object",
|
|
8003
|
+
"properties": {
|
|
8004
|
+
"skip": {
|
|
8005
|
+
"type": "integer",
|
|
8006
|
+
"description": "Number of records to skip"
|
|
8007
|
+
},
|
|
8008
|
+
"top": {
|
|
8009
|
+
"type": "integer",
|
|
8010
|
+
"description": "Max number of records to return"
|
|
8011
|
+
},
|
|
8012
|
+
"compareWithAppLocalTime": {
|
|
8013
|
+
"type": "boolean",
|
|
8014
|
+
"description": "Compare times with app local time"
|
|
8015
|
+
}
|
|
8016
|
+
}
|
|
8017
|
+
}
|
|
8018
|
+
}
|
|
8019
|
+
},
|
|
8020
|
+
"RunQueryResponse": {
|
|
8021
|
+
"type": "object",
|
|
8022
|
+
"properties": {
|
|
8023
|
+
"data": {
|
|
8024
|
+
"type": "array",
|
|
8025
|
+
"items": {
|
|
8026
|
+
"type": "object",
|
|
8027
|
+
"additionalProperties": {
|
|
8028
|
+
"type": "object",
|
|
8029
|
+
"properties": {
|
|
8030
|
+
"value": {
|
|
8031
|
+
"type": "any"
|
|
8032
|
+
}
|
|
8033
|
+
}
|
|
8034
|
+
}
|
|
8035
|
+
},
|
|
8036
|
+
"description": "Array of record data with field IDs as keys"
|
|
8037
|
+
},
|
|
8038
|
+
"fields": {
|
|
8039
|
+
"type": "array",
|
|
8040
|
+
"items": {
|
|
8041
|
+
"type": "object",
|
|
8042
|
+
"properties": {
|
|
8043
|
+
"id": {
|
|
8044
|
+
"type": "integer"
|
|
8045
|
+
},
|
|
8046
|
+
"label": {
|
|
8047
|
+
"type": "string"
|
|
8048
|
+
},
|
|
8049
|
+
"type": {
|
|
8050
|
+
"type": "string"
|
|
8051
|
+
}
|
|
8052
|
+
}
|
|
8053
|
+
},
|
|
8054
|
+
"description": "Field metadata"
|
|
8055
|
+
},
|
|
8056
|
+
"metadata": {
|
|
8057
|
+
"type": "object",
|
|
8058
|
+
"properties": {
|
|
8059
|
+
"numFields": {
|
|
8060
|
+
"type": "integer"
|
|
8061
|
+
},
|
|
8062
|
+
"numRecords": {
|
|
8063
|
+
"type": "integer"
|
|
8064
|
+
},
|
|
8065
|
+
"skip": {
|
|
8066
|
+
"type": "integer"
|
|
8067
|
+
},
|
|
8068
|
+
"top": {
|
|
8069
|
+
"type": "integer"
|
|
8070
|
+
},
|
|
8071
|
+
"totalRecords": {
|
|
8072
|
+
"type": "integer"
|
|
8073
|
+
}
|
|
8074
|
+
},
|
|
8075
|
+
"description": "Query metadata"
|
|
8076
|
+
}
|
|
8077
|
+
}
|
|
7957
8078
|
}
|
|
7958
8079
|
}
|
|
7959
8080
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
// Generated on 2025-03-
|
|
2
|
-
import { App, CreateApp200Response, CreateAppRequest, DeleteRecords200Response, DeleteRecordsRequest, DeleteTableResponse, Field, GetTempTokenDBID200Response,
|
|
1
|
+
// Generated on 2025-03-11T14:12:45.650Z
|
|
2
|
+
import { App, CreateApp200Response, CreateAppRequest, DeleteRecords200Response, DeleteRecordsRequest, DeleteTableResponse, Field, GetTempTokenDBID200Response, ReportRunResponse, RunQueryRequest, RunQueryResponse, Table, UpdateTableRequest, Upsert200Response, Upsert207Response, UpsertRequest } from "../generated/models";
|
|
3
3
|
|
|
4
4
|
export interface QuickbaseClient {
|
|
5
5
|
createApp: (params: { body: CreateAppRequest }) => Promise<CreateApp200Response>;
|
|
@@ -26,7 +26,7 @@ export interface QuickbaseClient {
|
|
|
26
26
|
runFormula: (params: { generated?: any }) => Promise<{ [key: string]: any }>;
|
|
27
27
|
upsert: (params: { body: UpsertRequest }) => Promise<Upsert200Response | Upsert207Response>;
|
|
28
28
|
deleteRecords: (params: { body: DeleteRecordsRequest }) => Promise<DeleteRecords200Response>;
|
|
29
|
-
|
|
29
|
+
runQuery: (params: { body: RunQueryRequest }) => Promise<RunQueryResponse>;
|
|
30
30
|
getTempTokenDBID: (params: { dbid: string }) => Promise<GetTempTokenDBID200Response>;
|
|
31
31
|
exchangeSsoToken: (params: { generated?: any }) => Promise<{ [key: string]: any }>;
|
|
32
32
|
cloneUserToken: (params: { generated?: any }) => Promise<{ [key: string]: any }>;
|
|
@@ -67,13 +67,13 @@ test.describe("QuickbaseClient Integration - Cache Switching with Temp Tokens",
|
|
|
67
67
|
console.log("Starting cacheSwitching test");
|
|
68
68
|
const realm = process.env.QB_REALM;
|
|
69
69
|
const appId = process.env.QB_APP_ID;
|
|
70
|
-
const tableId = process.env.
|
|
70
|
+
const tableId = process.env.QB_TABLE_ID_1;
|
|
71
71
|
const username = process.env.QB_USERNAME;
|
|
72
72
|
const password = process.env.QB_PASSWORD;
|
|
73
73
|
|
|
74
74
|
if (!realm) throw new Error("QB_REALM is not defined in .env");
|
|
75
75
|
if (!appId) throw new Error("QB_APP_ID is not defined in .env");
|
|
76
|
-
if (!tableId) throw new Error("
|
|
76
|
+
if (!tableId) throw new Error("QB_TABLE_ID_1 is not defined in .env");
|
|
77
77
|
if (!username) throw new Error("QB_USERNAME is not defined in .env");
|
|
78
78
|
if (!password) throw new Error("QB_PASSWORD is not defined in .env");
|
|
79
79
|
|
package/tests/setup.ts
CHANGED
|
@@ -2,26 +2,46 @@
|
|
|
2
2
|
import { vi } from "vitest";
|
|
3
3
|
import { quickbase } from "../src/quickbaseClient.ts";
|
|
4
4
|
import type { QuickbaseConfig } from "../src/quickbaseClient.ts";
|
|
5
|
+
import dotenv from "dotenv";
|
|
6
|
+
|
|
7
|
+
// Load environment variables from .env file
|
|
8
|
+
dotenv.config({ path: "./.env" }); // Assumes .env is at project root
|
|
5
9
|
|
|
6
10
|
export const mockFetch = vi.fn();
|
|
7
11
|
|
|
12
|
+
export const QB_REALM = process.env.QB_REALM || "test-realm";
|
|
13
|
+
export const QB_USER_TOKEN =
|
|
14
|
+
process.env.QB_USER_TOKEN || "user-token-1234567890";
|
|
15
|
+
export const QB_APP_ID = process.env.QB_APP_ID || "app-id-1234567890";
|
|
16
|
+
export const QB_TABLE_ID_1 = process.env.QB_TABLE_ID_1 || "table-id-1234567890";
|
|
17
|
+
|
|
18
|
+
// Mock env variables for consistency, using .env values if available
|
|
19
|
+
vi.stubEnv("QB_REALM", QB_REALM);
|
|
20
|
+
vi.stubEnv("QB_USER_TOKEN", QB_USER_TOKEN);
|
|
21
|
+
vi.stubEnv("QB_APP_ID", QB_APP_ID);
|
|
22
|
+
vi.stubEnv("QB_TABLE_ID_1", QB_TABLE_ID_1);
|
|
23
|
+
|
|
8
24
|
export const createClient = (
|
|
9
25
|
fetchApi?: any,
|
|
10
26
|
config: Partial<QuickbaseConfig> = {}
|
|
11
27
|
) => {
|
|
28
|
+
// Use loaded env vars with fallbacks for safety
|
|
29
|
+
const realm = QB_REALM;
|
|
30
|
+
const userToken = QB_USER_TOKEN;
|
|
31
|
+
|
|
12
32
|
const client = quickbase({
|
|
13
|
-
realm
|
|
14
|
-
userToken
|
|
33
|
+
realm,
|
|
34
|
+
userToken,
|
|
15
35
|
debug: true,
|
|
16
36
|
fetchApi,
|
|
37
|
+
...config, // Allow overrides if provided
|
|
38
|
+
});
|
|
39
|
+
console.log("[createClient] Config:", {
|
|
40
|
+
realm,
|
|
41
|
+
userToken,
|
|
42
|
+
debug: true,
|
|
17
43
|
...config,
|
|
18
44
|
});
|
|
19
|
-
console.log("[createClient]
|
|
20
|
-
console.log("[createClient] Returning:", client); // Debug client
|
|
45
|
+
console.log("[createClient] Returning:", client);
|
|
21
46
|
return client;
|
|
22
47
|
};
|
|
23
|
-
|
|
24
|
-
// Mock env variables for consistency
|
|
25
|
-
vi.stubEnv("QB_REALM", "builderprogram-dbradford6815");
|
|
26
|
-
vi.stubEnv("QB_USER_TOKEN", "b9f3pk_q4jd_0_b4qu5eebyvuix3xs57ysd7zn3");
|
|
27
|
-
vi.stubEnv("QB_APP_ID", "buwai2zpe");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { createClient } from "../../../setup.ts";
|
|
2
|
+
import { createClient, QB_TABLE_ID_1 } from "../../../setup.ts";
|
|
3
3
|
|
|
4
4
|
describe("QuickbaseClient Integration - getFields", () => {
|
|
5
5
|
const client = createClient();
|
|
@@ -7,8 +7,6 @@ describe("QuickbaseClient Integration - getFields", () => {
|
|
|
7
7
|
it(
|
|
8
8
|
"fetches real field data from QuickBase",
|
|
9
9
|
async () => {
|
|
10
|
-
const tableId = "buwai2z3s";
|
|
11
|
-
if (!tableId) throw new Error("Table ID is not defined");
|
|
12
10
|
if (!process.env.QB_REALM)
|
|
13
11
|
throw new Error("QB_REALM is not defined in .env");
|
|
14
12
|
if (!process.env.QB_USER_TOKEN)
|
|
@@ -17,10 +15,10 @@ describe("QuickbaseClient Integration - getFields", () => {
|
|
|
17
15
|
console.log("Config used:", {
|
|
18
16
|
realm: process.env.QB_REALM,
|
|
19
17
|
userToken: process.env.QB_USER_TOKEN,
|
|
20
|
-
tableId,
|
|
18
|
+
tableId: QB_TABLE_ID_1,
|
|
21
19
|
});
|
|
22
20
|
const result = await client.getFields({
|
|
23
|
-
tableId,
|
|
21
|
+
tableId: QB_TABLE_ID_1,
|
|
24
22
|
includeFieldPerms: true,
|
|
25
23
|
});
|
|
26
24
|
console.log("Real API response:", result);
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// tests/vitest/qb/records/runQuery.test.ts
|
|
2
|
+
import { describe, it, expect } from "vitest";
|
|
3
|
+
import { createClient, QB_TABLE_ID_1 } from "../../../setup.ts"; // Import QB_TABLE_ID_1
|
|
4
|
+
import { RunQueryRequest, RunQueryResponse } from "@/generated/models";
|
|
5
|
+
|
|
6
|
+
describe("QuickbaseClient Integration - runQuery", () => {
|
|
7
|
+
let createdRecordId: number;
|
|
8
|
+
|
|
9
|
+
it(
|
|
10
|
+
"queries real records from QuickBase",
|
|
11
|
+
async () => {
|
|
12
|
+
const client = createClient();
|
|
13
|
+
|
|
14
|
+
// Upsert a test record to query later
|
|
15
|
+
const upsertResponse = await client.upsert({
|
|
16
|
+
body: {
|
|
17
|
+
to: QB_TABLE_ID_1,
|
|
18
|
+
data: [
|
|
19
|
+
{
|
|
20
|
+
"6": { value: "Test Task " + Date.now() }, // Assuming field 6 is a text field
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
fieldsToReturn: [3, 6], // Record ID# and the text field
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
createdRecordId = upsertResponse.metadata.createdRecordIds[0];
|
|
27
|
+
console.log("Created test record with ID:", createdRecordId);
|
|
28
|
+
|
|
29
|
+
// Query the record
|
|
30
|
+
const queryRequest: RunQueryRequest = {
|
|
31
|
+
from: QB_TABLE_ID_1,
|
|
32
|
+
select: [3, 6], // Query Record ID# and the text field
|
|
33
|
+
where: `{3.EX.${createdRecordId}}`, // Filter by the created record
|
|
34
|
+
sortBy: [{ fieldId: 6, order: "ASC" }],
|
|
35
|
+
options: { skip: 0, top: 1 },
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
console.log("Config used:", {
|
|
39
|
+
realm: process.env.QB_REALM,
|
|
40
|
+
userToken: process.env.QB_USER_TOKEN,
|
|
41
|
+
tableId: QB_TABLE_ID_1,
|
|
42
|
+
});
|
|
43
|
+
console.log("Query request:", queryRequest);
|
|
44
|
+
const response: RunQueryResponse = await client.runQuery({
|
|
45
|
+
body: queryRequest,
|
|
46
|
+
});
|
|
47
|
+
console.log("Real API response:", response);
|
|
48
|
+
|
|
49
|
+
// Assertions
|
|
50
|
+
expect(response.data).toHaveLength(1);
|
|
51
|
+
expect(response.data[0]["3"].value).toBe(createdRecordId);
|
|
52
|
+
expect(response.data[0]["6"].value).toContain("Test Task");
|
|
53
|
+
expect(response.fields).toContainEqual({
|
|
54
|
+
id: 3,
|
|
55
|
+
label: expect.any(String),
|
|
56
|
+
type: expect.any(String),
|
|
57
|
+
});
|
|
58
|
+
expect(response.fields).toContainEqual({
|
|
59
|
+
id: 6,
|
|
60
|
+
label: expect.any(String),
|
|
61
|
+
type: expect.any(String),
|
|
62
|
+
});
|
|
63
|
+
expect(response.metadata).toMatchObject({
|
|
64
|
+
numFields: 2,
|
|
65
|
+
numRecords: 1,
|
|
66
|
+
skip: 0,
|
|
67
|
+
top: 1,
|
|
68
|
+
totalRecords: expect.any(Number),
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Cleanup: Delete the test record
|
|
72
|
+
await client.deleteRecords({
|
|
73
|
+
body: {
|
|
74
|
+
from: QB_TABLE_ID_1,
|
|
75
|
+
where: `{3.EX.${createdRecordId}}`, // Assuming field 3 is Record ID#
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
console.log("Cleaned up test record with ID:", createdRecordId);
|
|
79
|
+
},
|
|
80
|
+
{ timeout: 10000 }
|
|
81
|
+
);
|
|
82
|
+
});
|