quickbase-js 2.0.0 → 2.2.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.
- package/README.md +804 -59
- package/bin/quickbase-js.js +54 -0
- package/dist/auth/index.d.ts +1 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +9 -0
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/ticket.d.ts +84 -0
- package/dist/auth/ticket.d.ts.map +1 -0
- package/dist/auth/ticket.js +260 -0
- package/dist/auth/ticket.js.map +1 -0
- package/dist/cli/schema.d.ts +23 -0
- package/dist/cli/schema.d.ts.map +1 -0
- package/dist/cli/schema.js +425 -0
- package/dist/cli/schema.js.map +1 -0
- package/dist/client/request.d.ts +2 -1
- package/dist/client/request.d.ts.map +1 -1
- package/dist/client/request.js +165 -18
- package/dist/client/request.js.map +1 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +12 -0
- package/dist/core/config.js.map +1 -1
- package/dist/core/errors.d.ts +17 -0
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +32 -0
- package/dist/core/errors.js.map +1 -1
- package/dist/core/index.d.ts +3 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/schema.d.ts +37 -0
- package/dist/core/schema.d.ts.map +1 -0
- package/dist/core/schema.js +168 -0
- package/dist/core/schema.js.map +1 -0
- package/dist/core/transform.d.ts +36 -0
- package/dist/core/transform.d.ts.map +1 -0
- package/dist/core/transform.js +205 -0
- package/dist/core/transform.js.map +1 -0
- package/dist/core/types.d.ts +104 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/index.d.ts +14 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -2
- package/dist/index.js.map +1 -1
- package/dist/quickbase.esm.js +6 -2
- package/dist/quickbase.esm.js.map +4 -4
- package/dist/quickbase.min.js +6 -2
- package/dist/quickbase.min.js.map +4 -4
- package/dist/xml/codepages.d.ts +60 -0
- package/dist/xml/codepages.d.ts.map +1 -0
- package/dist/xml/codepages.js +88 -0
- package/dist/xml/codepages.js.map +1 -0
- package/dist/xml/dbvars.d.ts +39 -0
- package/dist/xml/dbvars.d.ts.map +1 -0
- package/dist/xml/dbvars.js +54 -0
- package/dist/xml/dbvars.js.map +1 -0
- package/dist/xml/errors.d.ts +64 -0
- package/dist/xml/errors.d.ts.map +1 -0
- package/dist/xml/errors.js +102 -0
- package/dist/xml/errors.js.map +1 -0
- package/dist/xml/fields.d.ts +45 -0
- package/dist/xml/fields.d.ts.map +1 -0
- package/dist/xml/fields.js +86 -0
- package/dist/xml/fields.js.map +1 -0
- package/dist/xml/groups.d.ts +196 -0
- package/dist/xml/groups.d.ts.map +1 -0
- package/dist/xml/groups.js +424 -0
- package/dist/xml/groups.js.map +1 -0
- package/dist/xml/html.d.ts +61 -0
- package/dist/xml/html.d.ts.map +1 -0
- package/dist/xml/html.js +110 -0
- package/dist/xml/html.js.map +1 -0
- package/dist/xml/index.d.ts +453 -0
- package/dist/xml/index.d.ts.map +1 -0
- package/dist/xml/index.js +741 -0
- package/dist/xml/index.js.map +1 -0
- package/dist/xml/metadata.d.ts +49 -0
- package/dist/xml/metadata.d.ts.map +1 -0
- package/dist/xml/metadata.js +84 -0
- package/dist/xml/metadata.js.map +1 -0
- package/dist/xml/records.d.ts +106 -0
- package/dist/xml/records.d.ts.map +1 -0
- package/dist/xml/records.js +220 -0
- package/dist/xml/records.js.map +1 -0
- package/dist/xml/request.d.ts +115 -0
- package/dist/xml/request.d.ts.map +1 -0
- package/dist/xml/request.js +167 -0
- package/dist/xml/request.js.map +1 -0
- package/dist/xml/roles.d.ts +117 -0
- package/dist/xml/roles.d.ts.map +1 -0
- package/dist/xml/roles.js +241 -0
- package/dist/xml/roles.js.map +1 -0
- package/dist/xml/schema.d.ts +94 -0
- package/dist/xml/schema.d.ts.map +1 -0
- package/dist/xml/schema.js +354 -0
- package/dist/xml/schema.js.map +1 -0
- package/dist/xml/transform.d.ts +154 -0
- package/dist/xml/transform.d.ts.map +1 -0
- package/dist/xml/transform.js +182 -0
- package/dist/xml/transform.js.map +1 -0
- package/dist/xml/types.d.ts +531 -0
- package/dist/xml/types.d.ts.map +1 -0
- package/dist/xml/types.js +22 -0
- package/dist/xml/types.js.map +1 -0
- package/dist/xml/users.d.ts +92 -0
- package/dist/xml/users.d.ts.map +1 -0
- package/dist/xml/users.js +166 -0
- package/dist/xml/users.js.map +1 -0
- package/dist/xml/webhooks.d.ts +98 -0
- package/dist/xml/webhooks.d.ts.map +1 -0
- package/dist/xml/webhooks.js +202 -0
- package/dist/xml/webhooks.js.map +1 -0
- package/package.json +6 -2
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* QuickBase JS SDK CLI
|
|
4
|
+
*
|
|
5
|
+
* Available commands:
|
|
6
|
+
* schema Generate schema from QuickBase application
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { fileURLToPath } from 'url';
|
|
10
|
+
import { dirname, join } from 'path';
|
|
11
|
+
|
|
12
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
13
|
+
|
|
14
|
+
async function main() {
|
|
15
|
+
const args = process.argv.slice(2);
|
|
16
|
+
const command = args[0];
|
|
17
|
+
|
|
18
|
+
switch (command) {
|
|
19
|
+
case 'schema':
|
|
20
|
+
const { main: schemaMain } = await import(
|
|
21
|
+
join(__dirname, '..', 'dist', 'cli', 'schema.js')
|
|
22
|
+
);
|
|
23
|
+
await schemaMain(args.slice(1));
|
|
24
|
+
break;
|
|
25
|
+
|
|
26
|
+
case '--help':
|
|
27
|
+
case '-h':
|
|
28
|
+
case undefined:
|
|
29
|
+
console.log(`
|
|
30
|
+
quickbase-js - QuickBase SDK CLI
|
|
31
|
+
|
|
32
|
+
Commands:
|
|
33
|
+
schema Generate schema from QuickBase application
|
|
34
|
+
|
|
35
|
+
Usage:
|
|
36
|
+
npx quickbase-js <command> [options]
|
|
37
|
+
|
|
38
|
+
Examples:
|
|
39
|
+
npx quickbase-js schema --help
|
|
40
|
+
npx quickbase-js schema -r mycompany -a bqw123abc -t token
|
|
41
|
+
`);
|
|
42
|
+
break;
|
|
43
|
+
|
|
44
|
+
default:
|
|
45
|
+
console.error(`Unknown command: ${command}`);
|
|
46
|
+
console.error('Run "npx quickbase-js --help" for available commands');
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
main().catch((error) => {
|
|
52
|
+
console.error('Error:', error.message);
|
|
53
|
+
process.exit(1);
|
|
54
|
+
});
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export type { AuthStrategy, AuthContext, CachedToken } from './types.js';
|
|
|
5
5
|
export { UserTokenStrategy } from './user-token.js';
|
|
6
6
|
export { TempTokenStrategy } from './temp-token.js';
|
|
7
7
|
export { SsoTokenStrategy } from './sso-token.js';
|
|
8
|
+
export { TicketStrategy } from './ticket.js';
|
|
8
9
|
export { TokenCache } from './token-cache.js';
|
|
9
10
|
import type { AuthConfig } from '../core/types.js';
|
|
10
11
|
import type { AuthStrategy, AuthContext } from './types.js';
|
package/dist/auth/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAM5D;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,WAAW,GACnB,YAAY,CA8Bd"}
|
package/dist/auth/index.js
CHANGED
|
@@ -4,10 +4,12 @@
|
|
|
4
4
|
export { UserTokenStrategy } from './user-token.js';
|
|
5
5
|
export { TempTokenStrategy } from './temp-token.js';
|
|
6
6
|
export { SsoTokenStrategy } from './sso-token.js';
|
|
7
|
+
export { TicketStrategy } from './ticket.js'; // XML-API-TICKET: Remove if XML API discontinued
|
|
7
8
|
export { TokenCache } from './token-cache.js';
|
|
8
9
|
import { UserTokenStrategy } from './user-token.js';
|
|
9
10
|
import { TempTokenStrategy } from './temp-token.js';
|
|
10
11
|
import { SsoTokenStrategy } from './sso-token.js';
|
|
12
|
+
import { TicketStrategy } from './ticket.js'; // XML-API-TICKET: Remove if XML API discontinued
|
|
11
13
|
/**
|
|
12
14
|
* Factory function to create the appropriate auth strategy
|
|
13
15
|
*/
|
|
@@ -22,6 +24,13 @@ export function createAuthStrategy(authConfig, context) {
|
|
|
22
24
|
});
|
|
23
25
|
case 'sso':
|
|
24
26
|
return new SsoTokenStrategy(authConfig.samlToken, context);
|
|
27
|
+
// XML-API-TICKET: Remove this case if XML API is discontinued
|
|
28
|
+
case 'ticket':
|
|
29
|
+
return new TicketStrategy(authConfig.username, authConfig.password, {
|
|
30
|
+
hours: authConfig.hours,
|
|
31
|
+
onExpired: authConfig.onExpired,
|
|
32
|
+
persist: authConfig.persist,
|
|
33
|
+
}, context);
|
|
25
34
|
default:
|
|
26
35
|
throw new Error(`Unknown auth type: ${authConfig.type}`);
|
|
27
36
|
}
|
package/dist/auth/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAI9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC,CAAC,iDAAiD;AAC/F,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAI9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC,CAAC,iDAAiD;AAE/F;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAChC,UAAsB,EACtB,OAAoB;IAEpB,QAAQ,UAAU,CAAC,IAAI,EAAE,CAAC;QACxB,KAAK,YAAY;YACf,OAAO,IAAI,iBAAiB,CAAC,UAAU,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAE9D,KAAK,YAAY;YACf,OAAO,IAAI,iBAAiB,CAAC,UAAU,CAAC,SAAS,EAAE,OAAO,EAAE;gBAC1D,QAAQ,EAAE,UAAU,CAAC,QAAQ;gBAC7B,eAAe,EAAE,UAAU,CAAC,eAAe;aAC5C,CAAC,CAAC;QAEL,KAAK,KAAK;YACR,OAAO,IAAI,gBAAgB,CAAC,UAAU,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAE7D,8DAA8D;QAC9D,KAAK,QAAQ;YACX,OAAO,IAAI,cAAc,CACvB,UAAU,CAAC,QAAQ,EACnB,UAAU,CAAC,QAAQ,EACnB;gBACE,KAAK,EAAE,UAAU,CAAC,KAAK;gBACvB,SAAS,EAAE,UAAU,CAAC,SAAS;gBAC/B,OAAO,EAAE,UAAU,CAAC,OAAO;aAC5B,EACD,OAAO,CACR,CAAC;QAEJ;YACE,MAAM,IAAI,KAAK,CAAC,sBAAuB,UAA+B,CAAC,IAAI,EAAE,CAAC,CAAC;IACnF,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ticket Authentication Strategy (XML API)
|
|
3
|
+
*
|
|
4
|
+
* Authenticates using username/password via the XML API_Authenticate endpoint.
|
|
5
|
+
* Unlike user tokens, tickets properly attribute record changes (createdBy/modifiedBy)
|
|
6
|
+
* to the authenticated user.
|
|
7
|
+
*
|
|
8
|
+
* NOTE: This uses the legacy QuickBase XML API (API_Authenticate).
|
|
9
|
+
* If QuickBase discontinues the XML API in the future, this file and related code
|
|
10
|
+
* can be safely removed.
|
|
11
|
+
*
|
|
12
|
+
* To find all related code, search for the marker: XML-API-TICKET
|
|
13
|
+
*
|
|
14
|
+
* Files to remove/update:
|
|
15
|
+
* - src/auth/ticket.ts (this file)
|
|
16
|
+
* - src/auth/index.ts (TicketStrategy export, createAuthStrategy case)
|
|
17
|
+
* - src/core/types.ts (TicketAuthConfig)
|
|
18
|
+
* - src/index.ts (exports)
|
|
19
|
+
* - tests/auth/ticket.test.ts
|
|
20
|
+
* - README.md: "Ticket Auth" section
|
|
21
|
+
*/
|
|
22
|
+
import type { AuthStrategy, AuthContext } from './types.js';
|
|
23
|
+
/**
|
|
24
|
+
* Options for ticket authentication
|
|
25
|
+
*/
|
|
26
|
+
export interface TicketAuthOptions {
|
|
27
|
+
/** Ticket validity in hours (default: 12, max: 4380 ~6 months) */
|
|
28
|
+
hours?: number;
|
|
29
|
+
/** Callback invoked when ticket expires - use to show login UI */
|
|
30
|
+
onExpired?: () => void;
|
|
31
|
+
/** Persist ticket to storage for session survival (default: none) */
|
|
32
|
+
persist?: 'sessionStorage' | 'localStorage';
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Ticket authentication strategy using XML API_Authenticate.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* const client = createClient({
|
|
40
|
+
* realm: 'mycompany',
|
|
41
|
+
* auth: {
|
|
42
|
+
* type: 'ticket',
|
|
43
|
+
* username: 'user@example.com',
|
|
44
|
+
* password: 'password',
|
|
45
|
+
* },
|
|
46
|
+
* });
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* XML-API-TICKET: Remove this class if XML API is discontinued.
|
|
50
|
+
*/
|
|
51
|
+
export declare class TicketStrategy implements AuthStrategy {
|
|
52
|
+
private readonly username;
|
|
53
|
+
private password;
|
|
54
|
+
private readonly hours;
|
|
55
|
+
private readonly realm;
|
|
56
|
+
private readonly fetchApi;
|
|
57
|
+
private readonly logger;
|
|
58
|
+
private readonly onExpired?;
|
|
59
|
+
private readonly persist?;
|
|
60
|
+
private readonly storageKey;
|
|
61
|
+
private ticket;
|
|
62
|
+
private userId;
|
|
63
|
+
private expiresAt;
|
|
64
|
+
private authenticated;
|
|
65
|
+
private pendingAuth;
|
|
66
|
+
constructor(username: string, password: string, options: TicketAuthOptions | undefined, context: AuthContext);
|
|
67
|
+
getToken(_dbid?: string): Promise<string>;
|
|
68
|
+
getAuthorizationHeader(token: string): string;
|
|
69
|
+
handleAuthError(_dbid?: string): Promise<boolean>;
|
|
70
|
+
invalidate(_dbid?: string): void;
|
|
71
|
+
private clearTicket;
|
|
72
|
+
/**
|
|
73
|
+
* Get the authenticated user's ID (available after first API call)
|
|
74
|
+
*/
|
|
75
|
+
getUserId(): string | null;
|
|
76
|
+
private authenticate;
|
|
77
|
+
private parseXmlResponse;
|
|
78
|
+
private escapeXml;
|
|
79
|
+
private getStorage;
|
|
80
|
+
private saveToStorage;
|
|
81
|
+
private restoreFromStorage;
|
|
82
|
+
private clearFromStorage;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=ticket.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ticket.d.ts","sourceRoot":"","sources":["../../src/auth/ticket.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAW5D;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,qEAAqE;IACrE,OAAO,CAAC,EAAE,gBAAgB,GAAG,cAAc,CAAC;CAC7C;AASD;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,cAAe,YAAW,YAAY;IACjD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAa;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAoC;IAC7D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IAEpC,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,WAAW,CAAgC;gBAGjD,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,iBAAiB,GAAG,SAAS,EACtC,OAAO,EAAE,WAAW;IAgBhB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAiC/C,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAIvC,eAAe,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAUvD,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAIhC,OAAO,CAAC,WAAW;IAMnB;;OAEG;IACH,SAAS,IAAI,MAAM,GAAG,IAAI;YAIZ,YAAY;IAuD1B,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,SAAS;IASjB,OAAO,CAAC,UAAU;IAelB,OAAO,CAAC,aAAa;IAkBrB,OAAO,CAAC,kBAAkB;IA+B1B,OAAO,CAAC,gBAAgB;CAWzB"}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ticket Authentication Strategy (XML API)
|
|
3
|
+
*
|
|
4
|
+
* Authenticates using username/password via the XML API_Authenticate endpoint.
|
|
5
|
+
* Unlike user tokens, tickets properly attribute record changes (createdBy/modifiedBy)
|
|
6
|
+
* to the authenticated user.
|
|
7
|
+
*
|
|
8
|
+
* NOTE: This uses the legacy QuickBase XML API (API_Authenticate).
|
|
9
|
+
* If QuickBase discontinues the XML API in the future, this file and related code
|
|
10
|
+
* can be safely removed.
|
|
11
|
+
*
|
|
12
|
+
* To find all related code, search for the marker: XML-API-TICKET
|
|
13
|
+
*
|
|
14
|
+
* Files to remove/update:
|
|
15
|
+
* - src/auth/ticket.ts (this file)
|
|
16
|
+
* - src/auth/index.ts (TicketStrategy export, createAuthStrategy case)
|
|
17
|
+
* - src/core/types.ts (TicketAuthConfig)
|
|
18
|
+
* - src/index.ts (exports)
|
|
19
|
+
* - tests/auth/ticket.test.ts
|
|
20
|
+
* - README.md: "Ticket Auth" section
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Ticket authentication strategy using XML API_Authenticate.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* const client = createClient({
|
|
28
|
+
* realm: 'mycompany',
|
|
29
|
+
* auth: {
|
|
30
|
+
* type: 'ticket',
|
|
31
|
+
* username: 'user@example.com',
|
|
32
|
+
* password: 'password',
|
|
33
|
+
* },
|
|
34
|
+
* });
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* XML-API-TICKET: Remove this class if XML API is discontinued.
|
|
38
|
+
*/
|
|
39
|
+
export class TicketStrategy {
|
|
40
|
+
username;
|
|
41
|
+
password; // Cleared after first auth
|
|
42
|
+
hours;
|
|
43
|
+
realm;
|
|
44
|
+
fetchApi;
|
|
45
|
+
logger;
|
|
46
|
+
onExpired;
|
|
47
|
+
persist;
|
|
48
|
+
storageKey;
|
|
49
|
+
ticket = null;
|
|
50
|
+
userId = null;
|
|
51
|
+
expiresAt = null;
|
|
52
|
+
authenticated = false;
|
|
53
|
+
pendingAuth = null;
|
|
54
|
+
constructor(username, password, options, context) {
|
|
55
|
+
this.username = username;
|
|
56
|
+
this.password = password;
|
|
57
|
+
this.hours = Math.min(Math.max(options?.hours ?? 12, 1), 4380);
|
|
58
|
+
this.onExpired = options?.onExpired;
|
|
59
|
+
this.persist = options?.persist;
|
|
60
|
+
this.realm = context.realm;
|
|
61
|
+
this.fetchApi = context.fetchApi;
|
|
62
|
+
this.logger = context.logger;
|
|
63
|
+
this.storageKey = `qb_ticket_${this.realm}`;
|
|
64
|
+
// Try to restore ticket from storage
|
|
65
|
+
this.restoreFromStorage();
|
|
66
|
+
}
|
|
67
|
+
async getToken(_dbid) {
|
|
68
|
+
// Return cached ticket if available and not expired
|
|
69
|
+
if (this.ticket && this.expiresAt && Date.now() < this.expiresAt) {
|
|
70
|
+
return this.ticket;
|
|
71
|
+
}
|
|
72
|
+
// If ticket existed but expired, clear it
|
|
73
|
+
if (this.ticket && this.expiresAt && Date.now() >= this.expiresAt) {
|
|
74
|
+
this.clearTicket();
|
|
75
|
+
this.onExpired?.();
|
|
76
|
+
throw new Error('Ticket expired; create a new client with fresh credentials');
|
|
77
|
+
}
|
|
78
|
+
// If already authenticated but no ticket, it expired
|
|
79
|
+
if (this.authenticated) {
|
|
80
|
+
this.onExpired?.();
|
|
81
|
+
throw new Error('Ticket expired; create a new client with fresh credentials');
|
|
82
|
+
}
|
|
83
|
+
// Dedupe concurrent auth requests
|
|
84
|
+
if (this.pendingAuth) {
|
|
85
|
+
return this.pendingAuth;
|
|
86
|
+
}
|
|
87
|
+
this.pendingAuth = this.authenticate();
|
|
88
|
+
try {
|
|
89
|
+
const ticket = await this.pendingAuth;
|
|
90
|
+
return ticket;
|
|
91
|
+
}
|
|
92
|
+
finally {
|
|
93
|
+
this.pendingAuth = null;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
getAuthorizationHeader(token) {
|
|
97
|
+
return `QB-TICKET ${token}`;
|
|
98
|
+
}
|
|
99
|
+
async handleAuthError(_dbid) {
|
|
100
|
+
// Clear expired ticket
|
|
101
|
+
this.clearTicket();
|
|
102
|
+
// Can't refresh - password was cleared after initial auth
|
|
103
|
+
this.logger.debug('Ticket auth error - cannot refresh (password was cleared)');
|
|
104
|
+
this.onExpired?.();
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
invalidate(_dbid) {
|
|
108
|
+
this.clearTicket();
|
|
109
|
+
}
|
|
110
|
+
clearTicket() {
|
|
111
|
+
this.ticket = null;
|
|
112
|
+
this.expiresAt = null;
|
|
113
|
+
this.clearFromStorage();
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Get the authenticated user's ID (available after first API call)
|
|
117
|
+
*/
|
|
118
|
+
getUserId() {
|
|
119
|
+
return this.userId;
|
|
120
|
+
}
|
|
121
|
+
async authenticate() {
|
|
122
|
+
if (!this.password) {
|
|
123
|
+
this.onExpired?.();
|
|
124
|
+
throw new Error('Ticket expired; create a new client with fresh credentials');
|
|
125
|
+
}
|
|
126
|
+
const url = `https://${this.realm}.quickbase.com/db/main`;
|
|
127
|
+
// Build XML request body
|
|
128
|
+
const xmlBody = `<qdbapi>
|
|
129
|
+
<username>${this.escapeXml(this.username)}</username>
|
|
130
|
+
<password>${this.escapeXml(this.password)}</password>
|
|
131
|
+
<hours>${this.hours}</hours>
|
|
132
|
+
</qdbapi>`;
|
|
133
|
+
this.logger.debug(`Authenticating via API_Authenticate for ${this.username}`);
|
|
134
|
+
const response = await this.fetchApi(url, {
|
|
135
|
+
method: 'POST',
|
|
136
|
+
headers: {
|
|
137
|
+
'Content-Type': 'application/xml',
|
|
138
|
+
'QUICKBASE-ACTION': 'API_Authenticate',
|
|
139
|
+
},
|
|
140
|
+
body: xmlBody,
|
|
141
|
+
});
|
|
142
|
+
const xmlText = await response.text();
|
|
143
|
+
const result = this.parseXmlResponse(xmlText);
|
|
144
|
+
if (result.errcode !== 0) {
|
|
145
|
+
const errMsg = result.errdetail || result.errtext || 'Unknown error';
|
|
146
|
+
throw new Error(`Authentication failed: ${errMsg} (code: ${result.errcode})`);
|
|
147
|
+
}
|
|
148
|
+
if (!result.ticket) {
|
|
149
|
+
throw new Error('No ticket returned from API_Authenticate');
|
|
150
|
+
}
|
|
151
|
+
// Store ticket and user ID
|
|
152
|
+
this.ticket = result.ticket;
|
|
153
|
+
this.userId = result.userid;
|
|
154
|
+
this.expiresAt = Date.now() + this.hours * 60 * 60 * 1000;
|
|
155
|
+
this.authenticated = true;
|
|
156
|
+
// Save to storage if persistence is enabled
|
|
157
|
+
this.saveToStorage();
|
|
158
|
+
// Clear password from memory
|
|
159
|
+
this.password = null;
|
|
160
|
+
this.logger.debug(`Authenticated successfully, userId: ${this.userId}`);
|
|
161
|
+
return this.ticket;
|
|
162
|
+
}
|
|
163
|
+
parseXmlResponse(xml) {
|
|
164
|
+
// Simple XML parsing for the specific response format
|
|
165
|
+
const getTagContent = (tag) => {
|
|
166
|
+
const match = xml.match(new RegExp(`<${tag}>([^<]*)</${tag}>`));
|
|
167
|
+
return match?.[1] ?? '';
|
|
168
|
+
};
|
|
169
|
+
return {
|
|
170
|
+
ticket: getTagContent('ticket'),
|
|
171
|
+
userid: getTagContent('userid'),
|
|
172
|
+
errcode: parseInt(getTagContent('errcode'), 10) || 0,
|
|
173
|
+
errtext: getTagContent('errtext'),
|
|
174
|
+
errdetail: getTagContent('errdetail') || undefined,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
escapeXml(str) {
|
|
178
|
+
return str
|
|
179
|
+
.replace(/&/g, '&')
|
|
180
|
+
.replace(/</g, '<')
|
|
181
|
+
.replace(/>/g, '>')
|
|
182
|
+
.replace(/"/g, '"')
|
|
183
|
+
.replace(/'/g, ''');
|
|
184
|
+
}
|
|
185
|
+
getStorage() {
|
|
186
|
+
if (!this.persist)
|
|
187
|
+
return null;
|
|
188
|
+
try {
|
|
189
|
+
// Check if we're in a browser environment
|
|
190
|
+
if (typeof globalThis === 'undefined')
|
|
191
|
+
return null;
|
|
192
|
+
const win = globalThis;
|
|
193
|
+
const storage = this.persist === 'localStorage' ? win.localStorage : win.sessionStorage;
|
|
194
|
+
return storage ?? null;
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
// Storage may be disabled (e.g., private browsing)
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
saveToStorage() {
|
|
202
|
+
const storage = this.getStorage();
|
|
203
|
+
if (!storage || !this.ticket || !this.userId || !this.expiresAt)
|
|
204
|
+
return;
|
|
205
|
+
try {
|
|
206
|
+
const data = {
|
|
207
|
+
ticket: this.ticket,
|
|
208
|
+
userId: this.userId,
|
|
209
|
+
expiresAt: this.expiresAt,
|
|
210
|
+
};
|
|
211
|
+
storage.setItem(this.storageKey, JSON.stringify(data));
|
|
212
|
+
this.logger.debug(`Ticket saved to ${this.persist}`);
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
// Storage quota exceeded or other error - ignore
|
|
216
|
+
this.logger.debug(`Failed to save ticket to ${this.persist}`);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
restoreFromStorage() {
|
|
220
|
+
const storage = this.getStorage();
|
|
221
|
+
if (!storage)
|
|
222
|
+
return;
|
|
223
|
+
try {
|
|
224
|
+
const json = storage.getItem(this.storageKey);
|
|
225
|
+
if (!json)
|
|
226
|
+
return;
|
|
227
|
+
const data = JSON.parse(json);
|
|
228
|
+
// Check if ticket is still valid (with 1 minute buffer)
|
|
229
|
+
if (Date.now() >= data.expiresAt - 60000) {
|
|
230
|
+
storage.removeItem(this.storageKey);
|
|
231
|
+
this.logger.debug('Stored ticket expired, removed from storage');
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
this.ticket = data.ticket;
|
|
235
|
+
this.userId = data.userId;
|
|
236
|
+
this.expiresAt = data.expiresAt;
|
|
237
|
+
this.authenticated = true;
|
|
238
|
+
// Password stays null since we have a valid ticket
|
|
239
|
+
this.password = null;
|
|
240
|
+
this.logger.debug(`Ticket restored from ${this.persist}`);
|
|
241
|
+
}
|
|
242
|
+
catch {
|
|
243
|
+
// Invalid JSON or other error - clear storage
|
|
244
|
+
storage.removeItem(this.storageKey);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
clearFromStorage() {
|
|
248
|
+
const storage = this.getStorage();
|
|
249
|
+
if (!storage)
|
|
250
|
+
return;
|
|
251
|
+
try {
|
|
252
|
+
storage.removeItem(this.storageKey);
|
|
253
|
+
this.logger.debug(`Ticket cleared from ${this.persist}`);
|
|
254
|
+
}
|
|
255
|
+
catch {
|
|
256
|
+
// Ignore errors
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
//# sourceMappingURL=ticket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ticket.js","sourceRoot":"","sources":["../../src/auth/ticket.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAgCH;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,OAAO,cAAc;IACR,QAAQ,CAAS;IAC1B,QAAQ,CAAgB,CAAC,2BAA2B;IAC3C,KAAK,CAAS;IACd,KAAK,CAAS;IACd,QAAQ,CAAe;IACvB,MAAM,CAAS;IACf,SAAS,CAAc;IACvB,OAAO,CAAqC;IAC5C,UAAU,CAAS;IAE5B,MAAM,GAAkB,IAAI,CAAC;IAC7B,MAAM,GAAkB,IAAI,CAAC;IAC7B,SAAS,GAAkB,IAAI,CAAC;IAChC,aAAa,GAAG,KAAK,CAAC;IACtB,WAAW,GAA2B,IAAI,CAAC;IAEnD,YACE,QAAgB,EAChB,QAAgB,EAChB,OAAsC,EACtC,OAAoB;QAEpB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAC/D,IAAI,CAAC,SAAS,GAAG,OAAO,EAAE,SAAS,CAAC;QACpC,IAAI,CAAC,OAAO,GAAG,OAAO,EAAE,OAAO,CAAC;QAChC,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QAC3B,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QACjC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,UAAU,GAAG,aAAa,IAAI,CAAC,KAAK,EAAE,CAAC;QAE5C,qCAAqC;QACrC,IAAI,CAAC,kBAAkB,EAAE,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,KAAc;QAC3B,oDAAoD;QACpD,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;YACjE,OAAO,IAAI,CAAC,MAAM,CAAC;QACrB,CAAC;QAED,0CAA0C;QAC1C,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAClE,IAAI,CAAC,WAAW,EAAE,CAAC;YACnB,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAChF,CAAC;QAED,qDAAqD;QACrD,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAChF,CAAC;QAED,kCAAkC;QAClC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,OAAO,IAAI,CAAC,WAAW,CAAC;QAC1B,CAAC;QAED,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QACvC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC;YACtC,OAAO,MAAM,CAAC;QAChB,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,sBAAsB,CAAC,KAAa;QAClC,OAAO,aAAa,KAAK,EAAE,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,KAAc;QAClC,uBAAuB;QACvB,IAAI,CAAC,WAAW,EAAE,CAAC;QAEnB,0DAA0D;QAC1D,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,2DAA2D,CAAC,CAAC;QAC/E,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,UAAU,CAAC,KAAc;QACvB,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAEO,WAAW;QACjB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,gBAAgB,EAAE,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAEO,KAAK,CAAC,YAAY;QACxB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAChF,CAAC;QAED,MAAM,GAAG,GAAG,WAAW,IAAI,CAAC,KAAK,wBAAwB,CAAC;QAE1D,yBAAyB;QACzB,MAAM,OAAO,GAAG;gBACJ,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC;gBAC7B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC;aAChC,IAAI,CAAC,KAAK;UACb,CAAC;QAEP,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,2CAA2C,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QAE9E,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE;YACxC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,iBAAiB;gBACjC,kBAAkB,EAAE,kBAAkB;aACvC;YACD,IAAI,EAAE,OAAO;SACd,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACtC,MAAM,MAAM,GAAG,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAE9C,IAAI,MAAM,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;YACzB,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,OAAO,IAAI,eAAe,CAAC;YACrE,MAAM,IAAI,KAAK,CAAC,0BAA0B,MAAM,WAAW,MAAM,CAAC,OAAO,GAAG,CAAC,CAAC;QAChF,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC9D,CAAC;QAED,2BAA2B;QAC3B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;QAC1D,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAE1B,4CAA4C;QAC5C,IAAI,CAAC,aAAa,EAAE,CAAC;QAErB,6BAA6B;QAC7B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QAErB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,uCAAuC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAExE,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAEO,gBAAgB,CAAC,GAAW;QAClC,sDAAsD;QACtD,MAAM,aAAa,GAAG,CAAC,GAAW,EAAU,EAAE;YAC5C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,GAAG,aAAa,GAAG,GAAG,CAAC,CAAC,CAAC;YAChE,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC1B,CAAC,CAAC;QAEF,OAAO;YACL,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC;YAC/B,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC;YAC/B,OAAO,EAAE,QAAQ,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC;YACpD,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC;YACjC,SAAS,EAAE,aAAa,CAAC,WAAW,CAAC,IAAI,SAAS;SACnD,CAAC;IACJ,CAAC;IAEO,SAAS,CAAC,GAAW;QAC3B,OAAO,GAAG;aACP,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;aACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;aACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;aACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;aACvB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC7B,CAAC;IAEO,UAAU;QAChB,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QAC/B,IAAI,CAAC;YACH,0CAA0C;YAC1C,IAAI,OAAO,UAAU,KAAK,WAAW;gBAAE,OAAO,IAAI,CAAC;YAEnD,MAAM,GAAG,GAAG,UAA0E,CAAC;YACvF,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,KAAK,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC;YACxF,OAAO,OAAO,IAAI,IAAI,CAAC;QACzB,CAAC;QAAC,MAAM,CAAC;YACP,mDAAmD;YACnD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAEO,aAAa;QACnB,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAClC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,OAAO;QAExE,IAAI,CAAC;YACH,MAAM,IAAI,GAAwB;gBAChC,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,SAAS,EAAE,IAAI,CAAC,SAAS;aAC1B,CAAC;YACF,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;YACvD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QACvD,CAAC;QAAC,MAAM,CAAC;YACP,iDAAiD;YACjD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,4BAA4B,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QAChE,CAAC;IACH,CAAC;IAEO,kBAAkB;QACxB,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAClC,IAAI,CAAC,OAAO;YAAE,OAAO;QAErB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC9C,IAAI,CAAC,IAAI;gBAAE,OAAO;YAElB,MAAM,IAAI,GAAwB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAEnD,wDAAwD;YACxD,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,SAAS,GAAG,KAAK,EAAE,CAAC;gBACzC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBACpC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;gBACjE,OAAO;YACT,CAAC;YAED,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;YAC1B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;YAC1B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;YAChC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;YAC1B,mDAAmD;YACnD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;YAErB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,wBAAwB,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5D,CAAC;QAAC,MAAM,CAAC;YACP,8CAA8C;YAC9C,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAEO,gBAAgB;QACtB,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAClC,IAAI,CAAC,OAAO;YAAE,OAAO;QAErB,IAAI,CAAC;YACH,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACpC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,uBAAuB,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QAC3D,CAAC;QAAC,MAAM,CAAC;YACP,gBAAgB;QAClB,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI Schema Generator
|
|
4
|
+
*
|
|
5
|
+
* Generates a schema definition from a QuickBase application.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* npx quickbase-js schema --realm <realm> --app <appId> --token <token>
|
|
9
|
+
*
|
|
10
|
+
* Options:
|
|
11
|
+
* --realm QuickBase realm (e.g., "mycompany")
|
|
12
|
+
* --app Application ID (e.g., "bqw123abc")
|
|
13
|
+
* --token User token for authentication (or set QB_USER_TOKEN env var)
|
|
14
|
+
* --output Output file path (default: stdout)
|
|
15
|
+
* --format Output format: "ts" or "json" (default: "ts")
|
|
16
|
+
* --merge Merge with existing schema file, preserving custom aliases
|
|
17
|
+
* --help Show help
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Main CLI entry point
|
|
21
|
+
*/
|
|
22
|
+
export declare function main(args: string[]): Promise<void>;
|
|
23
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/cli/schema.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;GAgBG;AAkZH;;GAEG;AACH,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAgFxD"}
|