zitejs 0.9.102 → 0.9.104
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/dist/cjs/sync/lib.d.ts +10 -0
- package/dist/cjs/sync/lib.js +69 -28
- package/dist/esm/sync/lib.d.ts +10 -0
- package/dist/esm/sync/lib.js +68 -28
- package/package.json +1 -1
package/dist/cjs/sync/lib.d.ts
CHANGED
|
@@ -16,6 +16,16 @@ export type ZiteSchema = {
|
|
|
16
16
|
};
|
|
17
17
|
export declare function toPascalCase(name: string): string;
|
|
18
18
|
export declare function toCamelCase(name: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* camelCase for a FRESH sdkName, reading acronym runs as words: "VIP" ->
|
|
21
|
+
* "vip", "APIKey" -> "apiKey" (plain toCamelCase yields "vIP" / "aPIKey").
|
|
22
|
+
*
|
|
23
|
+
* Deliberately not folded into toCamelCase: that also derives endpoint
|
|
24
|
+
* identifiers from existing filenames on every generate, where normalizing
|
|
25
|
+
* would rename a working app's `api.sendSMS`. This is only for names being
|
|
26
|
+
* chosen for the first time — generateSchema preserves existing sdkNames.
|
|
27
|
+
*/
|
|
28
|
+
export declare function toSdkName(name: string): string;
|
|
19
29
|
/**
|
|
20
30
|
* Build a ZiteSchema from a Database API response.
|
|
21
31
|
*
|
package/dist/cjs/sync/lib.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.toPascalCase = toPascalCase;
|
|
4
4
|
exports.toCamelCase = toCamelCase;
|
|
5
|
+
exports.toSdkName = toSdkName;
|
|
5
6
|
exports.generateSchema = generateSchema;
|
|
6
7
|
exports.generateDbTs = generateDbTs;
|
|
7
8
|
exports.generateApiTs = generateApiTs;
|
|
@@ -13,48 +14,73 @@ const AUTH_USERS_TABLE_ID = "zite_user";
|
|
|
13
14
|
/**
|
|
14
15
|
* What a field's value looks like when a record is READ back.
|
|
15
16
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
17
|
+
* **These are deliberately optimistic, and that is load-bearing.** Every column
|
|
18
|
+
* is nullable with no default (`recordsTableManager`) and only the six text
|
|
19
|
+
* types get NULL rewritten to `''`, so the wire really does answer `null` for
|
|
20
|
+
* the rest. They are typed `T | undefined` anyway, matching the pre-monorepo
|
|
21
|
+
* SDK — `| null` appears zero times in its generator.
|
|
22
|
+
*
|
|
23
|
+
* Two things have been tried and both broke apps, so before "fixing" this:
|
|
24
|
+
*
|
|
25
|
+
* 1. **Typing the truth** (`9a44ab3`). 7880 of 7880 audited 1.0 endpoints
|
|
26
|
+
* declare an `outputSchema` written as a mirror of this type with every cell
|
|
27
|
+
* `.optional()`, and `createEndpoint` constrains `execute`'s return against
|
|
28
|
+
* it. `| null` fails the app's typecheck on lines nobody edited — 52 of 144
|
|
29
|
+
* apps, ~2,100 sites.
|
|
30
|
+
* 2. **Making the runtime emit `undefined`** so the type becomes true. The
|
|
31
|
+
* idiom that breaks is `.filter(m => m.homeScore !== null)`, which silently
|
|
32
|
+
* becomes a no-op and lets empty rows through: wrong results, no error.
|
|
33
|
+
* 10 of 328 exported apps do exactly this.
|
|
34
|
+
*
|
|
35
|
+
* TODO: make these accurate in a deliberate zitejs major, once apps are
|
|
36
|
+
* migrated. Each app pins its own version, so the change only reaches apps that
|
|
37
|
+
* opt in by bumping — which is the only way to do it without breaking (2).
|
|
38
|
+
*
|
|
39
|
+
* Writes are unaffected — `null` is how you clear a cell. See
|
|
40
|
+
* `FIELD_INPUT_TYPE_MAP` and `withNull`.
|
|
22
41
|
*/
|
|
23
42
|
const FIELD_TYPE_MAP = {
|
|
24
|
-
// Text: NULL is rewritten to '' on read, so these
|
|
43
|
+
// Text: NULL is rewritten to '' on read, so these are never even absent.
|
|
25
44
|
single_line_text: "string",
|
|
26
45
|
long_text: "string",
|
|
27
46
|
rich_text: "string",
|
|
28
47
|
email: "string",
|
|
29
48
|
url: "string",
|
|
30
49
|
phone_number: "string",
|
|
31
|
-
number: "number
|
|
32
|
-
currency: "number
|
|
33
|
-
percent: "number
|
|
34
|
-
rating: "number
|
|
50
|
+
number: "number",
|
|
51
|
+
currency: "number",
|
|
52
|
+
percent: "number",
|
|
53
|
+
rating: "number",
|
|
35
54
|
// DECIMAL seconds, unlike Airtable's, which is formatted to "HH:mm:ss".
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
55
|
+
// 1.0 typed this `string`, which was simply wrong — base-runner groups it
|
|
56
|
+
// with the numeric types — so it stays a number rather than reverting.
|
|
57
|
+
duration: "number",
|
|
58
|
+
checkbox: "boolean",
|
|
59
|
+
single_select: "string",
|
|
60
|
+
multiple_select: "string[]",
|
|
61
|
+
date: "string",
|
|
62
|
+
datetime: "string",
|
|
63
|
+
attachments: "ZiteAttachment[]",
|
|
43
64
|
// `string | string[]`, matching the pre-monorepo type. base-runner does force
|
|
44
65
|
// an array on read today, but 1.0 code is written with `typeof x === 'string'`
|
|
45
66
|
// guards — narrowing to `string[]` turns those branches into `never` and
|
|
46
67
|
// fails the app's typecheck for no gain.
|
|
47
68
|
linked_record: "string | string[]",
|
|
48
69
|
user: "string | string[]",
|
|
49
|
-
|
|
50
|
-
|
|
70
|
+
// `any`, not `unknown`, and deliberately: these are values the platform
|
|
71
|
+
// cannot type — a lookup is whatever the far side holds. 1.0 said `any`, and
|
|
72
|
+
// `unknown` buys nothing because there is no narrowing an app could have
|
|
73
|
+
// written in advance: `sum + (x || 0)` is a TS2365 on `unknown`, and the
|
|
74
|
+
// guarded spellings already narrowed fine under `any`.
|
|
75
|
+
lookup: "any",
|
|
76
|
+
rollup: "any",
|
|
51
77
|
autonumber: "number",
|
|
52
78
|
// JSONB change metadata (`{ type: "PublicAPI", apiKeyId: 3 }`), not a string.
|
|
53
|
-
source: "
|
|
54
|
-
formula: "
|
|
79
|
+
source: "any",
|
|
80
|
+
formula: "any",
|
|
55
81
|
created_at: "string",
|
|
56
82
|
updated_at: "string",
|
|
57
|
-
updated_by: "string
|
|
83
|
+
updated_by: "string",
|
|
58
84
|
};
|
|
59
85
|
/**
|
|
60
86
|
* Field types whose WRITE shape differs from their read shape — the API accepts
|
|
@@ -170,6 +196,21 @@ function toCamelCase(name) {
|
|
|
170
196
|
const pascal = toPascalCase(name);
|
|
171
197
|
return pascal.charAt(0).toLowerCase() + pascal.slice(1);
|
|
172
198
|
}
|
|
199
|
+
/**
|
|
200
|
+
* camelCase for a FRESH sdkName, reading acronym runs as words: "VIP" ->
|
|
201
|
+
* "vip", "APIKey" -> "apiKey" (plain toCamelCase yields "vIP" / "aPIKey").
|
|
202
|
+
*
|
|
203
|
+
* Deliberately not folded into toCamelCase: that also derives endpoint
|
|
204
|
+
* identifiers from existing filenames on every generate, where normalizing
|
|
205
|
+
* would rename a working app's `api.sendSMS`. This is only for names being
|
|
206
|
+
* chosen for the first time — generateSchema preserves existing sdkNames.
|
|
207
|
+
*/
|
|
208
|
+
function toSdkName(name) {
|
|
209
|
+
const deAcronymed = name
|
|
210
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, (_, run, next) => run.charAt(0) + run.slice(1).toLowerCase() + next)
|
|
211
|
+
.replace(/([A-Z])([A-Z]+)/g, (_, first, rest) => first + rest.toLowerCase());
|
|
212
|
+
return toCamelCase(deAcronymed);
|
|
213
|
+
}
|
|
173
214
|
/**
|
|
174
215
|
* Existing sdkNames are preserved across syncs so user code keeps compiling,
|
|
175
216
|
* but schemas written before the sanitizer stripped trailing symbols can carry
|
|
@@ -198,9 +239,9 @@ function tsTypeForSchemaField(def, variant = "read") {
|
|
|
198
239
|
.map((o) => `"${o.label.replace(/"/g, '\\"')}"`)
|
|
199
240
|
.join(" | ");
|
|
200
241
|
const union = `${literals} | string`;
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
242
|
+
// No `| null` on the read side — see FIELD_TYPE_MAP. The write side keeps
|
|
243
|
+
// it below, since null is how a select cell is cleared.
|
|
244
|
+
const read = def.type === "multiple_select" ? `(${union})[]` : union;
|
|
204
245
|
if (variant === "write") {
|
|
205
246
|
return def.type === "multiple_select"
|
|
206
247
|
? `${union} | (${union})[] | null`
|
|
@@ -338,13 +379,13 @@ function generateSchema(database, existingSchema) {
|
|
|
338
379
|
const { id: _id, order: _order, ...definition } = field;
|
|
339
380
|
fields.push({
|
|
340
381
|
id: field.id,
|
|
341
|
-
sdkName: keepValidSdkName(existing?.sdkName) ??
|
|
382
|
+
sdkName: keepValidSdkName(existing?.sdkName) ?? toSdkName(field.name),
|
|
342
383
|
definition,
|
|
343
384
|
});
|
|
344
385
|
}
|
|
345
386
|
tables.push({
|
|
346
387
|
id: table.id,
|
|
347
|
-
sdkName: keepValidSdkName(existingTable?.sdkName) ??
|
|
388
|
+
sdkName: keepValidSdkName(existingTable?.sdkName) ?? toSdkName(table.name),
|
|
348
389
|
primaryFieldId: table.primaryFieldId,
|
|
349
390
|
fields,
|
|
350
391
|
});
|
package/dist/esm/sync/lib.d.ts
CHANGED
|
@@ -16,6 +16,16 @@ export type ZiteSchema = {
|
|
|
16
16
|
};
|
|
17
17
|
export declare function toPascalCase(name: string): string;
|
|
18
18
|
export declare function toCamelCase(name: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* camelCase for a FRESH sdkName, reading acronym runs as words: "VIP" ->
|
|
21
|
+
* "vip", "APIKey" -> "apiKey" (plain toCamelCase yields "vIP" / "aPIKey").
|
|
22
|
+
*
|
|
23
|
+
* Deliberately not folded into toCamelCase: that also derives endpoint
|
|
24
|
+
* identifiers from existing filenames on every generate, where normalizing
|
|
25
|
+
* would rename a working app's `api.sendSMS`. This is only for names being
|
|
26
|
+
* chosen for the first time — generateSchema preserves existing sdkNames.
|
|
27
|
+
*/
|
|
28
|
+
export declare function toSdkName(name: string): string;
|
|
19
29
|
/**
|
|
20
30
|
* Build a ZiteSchema from a Database API response.
|
|
21
31
|
*
|
package/dist/esm/sync/lib.js
CHANGED
|
@@ -3,48 +3,73 @@ const AUTH_USERS_TABLE_ID = "zite_user";
|
|
|
3
3
|
/**
|
|
4
4
|
* What a field's value looks like when a record is READ back.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
6
|
+
* **These are deliberately optimistic, and that is load-bearing.** Every column
|
|
7
|
+
* is nullable with no default (`recordsTableManager`) and only the six text
|
|
8
|
+
* types get NULL rewritten to `''`, so the wire really does answer `null` for
|
|
9
|
+
* the rest. They are typed `T | undefined` anyway, matching the pre-monorepo
|
|
10
|
+
* SDK — `| null` appears zero times in its generator.
|
|
11
|
+
*
|
|
12
|
+
* Two things have been tried and both broke apps, so before "fixing" this:
|
|
13
|
+
*
|
|
14
|
+
* 1. **Typing the truth** (`9a44ab3`). 7880 of 7880 audited 1.0 endpoints
|
|
15
|
+
* declare an `outputSchema` written as a mirror of this type with every cell
|
|
16
|
+
* `.optional()`, and `createEndpoint` constrains `execute`'s return against
|
|
17
|
+
* it. `| null` fails the app's typecheck on lines nobody edited — 52 of 144
|
|
18
|
+
* apps, ~2,100 sites.
|
|
19
|
+
* 2. **Making the runtime emit `undefined`** so the type becomes true. The
|
|
20
|
+
* idiom that breaks is `.filter(m => m.homeScore !== null)`, which silently
|
|
21
|
+
* becomes a no-op and lets empty rows through: wrong results, no error.
|
|
22
|
+
* 10 of 328 exported apps do exactly this.
|
|
23
|
+
*
|
|
24
|
+
* TODO: make these accurate in a deliberate zitejs major, once apps are
|
|
25
|
+
* migrated. Each app pins its own version, so the change only reaches apps that
|
|
26
|
+
* opt in by bumping — which is the only way to do it without breaking (2).
|
|
27
|
+
*
|
|
28
|
+
* Writes are unaffected — `null` is how you clear a cell. See
|
|
29
|
+
* `FIELD_INPUT_TYPE_MAP` and `withNull`.
|
|
12
30
|
*/
|
|
13
31
|
const FIELD_TYPE_MAP = {
|
|
14
|
-
// Text: NULL is rewritten to '' on read, so these
|
|
32
|
+
// Text: NULL is rewritten to '' on read, so these are never even absent.
|
|
15
33
|
single_line_text: "string",
|
|
16
34
|
long_text: "string",
|
|
17
35
|
rich_text: "string",
|
|
18
36
|
email: "string",
|
|
19
37
|
url: "string",
|
|
20
38
|
phone_number: "string",
|
|
21
|
-
number: "number
|
|
22
|
-
currency: "number
|
|
23
|
-
percent: "number
|
|
24
|
-
rating: "number
|
|
39
|
+
number: "number",
|
|
40
|
+
currency: "number",
|
|
41
|
+
percent: "number",
|
|
42
|
+
rating: "number",
|
|
25
43
|
// DECIMAL seconds, unlike Airtable's, which is formatted to "HH:mm:ss".
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
44
|
+
// 1.0 typed this `string`, which was simply wrong — base-runner groups it
|
|
45
|
+
// with the numeric types — so it stays a number rather than reverting.
|
|
46
|
+
duration: "number",
|
|
47
|
+
checkbox: "boolean",
|
|
48
|
+
single_select: "string",
|
|
49
|
+
multiple_select: "string[]",
|
|
50
|
+
date: "string",
|
|
51
|
+
datetime: "string",
|
|
52
|
+
attachments: "ZiteAttachment[]",
|
|
33
53
|
// `string | string[]`, matching the pre-monorepo type. base-runner does force
|
|
34
54
|
// an array on read today, but 1.0 code is written with `typeof x === 'string'`
|
|
35
55
|
// guards — narrowing to `string[]` turns those branches into `never` and
|
|
36
56
|
// fails the app's typecheck for no gain.
|
|
37
57
|
linked_record: "string | string[]",
|
|
38
58
|
user: "string | string[]",
|
|
39
|
-
|
|
40
|
-
|
|
59
|
+
// `any`, not `unknown`, and deliberately: these are values the platform
|
|
60
|
+
// cannot type — a lookup is whatever the far side holds. 1.0 said `any`, and
|
|
61
|
+
// `unknown` buys nothing because there is no narrowing an app could have
|
|
62
|
+
// written in advance: `sum + (x || 0)` is a TS2365 on `unknown`, and the
|
|
63
|
+
// guarded spellings already narrowed fine under `any`.
|
|
64
|
+
lookup: "any",
|
|
65
|
+
rollup: "any",
|
|
41
66
|
autonumber: "number",
|
|
42
67
|
// JSONB change metadata (`{ type: "PublicAPI", apiKeyId: 3 }`), not a string.
|
|
43
|
-
source: "
|
|
44
|
-
formula: "
|
|
68
|
+
source: "any",
|
|
69
|
+
formula: "any",
|
|
45
70
|
created_at: "string",
|
|
46
71
|
updated_at: "string",
|
|
47
|
-
updated_by: "string
|
|
72
|
+
updated_by: "string",
|
|
48
73
|
};
|
|
49
74
|
/**
|
|
50
75
|
* Field types whose WRITE shape differs from their read shape — the API accepts
|
|
@@ -160,6 +185,21 @@ export function toCamelCase(name) {
|
|
|
160
185
|
const pascal = toPascalCase(name);
|
|
161
186
|
return pascal.charAt(0).toLowerCase() + pascal.slice(1);
|
|
162
187
|
}
|
|
188
|
+
/**
|
|
189
|
+
* camelCase for a FRESH sdkName, reading acronym runs as words: "VIP" ->
|
|
190
|
+
* "vip", "APIKey" -> "apiKey" (plain toCamelCase yields "vIP" / "aPIKey").
|
|
191
|
+
*
|
|
192
|
+
* Deliberately not folded into toCamelCase: that also derives endpoint
|
|
193
|
+
* identifiers from existing filenames on every generate, where normalizing
|
|
194
|
+
* would rename a working app's `api.sendSMS`. This is only for names being
|
|
195
|
+
* chosen for the first time — generateSchema preserves existing sdkNames.
|
|
196
|
+
*/
|
|
197
|
+
export function toSdkName(name) {
|
|
198
|
+
const deAcronymed = name
|
|
199
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, (_, run, next) => run.charAt(0) + run.slice(1).toLowerCase() + next)
|
|
200
|
+
.replace(/([A-Z])([A-Z]+)/g, (_, first, rest) => first + rest.toLowerCase());
|
|
201
|
+
return toCamelCase(deAcronymed);
|
|
202
|
+
}
|
|
163
203
|
/**
|
|
164
204
|
* Existing sdkNames are preserved across syncs so user code keeps compiling,
|
|
165
205
|
* but schemas written before the sanitizer stripped trailing symbols can carry
|
|
@@ -188,9 +228,9 @@ function tsTypeForSchemaField(def, variant = "read") {
|
|
|
188
228
|
.map((o) => `"${o.label.replace(/"/g, '\\"')}"`)
|
|
189
229
|
.join(" | ");
|
|
190
230
|
const union = `${literals} | string`;
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
231
|
+
// No `| null` on the read side — see FIELD_TYPE_MAP. The write side keeps
|
|
232
|
+
// it below, since null is how a select cell is cleared.
|
|
233
|
+
const read = def.type === "multiple_select" ? `(${union})[]` : union;
|
|
194
234
|
if (variant === "write") {
|
|
195
235
|
return def.type === "multiple_select"
|
|
196
236
|
? `${union} | (${union})[] | null`
|
|
@@ -328,13 +368,13 @@ export function generateSchema(database, existingSchema) {
|
|
|
328
368
|
const { id: _id, order: _order, ...definition } = field;
|
|
329
369
|
fields.push({
|
|
330
370
|
id: field.id,
|
|
331
|
-
sdkName: keepValidSdkName(existing?.sdkName) ??
|
|
371
|
+
sdkName: keepValidSdkName(existing?.sdkName) ?? toSdkName(field.name),
|
|
332
372
|
definition,
|
|
333
373
|
});
|
|
334
374
|
}
|
|
335
375
|
tables.push({
|
|
336
376
|
id: table.id,
|
|
337
|
-
sdkName: keepValidSdkName(existingTable?.sdkName) ??
|
|
377
|
+
sdkName: keepValidSdkName(existingTable?.sdkName) ?? toSdkName(table.name),
|
|
338
378
|
primaryFieldId: table.primaryFieldId,
|
|
339
379
|
fields,
|
|
340
380
|
});
|