zitejs 0.9.101 → 0.9.102
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.js +75 -11
- package/dist/esm/sync/lib.js +75 -11
- package/package.json +1 -1
package/dist/cjs/sync/lib.js
CHANGED
|
@@ -151,7 +151,9 @@ const DATE_FORMAT_EXAMPLES = {
|
|
|
151
151
|
};
|
|
152
152
|
const withDateFormatExample = (format) => {
|
|
153
153
|
const example = DATE_FORMAT_EXAMPLES[format];
|
|
154
|
-
return example
|
|
154
|
+
return example
|
|
155
|
+
? `"${format}" format (e.g. ${example})`
|
|
156
|
+
: `"${format}" format`;
|
|
155
157
|
};
|
|
156
158
|
function toPascalCase(name) {
|
|
157
159
|
const pascal = name
|
|
@@ -196,7 +198,9 @@ function tsTypeForSchemaField(def, variant = "read") {
|
|
|
196
198
|
.map((o) => `"${o.label.replace(/"/g, '\\"')}"`)
|
|
197
199
|
.join(" | ");
|
|
198
200
|
const union = `${literals} | string`;
|
|
199
|
-
const read = def.type === "multiple_select"
|
|
201
|
+
const read = def.type === "multiple_select"
|
|
202
|
+
? `(${union})[] | null`
|
|
203
|
+
: `${union} | null`;
|
|
200
204
|
if (variant === "write") {
|
|
201
205
|
return def.type === "multiple_select"
|
|
202
206
|
? `${union} | (${union})[] | null`
|
|
@@ -447,7 +451,7 @@ function generateDbTs(schema) {
|
|
|
447
451
|
lines.push("// .findAll({ filters?, sort?, offset?, limit?, fields? }) → { records: T[], hasMore: boolean }");
|
|
448
452
|
lines.push("// filters: { fieldName: value } for equality, or { fieldName: { <op>: value } }");
|
|
449
453
|
lines.push("// operators: contains, not, in, notIn, lt, lte, gt, gte");
|
|
450
|
-
lines.push('// `not: null` means "is set". An empty `in: []` matches nothing; an',
|
|
454
|
+
lines.push('// `not: null` means "is set". An empty `in: []` matches nothing; an', "// empty `notIn: []` applies no filter.");
|
|
451
455
|
lines.push("// sort is currently IGNORED here — it is stripped before the request.", "// (it does work on zite.auth.findAllUsers). Order in SQL instead.");
|
|
452
456
|
lines.push("// limit defaults to 500, max 2000; offset is a row count (a number)");
|
|
453
457
|
lines.push("// .findOne({ id?, filters?, fields? }) → T | undefined");
|
|
@@ -620,12 +624,52 @@ function inspectEndpointFile(source) {
|
|
|
620
624
|
* words are legal object keys.
|
|
621
625
|
*/
|
|
622
626
|
const RESERVED_IDENTIFIERS = new Set([
|
|
623
|
-
"await",
|
|
624
|
-
"
|
|
625
|
-
"
|
|
626
|
-
"
|
|
627
|
-
"
|
|
628
|
-
"
|
|
627
|
+
"await",
|
|
628
|
+
"break",
|
|
629
|
+
"case",
|
|
630
|
+
"catch",
|
|
631
|
+
"class",
|
|
632
|
+
"const",
|
|
633
|
+
"continue",
|
|
634
|
+
"debugger",
|
|
635
|
+
"default",
|
|
636
|
+
"delete",
|
|
637
|
+
"do",
|
|
638
|
+
"else",
|
|
639
|
+
"enum",
|
|
640
|
+
"export",
|
|
641
|
+
"extends",
|
|
642
|
+
"false",
|
|
643
|
+
"finally",
|
|
644
|
+
"for",
|
|
645
|
+
"function",
|
|
646
|
+
"if",
|
|
647
|
+
"implements",
|
|
648
|
+
"import",
|
|
649
|
+
"in",
|
|
650
|
+
"instanceof",
|
|
651
|
+
"interface",
|
|
652
|
+
"let",
|
|
653
|
+
"new",
|
|
654
|
+
"null",
|
|
655
|
+
"package",
|
|
656
|
+
"private",
|
|
657
|
+
"protected",
|
|
658
|
+
"public",
|
|
659
|
+
"return",
|
|
660
|
+
"static",
|
|
661
|
+
"super",
|
|
662
|
+
"switch",
|
|
663
|
+
"this",
|
|
664
|
+
"throw",
|
|
665
|
+
"true",
|
|
666
|
+
"try",
|
|
667
|
+
"typeof",
|
|
668
|
+
"var",
|
|
669
|
+
"void",
|
|
670
|
+
"while",
|
|
671
|
+
"with",
|
|
672
|
+
"yield",
|
|
629
673
|
]);
|
|
630
674
|
const toSafeIdentifier = (camelName) => RESERVED_IDENTIFIERS.has(camelName) ? `_${camelName}` : camelName;
|
|
631
675
|
function generateApiTs(endpointFiles) {
|
|
@@ -955,7 +999,7 @@ function generateAirtableTs(lock) {
|
|
|
955
999
|
'// each carries its current user-facing name in quotes (// "Task Name"), which is',
|
|
956
1000
|
"// the source of truth for what it means.",
|
|
957
1001
|
"// Values are RAW; format them for display using each field's comment.",
|
|
958
|
-
|
|
1002
|
+
'// Fields marked "Links to X" hold Airtable record ids (rec...) from',
|
|
959
1003
|
"// findOne/findAll — never invent one.",
|
|
960
1004
|
"// Read-only fields are absent from the *RecordInput types: Airtable rejects a",
|
|
961
1005
|
"// write to a computed one (formula, rollup, lookup, autonumber, the created/",
|
|
@@ -1066,11 +1110,31 @@ function generateBackendWrapperTs(envVarNames = []) {
|
|
|
1066
1110
|
" * compile and throw. `Omit` keeps any index signature merged in by",
|
|
1067
1111
|
" * `.zite/user-extensions.d.ts`, so a migrated user-sync app still reads its",
|
|
1068
1112
|
" * synced columns off this.",
|
|
1113
|
+
" *",
|
|
1114
|
+
" * The `Pick` intersection is not redundant. On an app that DOES merge in",
|
|
1115
|
+
" * `[key: string]: any`, `keyof User` widens to `string`, `Exclude` then",
|
|
1116
|
+
" * removes nothing, and the `Omit` collapses to a bare index signature —",
|
|
1117
|
+
" * which would silently degrade `user.id` from `string` to `any`. The `Pick`",
|
|
1118
|
+
" * names those members explicitly, so they survive the collapse.",
|
|
1119
|
+
" *",
|
|
1120
|
+
" * Only `id` and `email` are pinned that way, deliberately. On a user-sync",
|
|
1121
|
+
" * app `context.user` IS the synced row (`buildUserContext` returns it",
|
|
1122
|
+
" * whole), and only those two are guaranteed by the runtime: the id is the",
|
|
1123
|
+
" * record id and the email is merged in explicitly. `firstName`/`lastName`",
|
|
1124
|
+
" * come from whatever the app mapped those columns to, so pinning them to",
|
|
1125
|
+
" * `string` would reject a legitimate read on a table that types them",
|
|
1126
|
+
" * differently. Non-widened apps get both from the `Omit` regardless.",
|
|
1127
|
+
" *",
|
|
1128
|
+
" * On such an app `user.createdAt` still compiles, as `any`. That is",
|
|
1129
|
+
" * deliberate: a synced user table may legitimately have its own",
|
|
1130
|
+
" * `createdAt` column, and typing it `never` to close the hole would break",
|
|
1131
|
+
" * exactly the legacy apps `user-extensions.d.ts` exists to keep compiling.",
|
|
1069
1132
|
" */",
|
|
1070
1133
|
"export type ZiteEndpointUser = Omit<",
|
|
1071
1134
|
" User,",
|
|
1072
1135
|
" 'name' | 'emailVerified' | 'image' | 'createdAt' | 'updatedAt'",
|
|
1073
|
-
"
|
|
1136
|
+
"> &",
|
|
1137
|
+
" Pick<User, 'id' | 'email'>;",
|
|
1074
1138
|
"",
|
|
1075
1139
|
'export interface ZiteRequestContext extends Omit<_ZiteRequestContext, "user"> {',
|
|
1076
1140
|
" user: ZiteEndpointUser;",
|
package/dist/esm/sync/lib.js
CHANGED
|
@@ -141,7 +141,9 @@ const DATE_FORMAT_EXAMPLES = {
|
|
|
141
141
|
};
|
|
142
142
|
const withDateFormatExample = (format) => {
|
|
143
143
|
const example = DATE_FORMAT_EXAMPLES[format];
|
|
144
|
-
return example
|
|
144
|
+
return example
|
|
145
|
+
? `"${format}" format (e.g. ${example})`
|
|
146
|
+
: `"${format}" format`;
|
|
145
147
|
};
|
|
146
148
|
export function toPascalCase(name) {
|
|
147
149
|
const pascal = name
|
|
@@ -186,7 +188,9 @@ function tsTypeForSchemaField(def, variant = "read") {
|
|
|
186
188
|
.map((o) => `"${o.label.replace(/"/g, '\\"')}"`)
|
|
187
189
|
.join(" | ");
|
|
188
190
|
const union = `${literals} | string`;
|
|
189
|
-
const read = def.type === "multiple_select"
|
|
191
|
+
const read = def.type === "multiple_select"
|
|
192
|
+
? `(${union})[] | null`
|
|
193
|
+
: `${union} | null`;
|
|
190
194
|
if (variant === "write") {
|
|
191
195
|
return def.type === "multiple_select"
|
|
192
196
|
? `${union} | (${union})[] | null`
|
|
@@ -437,7 +441,7 @@ export function generateDbTs(schema) {
|
|
|
437
441
|
lines.push("// .findAll({ filters?, sort?, offset?, limit?, fields? }) → { records: T[], hasMore: boolean }");
|
|
438
442
|
lines.push("// filters: { fieldName: value } for equality, or { fieldName: { <op>: value } }");
|
|
439
443
|
lines.push("// operators: contains, not, in, notIn, lt, lte, gt, gte");
|
|
440
|
-
lines.push('// `not: null` means "is set". An empty `in: []` matches nothing; an',
|
|
444
|
+
lines.push('// `not: null` means "is set". An empty `in: []` matches nothing; an', "// empty `notIn: []` applies no filter.");
|
|
441
445
|
lines.push("// sort is currently IGNORED here — it is stripped before the request.", "// (it does work on zite.auth.findAllUsers). Order in SQL instead.");
|
|
442
446
|
lines.push("// limit defaults to 500, max 2000; offset is a row count (a number)");
|
|
443
447
|
lines.push("// .findOne({ id?, filters?, fields? }) → T | undefined");
|
|
@@ -610,12 +614,52 @@ function inspectEndpointFile(source) {
|
|
|
610
614
|
* words are legal object keys.
|
|
611
615
|
*/
|
|
612
616
|
const RESERVED_IDENTIFIERS = new Set([
|
|
613
|
-
"await",
|
|
614
|
-
"
|
|
615
|
-
"
|
|
616
|
-
"
|
|
617
|
-
"
|
|
618
|
-
"
|
|
617
|
+
"await",
|
|
618
|
+
"break",
|
|
619
|
+
"case",
|
|
620
|
+
"catch",
|
|
621
|
+
"class",
|
|
622
|
+
"const",
|
|
623
|
+
"continue",
|
|
624
|
+
"debugger",
|
|
625
|
+
"default",
|
|
626
|
+
"delete",
|
|
627
|
+
"do",
|
|
628
|
+
"else",
|
|
629
|
+
"enum",
|
|
630
|
+
"export",
|
|
631
|
+
"extends",
|
|
632
|
+
"false",
|
|
633
|
+
"finally",
|
|
634
|
+
"for",
|
|
635
|
+
"function",
|
|
636
|
+
"if",
|
|
637
|
+
"implements",
|
|
638
|
+
"import",
|
|
639
|
+
"in",
|
|
640
|
+
"instanceof",
|
|
641
|
+
"interface",
|
|
642
|
+
"let",
|
|
643
|
+
"new",
|
|
644
|
+
"null",
|
|
645
|
+
"package",
|
|
646
|
+
"private",
|
|
647
|
+
"protected",
|
|
648
|
+
"public",
|
|
649
|
+
"return",
|
|
650
|
+
"static",
|
|
651
|
+
"super",
|
|
652
|
+
"switch",
|
|
653
|
+
"this",
|
|
654
|
+
"throw",
|
|
655
|
+
"true",
|
|
656
|
+
"try",
|
|
657
|
+
"typeof",
|
|
658
|
+
"var",
|
|
659
|
+
"void",
|
|
660
|
+
"while",
|
|
661
|
+
"with",
|
|
662
|
+
"yield",
|
|
619
663
|
]);
|
|
620
664
|
const toSafeIdentifier = (camelName) => RESERVED_IDENTIFIERS.has(camelName) ? `_${camelName}` : camelName;
|
|
621
665
|
export function generateApiTs(endpointFiles) {
|
|
@@ -945,7 +989,7 @@ export function generateAirtableTs(lock) {
|
|
|
945
989
|
'// each carries its current user-facing name in quotes (// "Task Name"), which is',
|
|
946
990
|
"// the source of truth for what it means.",
|
|
947
991
|
"// Values are RAW; format them for display using each field's comment.",
|
|
948
|
-
|
|
992
|
+
'// Fields marked "Links to X" hold Airtable record ids (rec...) from',
|
|
949
993
|
"// findOne/findAll — never invent one.",
|
|
950
994
|
"// Read-only fields are absent from the *RecordInput types: Airtable rejects a",
|
|
951
995
|
"// write to a computed one (formula, rollup, lookup, autonumber, the created/",
|
|
@@ -1056,11 +1100,31 @@ export function generateBackendWrapperTs(envVarNames = []) {
|
|
|
1056
1100
|
" * compile and throw. `Omit` keeps any index signature merged in by",
|
|
1057
1101
|
" * `.zite/user-extensions.d.ts`, so a migrated user-sync app still reads its",
|
|
1058
1102
|
" * synced columns off this.",
|
|
1103
|
+
" *",
|
|
1104
|
+
" * The `Pick` intersection is not redundant. On an app that DOES merge in",
|
|
1105
|
+
" * `[key: string]: any`, `keyof User` widens to `string`, `Exclude` then",
|
|
1106
|
+
" * removes nothing, and the `Omit` collapses to a bare index signature —",
|
|
1107
|
+
" * which would silently degrade `user.id` from `string` to `any`. The `Pick`",
|
|
1108
|
+
" * names those members explicitly, so they survive the collapse.",
|
|
1109
|
+
" *",
|
|
1110
|
+
" * Only `id` and `email` are pinned that way, deliberately. On a user-sync",
|
|
1111
|
+
" * app `context.user` IS the synced row (`buildUserContext` returns it",
|
|
1112
|
+
" * whole), and only those two are guaranteed by the runtime: the id is the",
|
|
1113
|
+
" * record id and the email is merged in explicitly. `firstName`/`lastName`",
|
|
1114
|
+
" * come from whatever the app mapped those columns to, so pinning them to",
|
|
1115
|
+
" * `string` would reject a legitimate read on a table that types them",
|
|
1116
|
+
" * differently. Non-widened apps get both from the `Omit` regardless.",
|
|
1117
|
+
" *",
|
|
1118
|
+
" * On such an app `user.createdAt` still compiles, as `any`. That is",
|
|
1119
|
+
" * deliberate: a synced user table may legitimately have its own",
|
|
1120
|
+
" * `createdAt` column, and typing it `never` to close the hole would break",
|
|
1121
|
+
" * exactly the legacy apps `user-extensions.d.ts` exists to keep compiling.",
|
|
1059
1122
|
" */",
|
|
1060
1123
|
"export type ZiteEndpointUser = Omit<",
|
|
1061
1124
|
" User,",
|
|
1062
1125
|
" 'name' | 'emailVerified' | 'image' | 'createdAt' | 'updatedAt'",
|
|
1063
|
-
"
|
|
1126
|
+
"> &",
|
|
1127
|
+
" Pick<User, 'id' | 'email'>;",
|
|
1064
1128
|
"",
|
|
1065
1129
|
'export interface ZiteRequestContext extends Omit<_ZiteRequestContext, "user"> {',
|
|
1066
1130
|
" user: ZiteEndpointUser;",
|