appwrite-utils-cli 1.2.29 → 1.3.1
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 +52 -0
- package/dist/collections/attributes.js +2 -1
- package/dist/collections/methods.js +5 -5
- package/dist/config/yamlConfig.d.ts +11 -11
- package/dist/shared/attributeManager.js +12 -6
- package/dist/shared/schemaGenerator.js +74 -50
- package/dist/utils/schemaStrings.js +74 -50
- package/package.json +3 -3
- package/src/collections/attributes.ts +2 -1
- package/src/collections/methods.ts +6 -5
- package/src/shared/attributeManager.ts +10 -6
- package/src/shared/schemaGenerator.ts +76 -49
- package/src/utils/schemaStrings.ts +76 -49
package/README.md
CHANGED
@@ -327,6 +327,58 @@ This updated CLI ensures that developers have robust tools at their fingertips t
|
|
327
327
|
|
328
328
|
## Changelog
|
329
329
|
|
330
|
+
### 1.3.0 - Zod v4 Upgrade & Collection Management Fixes
|
331
|
+
|
332
|
+
**🎉 Major Release - Zod v4 Compatibility & Reliability Improvements**
|
333
|
+
|
334
|
+
#### Breaking Changes
|
335
|
+
- **Zod v4 Upgrade**: Updated to Zod v4.0.0 for enhanced schema validation
|
336
|
+
- ⚠️ **Potential Breaking Change**: Some schema validations may behave differently
|
337
|
+
- Function event types are now more flexible to accommodate Zod v4 changes
|
338
|
+
- Review your validation schemas if you experience issues
|
339
|
+
|
340
|
+
#### Major Bug Fixes
|
341
|
+
- **Fixed Duplicate Attribute Creation**: Resolved issue where attributes were being created multiple times
|
342
|
+
- Implemented intelligent filtering to only process new or changed attributes
|
343
|
+
- Enhanced status monitoring and error handling
|
344
|
+
- Significantly improved sync performance and reliability
|
345
|
+
|
346
|
+
- **Fixed Index Creation Issues**: Resolved indexes not being created from collection configurations
|
347
|
+
- Added proper null checks for index arrays from different collection sources
|
348
|
+
- Enhanced index creation with comprehensive status monitoring
|
349
|
+
- Improved error handling and retry logic for stuck indexes
|
350
|
+
|
351
|
+
#### Enhanced Collection Management
|
352
|
+
- **Smart Attribute Processing**: Attributes are now only created/updated when needed
|
353
|
+
- Compares existing vs. config attributes before processing
|
354
|
+
- Skips unchanged attributes with clear logging
|
355
|
+
- Better handling of edge cases and error conditions
|
356
|
+
|
357
|
+
- **Improved Index Handling**: More robust index creation from collection configs
|
358
|
+
- Proper fallback logic when indexes are undefined
|
359
|
+
- Enhanced compatibility with different collection sources
|
360
|
+
- Better error reporting and debugging information
|
361
|
+
|
362
|
+
#### Performance Improvements
|
363
|
+
- **Optimized Sync Operations**: Collections now process only necessary changes
|
364
|
+
- **Enhanced Status Monitoring**: Real-time feedback for attribute and index operations
|
365
|
+
- **Better Resource Management**: Reduced API calls through intelligent filtering
|
366
|
+
|
367
|
+
#### Developer Experience
|
368
|
+
- **Build Stability**: Resolved TypeScript compilation issues with function schemas
|
369
|
+
- **Type Safety**: Maintained strict typing while accommodating Zod v4 changes
|
370
|
+
- **Enhanced Logging**: Better progress reporting and error messages
|
371
|
+
|
372
|
+
#### Migration Guide
|
373
|
+
1. **Update Dependencies**: Ensure compatibility with Zod v4.0.0
|
374
|
+
2. **Test Collection Operations**: Verify that attribute and index creation works as expected
|
375
|
+
3. **Review Validations**: Check any custom validation schemas for potential breaking changes
|
376
|
+
4. **Function Events**: Function event arrays are now `string[]` for enhanced flexibility
|
377
|
+
|
378
|
+
**Integration Note**: This version significantly improves collection management reliability and provides full Zod v4 compatibility. The fixes address core synchronization issues that could cause duplicate resources or missing indexes.
|
379
|
+
|
380
|
+
---
|
381
|
+
|
330
382
|
### 1.1.0 - Enhanced Transfer System with Fault Tolerance
|
331
383
|
|
332
384
|
**🔧 Robust Transfer Operations with Status Monitoring**
|
@@ -277,7 +277,8 @@ export const createOrUpdateAttribute = async (db, dbId, collection, attribute) =
|
|
277
277
|
nameToIdMapping.set(finalAttribute.relatedCollection, relatedCollectionId);
|
278
278
|
}
|
279
279
|
}
|
280
|
-
|
280
|
+
// Only queue relationship attributes that have dependencies
|
281
|
+
if (finalAttribute.type === "relationship" && !(relatedCollectionId && collectionFoundViaRelatedCollection)) {
|
281
282
|
// console.log(`Enqueueing operation for attribute: ${finalAttribute.key}`);
|
282
283
|
enqueueOperation({
|
283
284
|
type: "attribute",
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { Client, Databases, ID, Permission, Query, } from "node-appwrite";
|
2
2
|
import { nameToIdMapping, processQueue } from "../shared/operationQueue.js";
|
3
|
-
import { createUpdateCollectionAttributes } from "./attributes.js";
|
4
|
-
import { createOrUpdateIndexes } from "./indexes.js";
|
3
|
+
import { createUpdateCollectionAttributes, createUpdateCollectionAttributesWithStatusCheck } from "./attributes.js";
|
4
|
+
import { createOrUpdateIndexes, createOrUpdateIndexesWithStatusCheck } from "./indexes.js";
|
5
5
|
import { SchemaGenerator } from "../shared/schemaGenerator.js";
|
6
6
|
import { isNull, isUndefined, isNil, isPlainObject, isString, isJSONValue, chunk, } from "es-toolkit";
|
7
7
|
import { delay, tryAwaitWithRetry } from "../utils/helperFunctions.js";
|
@@ -267,17 +267,17 @@ export const createOrUpdateCollections = async (database, databaseId, config, de
|
|
267
267
|
await delay(250);
|
268
268
|
// Update attributes and indexes for the collection
|
269
269
|
MessageFormatter.progress("Creating Attributes", { prefix: "Collections" });
|
270
|
-
await
|
270
|
+
await createUpdateCollectionAttributesWithStatusCheck(database, databaseId, collectionToUse,
|
271
271
|
// @ts-expect-error
|
272
272
|
attributes);
|
273
273
|
// Add delay after creating attributes
|
274
274
|
await delay(250);
|
275
|
-
const indexesToUse = indexes.length > 0
|
275
|
+
const indexesToUse = indexes && indexes.length > 0
|
276
276
|
? indexes
|
277
277
|
: config.collections?.find((c) => c.$id === collectionToUse.$id)
|
278
278
|
?.indexes ?? [];
|
279
279
|
MessageFormatter.progress("Creating Indexes", { prefix: "Collections" });
|
280
|
-
await
|
280
|
+
await createOrUpdateIndexesWithStatusCheck(databaseId, database, collectionToUse.$id, collectionToUse, indexesToUse);
|
281
281
|
// Add delay after creating indexes
|
282
282
|
await delay(250);
|
283
283
|
}
|
@@ -235,7 +235,7 @@ declare const YamlConfigSchema: z.ZodObject<{
|
|
235
235
|
functions: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodObject<{
|
236
236
|
id: z.ZodString;
|
237
237
|
name: z.ZodString;
|
238
|
-
runtime:
|
238
|
+
runtime: any;
|
239
239
|
execute: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
240
240
|
events: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
241
241
|
schedule: z.ZodOptional<z.ZodString>;
|
@@ -244,7 +244,7 @@ declare const YamlConfigSchema: z.ZodObject<{
|
|
244
244
|
logging: z.ZodOptional<z.ZodBoolean>;
|
245
245
|
entrypoint: z.ZodOptional<z.ZodString>;
|
246
246
|
commands: z.ZodOptional<z.ZodString>;
|
247
|
-
scopes: z.ZodOptional<z.ZodArray<z.
|
247
|
+
scopes: z.ZodOptional<z.ZodArray<z.ZodEffects<z.ZodString, "users.read" | "users.write" | "sessions.read" | "sessions.write" | "teams.read" | "teams.write" | "databases.read" | "databases.write" | "collections.read" | "collections.write" | "attributes.read" | "attributes.write" | "indexes.read" | "indexes.write" | "documents.read" | "documents.write" | "files.read" | "files.write" | "buckets.read" | "buckets.write" | "functions.read" | "functions.write" | "execution.read" | "execution.write" | "locale.read" | "avatars.read" | "health.read" | "rules.read" | "rules.write" | "migrations.read" | "migrations.write" | "sites.read" | "sites.write" | "log.read" | "log.write" | "tokens.read" | "tokens.write" | "vcs.read" | "vcs.write" | "assistant.read" | "messages.read" | "messages.write" | "targets.read" | "targets.write" | "providers.read" | "providers.write" | "topics.read" | "topics.write" | "subscribers.read" | "subscribers.write", string>, "many">>;
|
248
248
|
installationId: z.ZodOptional<z.ZodString>;
|
249
249
|
providerRepositoryId: z.ZodOptional<z.ZodString>;
|
250
250
|
providerBranch: z.ZodOptional<z.ZodString>;
|
@@ -254,7 +254,7 @@ declare const YamlConfigSchema: z.ZodObject<{
|
|
254
254
|
templateOwner: z.ZodOptional<z.ZodString>;
|
255
255
|
templateRootDirectory: z.ZodOptional<z.ZodString>;
|
256
256
|
templateBranch: z.ZodOptional<z.ZodString>;
|
257
|
-
specification: z.ZodOptional<z.
|
257
|
+
specification: z.ZodOptional<z.ZodEffects<z.ZodString, "s-0.5vcpu-512mb" | "s-1vcpu-512mb" | "s-1vcpu-1gb" | "s-2vcpu-2gb" | "s-2vcpu-4gb" | "s-4vcpu-4gb" | "s-4vcpu-8gb" | "s-8vcpu-4gb" | "s-8vcpu-8gb", string>>;
|
258
258
|
dirPath: z.ZodOptional<z.ZodString>;
|
259
259
|
predeployCommands: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
260
260
|
deployDir: z.ZodOptional<z.ZodString>;
|
@@ -263,9 +263,9 @@ declare const YamlConfigSchema: z.ZodObject<{
|
|
263
263
|
}, "strip", z.ZodTypeAny, {
|
264
264
|
name: string;
|
265
265
|
id: string;
|
266
|
-
runtime: "node-14.5" | "node-16.0" | "node-18.0" | "node-19.0" | "node-20.0" | "node-21.0" | "node-22" | "bun-1.0" | "bun-1.1" | "deno-1.21" | "deno-1.24" | "deno-1.35" | "deno-1.40" | "deno-1.46" | "deno-2.0" | "go-1.23" | "python-3.8" | "python-3.9" | "python-3.10" | "python-3.11" | "python-3.12" | "python-ml-3.11" | "dart-2.15" | "dart-2.16" | "dart-2.17" | "dart-2.18" | "dart-3.0" | "dart-3.1" | "dart-3.3" | "dart-3.5" | "php-8.0" | "php-8.1" | "php-8.2" | "php-8.3" | "ruby-3.0" | "ruby-3.1" | "ruby-3.2" | "ruby-3.3" | "dotnet-6.0" | "dotnet-7.0" | "dotnet-8.0" | "java-8.0" | "java-11.0" | "java-17.0" | "java-18.0" | "java-21.0" | "java-22" | "swift-5.5" | "swift-5.8" | "swift-5.9" | "swift-5.10" | "kotlin-1.6" | "kotlin-1.8" | "kotlin-1.9" | "kotlin-2.0" | "cpp-17" | "cpp-20";
|
267
266
|
enabled?: boolean | undefined;
|
268
267
|
logging?: boolean | undefined;
|
268
|
+
runtime?: any;
|
269
269
|
execute?: string[] | undefined;
|
270
270
|
events?: string[] | undefined;
|
271
271
|
schedule?: string | undefined;
|
@@ -291,16 +291,16 @@ declare const YamlConfigSchema: z.ZodObject<{
|
|
291
291
|
}, {
|
292
292
|
name: string;
|
293
293
|
id: string;
|
294
|
-
runtime: "node-14.5" | "node-16.0" | "node-18.0" | "node-19.0" | "node-20.0" | "node-21.0" | "node-22" | "bun-1.0" | "bun-1.1" | "deno-1.21" | "deno-1.24" | "deno-1.35" | "deno-1.40" | "deno-1.46" | "deno-2.0" | "go-1.23" | "python-3.8" | "python-3.9" | "python-3.10" | "python-3.11" | "python-3.12" | "python-ml-3.11" | "dart-2.15" | "dart-2.16" | "dart-2.17" | "dart-2.18" | "dart-3.0" | "dart-3.1" | "dart-3.3" | "dart-3.5" | "php-8.0" | "php-8.1" | "php-8.2" | "php-8.3" | "ruby-3.0" | "ruby-3.1" | "ruby-3.2" | "ruby-3.3" | "dotnet-6.0" | "dotnet-7.0" | "dotnet-8.0" | "java-8.0" | "java-11.0" | "java-17.0" | "java-18.0" | "java-21.0" | "java-22" | "swift-5.5" | "swift-5.8" | "swift-5.9" | "swift-5.10" | "kotlin-1.6" | "kotlin-1.8" | "kotlin-1.9" | "kotlin-2.0" | "cpp-17" | "cpp-20";
|
295
294
|
enabled?: boolean | undefined;
|
296
295
|
logging?: boolean | undefined;
|
296
|
+
runtime?: any;
|
297
297
|
execute?: string[] | undefined;
|
298
298
|
events?: string[] | undefined;
|
299
299
|
schedule?: string | undefined;
|
300
300
|
timeout?: number | undefined;
|
301
301
|
entrypoint?: string | undefined;
|
302
302
|
commands?: string | undefined;
|
303
|
-
scopes?:
|
303
|
+
scopes?: string[] | undefined;
|
304
304
|
installationId?: string | undefined;
|
305
305
|
providerRepositoryId?: string | undefined;
|
306
306
|
providerBranch?: string | undefined;
|
@@ -310,7 +310,7 @@ declare const YamlConfigSchema: z.ZodObject<{
|
|
310
310
|
templateOwner?: string | undefined;
|
311
311
|
templateRootDirectory?: string | undefined;
|
312
312
|
templateBranch?: string | undefined;
|
313
|
-
specification?:
|
313
|
+
specification?: string | undefined;
|
314
314
|
dirPath?: string | undefined;
|
315
315
|
predeployCommands?: string[] | undefined;
|
316
316
|
deployDir?: string | undefined;
|
@@ -391,9 +391,9 @@ declare const YamlConfigSchema: z.ZodObject<{
|
|
391
391
|
functions: {
|
392
392
|
name: string;
|
393
393
|
id: string;
|
394
|
-
runtime: "node-14.5" | "node-16.0" | "node-18.0" | "node-19.0" | "node-20.0" | "node-21.0" | "node-22" | "bun-1.0" | "bun-1.1" | "deno-1.21" | "deno-1.24" | "deno-1.35" | "deno-1.40" | "deno-1.46" | "deno-2.0" | "go-1.23" | "python-3.8" | "python-3.9" | "python-3.10" | "python-3.11" | "python-3.12" | "python-ml-3.11" | "dart-2.15" | "dart-2.16" | "dart-2.17" | "dart-2.18" | "dart-3.0" | "dart-3.1" | "dart-3.3" | "dart-3.5" | "php-8.0" | "php-8.1" | "php-8.2" | "php-8.3" | "ruby-3.0" | "ruby-3.1" | "ruby-3.2" | "ruby-3.3" | "dotnet-6.0" | "dotnet-7.0" | "dotnet-8.0" | "java-8.0" | "java-11.0" | "java-17.0" | "java-18.0" | "java-21.0" | "java-22" | "swift-5.5" | "swift-5.8" | "swift-5.9" | "swift-5.10" | "kotlin-1.6" | "kotlin-1.8" | "kotlin-1.9" | "kotlin-2.0" | "cpp-17" | "cpp-20";
|
395
394
|
enabled?: boolean | undefined;
|
396
395
|
logging?: boolean | undefined;
|
396
|
+
runtime?: any;
|
397
397
|
execute?: string[] | undefined;
|
398
398
|
events?: string[] | undefined;
|
399
399
|
schedule?: string | undefined;
|
@@ -485,16 +485,16 @@ declare const YamlConfigSchema: z.ZodObject<{
|
|
485
485
|
functions?: {
|
486
486
|
name: string;
|
487
487
|
id: string;
|
488
|
-
runtime: "node-14.5" | "node-16.0" | "node-18.0" | "node-19.0" | "node-20.0" | "node-21.0" | "node-22" | "bun-1.0" | "bun-1.1" | "deno-1.21" | "deno-1.24" | "deno-1.35" | "deno-1.40" | "deno-1.46" | "deno-2.0" | "go-1.23" | "python-3.8" | "python-3.9" | "python-3.10" | "python-3.11" | "python-3.12" | "python-ml-3.11" | "dart-2.15" | "dart-2.16" | "dart-2.17" | "dart-2.18" | "dart-3.0" | "dart-3.1" | "dart-3.3" | "dart-3.5" | "php-8.0" | "php-8.1" | "php-8.2" | "php-8.3" | "ruby-3.0" | "ruby-3.1" | "ruby-3.2" | "ruby-3.3" | "dotnet-6.0" | "dotnet-7.0" | "dotnet-8.0" | "java-8.0" | "java-11.0" | "java-17.0" | "java-18.0" | "java-21.0" | "java-22" | "swift-5.5" | "swift-5.8" | "swift-5.9" | "swift-5.10" | "kotlin-1.6" | "kotlin-1.8" | "kotlin-1.9" | "kotlin-2.0" | "cpp-17" | "cpp-20";
|
489
488
|
enabled?: boolean | undefined;
|
490
489
|
logging?: boolean | undefined;
|
490
|
+
runtime?: any;
|
491
491
|
execute?: string[] | undefined;
|
492
492
|
events?: string[] | undefined;
|
493
493
|
schedule?: string | undefined;
|
494
494
|
timeout?: number | undefined;
|
495
495
|
entrypoint?: string | undefined;
|
496
496
|
commands?: string | undefined;
|
497
|
-
scopes?:
|
497
|
+
scopes?: string[] | undefined;
|
498
498
|
installationId?: string | undefined;
|
499
499
|
providerRepositoryId?: string | undefined;
|
500
500
|
providerBranch?: string | undefined;
|
@@ -504,7 +504,7 @@ declare const YamlConfigSchema: z.ZodObject<{
|
|
504
504
|
templateOwner?: string | undefined;
|
505
505
|
templateRootDirectory?: string | undefined;
|
506
506
|
templateBranch?: string | undefined;
|
507
|
-
specification?:
|
507
|
+
specification?: string | undefined;
|
508
508
|
dirPath?: string | undefined;
|
509
509
|
predeployCommands?: string[] | undefined;
|
510
510
|
deployDir?: string | undefined;
|
@@ -32,14 +32,20 @@ export const attributesSame = (databaseAttribute, configAttribute) => {
|
|
32
32
|
const configValue = configAttribute[attr];
|
33
33
|
// Use type-specific default values when comparing
|
34
34
|
if (databaseAttribute.type === "integer") {
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
if (attr === "min") {
|
36
|
+
return (dbValue ?? -2147483647) === (configValue ?? -2147483647);
|
37
|
+
}
|
38
|
+
else { // attr === "max"
|
39
|
+
return (dbValue ?? 2147483647) === (configValue ?? 2147483647);
|
40
|
+
}
|
38
41
|
}
|
39
42
|
if (databaseAttribute.type === "double" || databaseAttribute.type === "float") {
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
+
if (attr === "min") {
|
44
|
+
return (dbValue ?? -2147483647) === (configValue ?? -2147483647);
|
45
|
+
}
|
46
|
+
else { // attr === "max"
|
47
|
+
return (dbValue ?? 2147483647) === (configValue ?? 2147483647);
|
48
|
+
}
|
43
49
|
}
|
44
50
|
}
|
45
51
|
// Check if both objects have the attribute
|
@@ -354,62 +354,86 @@ export default appwriteConfig;
|
|
354
354
|
const isArray = detail.isArray ? "array" : "";
|
355
355
|
return [relatedCollectionName, key, isArray];
|
356
356
|
});
|
357
|
-
|
358
|
-
|
359
|
-
let
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
357
|
+
// Check if we have any relationships - if not, generate simple schema
|
358
|
+
const hasRelationships = relatedCollections.length > 0;
|
359
|
+
let schemaString = `${imports}\n\n`;
|
360
|
+
if (!hasRelationships) {
|
361
|
+
// Simple case: no relationships, generate single schema directly
|
362
|
+
schemaString += `export const ${pascalName}Schema = z.object({\n`;
|
363
|
+
schemaString += ` $id: z.string(),\n`;
|
364
|
+
schemaString += ` $createdAt: z.string(),\n`;
|
365
|
+
schemaString += ` $updatedAt: z.string(),\n`;
|
366
|
+
schemaString += ` $permissions: z.array(z.string()),\n`;
|
367
|
+
for (const attribute of attributes) {
|
368
|
+
if (attribute.type === "relationship") {
|
369
|
+
continue;
|
370
|
+
}
|
371
|
+
schemaString += ` ${attribute.key}: ${this.typeToZod(attribute)},\n`;
|
371
372
|
}
|
372
|
-
|
373
|
-
|
374
|
-
|
373
|
+
schemaString += `});\n\n`;
|
374
|
+
schemaString += `export type ${pascalName} = z.infer<typeof ${pascalName}Schema>;\n\n`;
|
375
|
+
}
|
376
|
+
else {
|
377
|
+
// Complex case: has relationships, generate BaseSchema + extended schema pattern
|
378
|
+
let relatedTypes = "";
|
379
|
+
let relatedTypesLazy = "";
|
380
|
+
let curNum = 0;
|
381
|
+
let maxNum = relatedCollections.length;
|
382
|
+
relatedCollections.forEach((relatedCollection) => {
|
383
|
+
console.log(relatedCollection);
|
384
|
+
let relatedPascalName = toPascalCase(relatedCollection[0]);
|
385
|
+
let relatedCamelName = toCamelCase(relatedCollection[0]);
|
386
|
+
curNum++;
|
387
|
+
let endNameTypes = relatedPascalName;
|
388
|
+
let endNameLazy = `${relatedPascalName}Schema`;
|
389
|
+
if (relatedCollection[2] === "array") {
|
390
|
+
endNameTypes += "[]";
|
391
|
+
endNameLazy += ".array().default([])";
|
392
|
+
}
|
393
|
+
else if (!(relatedCollection[2] === "array")) {
|
394
|
+
endNameTypes += " | null";
|
395
|
+
endNameLazy += ".nullish()";
|
396
|
+
}
|
397
|
+
imports += `import { ${relatedPascalName}Schema, type ${relatedPascalName} } from "./${relatedCamelName}";\n`;
|
398
|
+
relatedTypes += `${relatedCollection[1]}?: ${endNameTypes};\n`;
|
399
|
+
if (relatedTypes.length > 0 && curNum !== maxNum) {
|
400
|
+
relatedTypes += " ";
|
401
|
+
}
|
402
|
+
relatedTypesLazy += `${relatedCollection[1]}: z.lazy(() => ${endNameLazy}),\n`;
|
403
|
+
if (relatedTypesLazy.length > 0 && curNum !== maxNum) {
|
404
|
+
relatedTypesLazy += " ";
|
405
|
+
}
|
406
|
+
});
|
407
|
+
// Re-add imports after processing relationships
|
408
|
+
schemaString = `${imports}\n\n`;
|
409
|
+
schemaString += `export const ${pascalName}SchemaBase = z.object({\n`;
|
410
|
+
schemaString += ` $id: z.string(),\n`;
|
411
|
+
schemaString += ` $createdAt: z.string(),\n`;
|
412
|
+
schemaString += ` $updatedAt: z.string(),\n`;
|
413
|
+
schemaString += ` $permissions: z.array(z.string()),\n`;
|
414
|
+
for (const attribute of attributes) {
|
415
|
+
if (attribute.type === "relationship") {
|
416
|
+
continue;
|
417
|
+
}
|
418
|
+
schemaString += ` ${attribute.key}: ${this.typeToZod(attribute)},\n`;
|
375
419
|
}
|
376
|
-
|
377
|
-
|
378
|
-
if (relatedTypes.length > 0
|
379
|
-
|
420
|
+
schemaString += `});\n\n`;
|
421
|
+
schemaString += `export type ${pascalName}Base = z.infer<typeof ${pascalName}SchemaBase>`;
|
422
|
+
if (relatedTypes.length > 0) {
|
423
|
+
schemaString += ` & {\n ${relatedTypes}};\n\n`;
|
380
424
|
}
|
381
|
-
|
382
|
-
|
383
|
-
relatedTypesLazy += " ";
|
425
|
+
else {
|
426
|
+
schemaString += `;\n\n`;
|
384
427
|
}
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
schemaString += ` $id: z.string().optional(),\n`;
|
389
|
-
schemaString += ` $createdAt: z.string().optional(),\n`;
|
390
|
-
schemaString += ` $updatedAt: z.string().optional(),\n`;
|
391
|
-
for (const attribute of attributes) {
|
392
|
-
if (attribute.type === "relationship") {
|
393
|
-
continue;
|
428
|
+
schemaString += `export const ${pascalName}Schema: z.ZodType<${pascalName}Base> = ${pascalName}SchemaBase`;
|
429
|
+
if (relatedTypes.length > 0) {
|
430
|
+
schemaString += `.extend({\n ${relatedTypesLazy}});\n\n`;
|
394
431
|
}
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
if (relatedTypes.length > 0) {
|
400
|
-
schemaString += ` & {\n ${relatedTypes}};\n\n`;
|
401
|
-
}
|
402
|
-
else {
|
403
|
-
schemaString += `;\n\n`;
|
404
|
-
}
|
405
|
-
schemaString += `export const ${pascalName}Schema: z.ZodType<${pascalName}Base> = ${pascalName}SchemaBase`;
|
406
|
-
if (relatedTypes.length > 0) {
|
407
|
-
schemaString += `.extend({\n ${relatedTypesLazy}});\n\n`;
|
408
|
-
}
|
409
|
-
else {
|
410
|
-
schemaString += `;\n`;
|
432
|
+
else {
|
433
|
+
schemaString += `;\n`;
|
434
|
+
}
|
435
|
+
schemaString += `export type ${pascalName} = z.infer<typeof ${pascalName}Schema>;\n\n`;
|
411
436
|
}
|
412
|
-
schemaString += `export type ${pascalName} = z.infer<typeof ${pascalName}Schema>;\n\n`;
|
413
437
|
return schemaString;
|
414
438
|
};
|
415
439
|
typeToZod = (attribute) => {
|
@@ -233,62 +233,86 @@ export class SchemaGenerator {
|
|
233
233
|
const isArray = detail.isArray ? "array" : "";
|
234
234
|
return [relatedCollectionName, key, isArray];
|
235
235
|
});
|
236
|
-
|
237
|
-
|
238
|
-
let
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
236
|
+
// Check if we have any relationships - if not, generate simple schema
|
237
|
+
const hasRelationships = relatedCollections.length > 0;
|
238
|
+
let schemaString = `${imports}\n\n`;
|
239
|
+
if (!hasRelationships) {
|
240
|
+
// Simple case: no relationships, generate single schema directly
|
241
|
+
schemaString += `export const ${pascalName}Schema = z.object({\n`;
|
242
|
+
schemaString += ` $id: z.string(),\n`;
|
243
|
+
schemaString += ` $createdAt: z.string(),\n`;
|
244
|
+
schemaString += ` $updatedAt: z.string(),\n`;
|
245
|
+
schemaString += ` $permissions: z.array(z.string()),\n`;
|
246
|
+
for (const attribute of attributes) {
|
247
|
+
if (attribute.type === "relationship") {
|
248
|
+
continue;
|
249
|
+
}
|
250
|
+
schemaString += ` ${attribute.key}: ${this.typeToZod(attribute)},\n`;
|
250
251
|
}
|
251
|
-
|
252
|
-
|
253
|
-
|
252
|
+
schemaString += `});\n\n`;
|
253
|
+
schemaString += `export type ${pascalName} = z.infer<typeof ${pascalName}Schema>;\n\n`;
|
254
|
+
}
|
255
|
+
else {
|
256
|
+
// Complex case: has relationships, generate BaseSchema + extended schema pattern
|
257
|
+
let relatedTypes = "";
|
258
|
+
let relatedTypesLazy = "";
|
259
|
+
let curNum = 0;
|
260
|
+
let maxNum = relatedCollections.length;
|
261
|
+
relatedCollections.forEach((relatedCollection) => {
|
262
|
+
console.log(relatedCollection);
|
263
|
+
let relatedPascalName = toPascalCase(relatedCollection[0]);
|
264
|
+
let relatedCamelName = toCamelCase(relatedCollection[0]);
|
265
|
+
curNum++;
|
266
|
+
let endNameTypes = relatedPascalName;
|
267
|
+
let endNameLazy = `${relatedPascalName}Schema`;
|
268
|
+
if (relatedCollection[2] === "array") {
|
269
|
+
endNameTypes += "[]";
|
270
|
+
endNameLazy += ".array().default([])";
|
271
|
+
}
|
272
|
+
else if (!(relatedCollection[2] === "array")) {
|
273
|
+
endNameTypes += " | null";
|
274
|
+
endNameLazy += ".nullish()";
|
275
|
+
}
|
276
|
+
imports += `import { ${relatedPascalName}Schema, type ${relatedPascalName} } from "./${relatedCamelName}";\n`;
|
277
|
+
relatedTypes += `${relatedCollection[1]}?: ${endNameTypes};\n`;
|
278
|
+
if (relatedTypes.length > 0 && curNum !== maxNum) {
|
279
|
+
relatedTypes += " ";
|
280
|
+
}
|
281
|
+
relatedTypesLazy += `${relatedCollection[1]}: z.lazy(() => ${endNameLazy}),\n`;
|
282
|
+
if (relatedTypesLazy.length > 0 && curNum !== maxNum) {
|
283
|
+
relatedTypesLazy += " ";
|
284
|
+
}
|
285
|
+
});
|
286
|
+
// Re-add imports after processing relationships
|
287
|
+
schemaString = `${imports}\n\n`;
|
288
|
+
schemaString += `export const ${pascalName}SchemaBase = z.object({\n`;
|
289
|
+
schemaString += ` $id: z.string(),\n`;
|
290
|
+
schemaString += ` $createdAt: z.string(),\n`;
|
291
|
+
schemaString += ` $updatedAt: z.string(),\n`;
|
292
|
+
schemaString += ` $permissions: z.array(z.string()),\n`;
|
293
|
+
for (const attribute of attributes) {
|
294
|
+
if (attribute.type === "relationship") {
|
295
|
+
continue;
|
296
|
+
}
|
297
|
+
schemaString += ` ${attribute.key}: ${this.typeToZod(attribute)},\n`;
|
254
298
|
}
|
255
|
-
|
256
|
-
|
257
|
-
if (relatedTypes.length > 0
|
258
|
-
|
299
|
+
schemaString += `});\n\n`;
|
300
|
+
schemaString += `export type ${pascalName}Base = z.infer<typeof ${pascalName}SchemaBase>`;
|
301
|
+
if (relatedTypes.length > 0) {
|
302
|
+
schemaString += ` & {\n ${relatedTypes}};\n\n`;
|
259
303
|
}
|
260
|
-
|
261
|
-
|
262
|
-
relatedTypesLazy += " ";
|
304
|
+
else {
|
305
|
+
schemaString += `;\n\n`;
|
263
306
|
}
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
schemaString += ` $id: z.string().optional(),\n`;
|
268
|
-
schemaString += ` $createdAt: z.string().optional(),\n`;
|
269
|
-
schemaString += ` $updatedAt: z.string().optional(),\n`;
|
270
|
-
for (const attribute of attributes) {
|
271
|
-
if (attribute.type === "relationship") {
|
272
|
-
continue;
|
307
|
+
schemaString += `export const ${pascalName}Schema: z.ZodType<${pascalName}Base> = ${pascalName}SchemaBase`;
|
308
|
+
if (relatedTypes.length > 0) {
|
309
|
+
schemaString += `.extend({\n ${relatedTypesLazy}});\n\n`;
|
273
310
|
}
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
if (relatedTypes.length > 0) {
|
279
|
-
schemaString += ` & {\n ${relatedTypes}};\n\n`;
|
280
|
-
}
|
281
|
-
else {
|
282
|
-
schemaString += `;\n\n`;
|
283
|
-
}
|
284
|
-
schemaString += `export const ${pascalName}Schema: z.ZodType<${pascalName}Base> = ${pascalName}SchemaBase`;
|
285
|
-
if (relatedTypes.length > 0) {
|
286
|
-
schemaString += `.extend({\n ${relatedTypesLazy}});\n\n`;
|
287
|
-
}
|
288
|
-
else {
|
289
|
-
schemaString += `;\n`;
|
311
|
+
else {
|
312
|
+
schemaString += `;\n`;
|
313
|
+
}
|
314
|
+
schemaString += `export type ${pascalName} = z.infer<typeof ${pascalName}Schema>;\n\n`;
|
290
315
|
}
|
291
|
-
schemaString += `export type ${pascalName} = z.infer<typeof ${pascalName}Schema>;\n\n`;
|
292
316
|
return schemaString;
|
293
317
|
};
|
294
318
|
typeToZod = (attribute) => {
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "appwrite-utils-cli",
|
3
3
|
"description": "Appwrite Utility Functions to help with database management, data conversion, data import, migrations, and much more. Meant to be used as a CLI tool, I do not recommend installing this in frontend environments.",
|
4
|
-
"version": "1.
|
4
|
+
"version": "1.3.1",
|
5
5
|
"main": "src/main.ts",
|
6
6
|
"type": "module",
|
7
7
|
"repository": {
|
@@ -33,7 +33,7 @@
|
|
33
33
|
"@types/inquirer": "^9.0.8",
|
34
34
|
"@types/json-schema": "^7.0.15",
|
35
35
|
"@types/yargs": "^17.0.33",
|
36
|
-
"appwrite-utils": "^1.
|
36
|
+
"appwrite-utils": "^1.3.1",
|
37
37
|
"chalk": "^5.4.1",
|
38
38
|
"cli-progress": "^3.12.0",
|
39
39
|
"commander": "^12.1.0",
|
@@ -50,7 +50,7 @@
|
|
50
50
|
"ulidx": "^2.4.1",
|
51
51
|
"winston": "^3.17.0",
|
52
52
|
"yargs": "^18.0.0",
|
53
|
-
"zod": "^
|
53
|
+
"zod": "^4.0.0"
|
54
54
|
},
|
55
55
|
"devDependencies": {
|
56
56
|
"@types/cli-progress": "^3.11.6",
|
@@ -437,7 +437,8 @@ export const createOrUpdateAttribute = async (
|
|
437
437
|
);
|
438
438
|
}
|
439
439
|
}
|
440
|
-
|
440
|
+
// Only queue relationship attributes that have dependencies
|
441
|
+
if (finalAttribute.type === "relationship" && !(relatedCollectionId && collectionFoundViaRelatedCollection)) {
|
441
442
|
// console.log(`Enqueueing operation for attribute: ${finalAttribute.key}`);
|
442
443
|
enqueueOperation({
|
443
444
|
type: "attribute",
|
@@ -8,8 +8,8 @@ import {
|
|
8
8
|
} from "node-appwrite";
|
9
9
|
import type { AppwriteConfig, CollectionCreate, Indexes } from "appwrite-utils";
|
10
10
|
import { nameToIdMapping, processQueue } from "../shared/operationQueue.js";
|
11
|
-
import { createUpdateCollectionAttributes } from "./attributes.js";
|
12
|
-
import { createOrUpdateIndexes } from "./indexes.js";
|
11
|
+
import { createUpdateCollectionAttributes, createUpdateCollectionAttributesWithStatusCheck } from "./attributes.js";
|
12
|
+
import { createOrUpdateIndexes, createOrUpdateIndexesWithStatusCheck } from "./indexes.js";
|
13
13
|
import { SchemaGenerator } from "../shared/schemaGenerator.js";
|
14
14
|
import {
|
15
15
|
isNull,
|
@@ -426,7 +426,7 @@ export const createOrUpdateCollections = async (
|
|
426
426
|
|
427
427
|
// Update attributes and indexes for the collection
|
428
428
|
MessageFormatter.progress("Creating Attributes", { prefix: "Collections" });
|
429
|
-
await
|
429
|
+
await createUpdateCollectionAttributesWithStatusCheck(
|
430
430
|
database,
|
431
431
|
databaseId,
|
432
432
|
collectionToUse!,
|
@@ -438,16 +438,17 @@ export const createOrUpdateCollections = async (
|
|
438
438
|
await delay(250);
|
439
439
|
|
440
440
|
const indexesToUse =
|
441
|
-
indexes.length > 0
|
441
|
+
indexes && indexes.length > 0
|
442
442
|
? indexes
|
443
443
|
: config.collections?.find((c) => c.$id === collectionToUse!.$id)
|
444
444
|
?.indexes ?? [];
|
445
445
|
|
446
446
|
MessageFormatter.progress("Creating Indexes", { prefix: "Collections" });
|
447
|
-
await
|
447
|
+
await createOrUpdateIndexesWithStatusCheck(
|
448
448
|
databaseId,
|
449
449
|
database,
|
450
450
|
collectionToUse!.$id,
|
451
|
+
collectionToUse!,
|
451
452
|
indexesToUse as Indexes
|
452
453
|
);
|
453
454
|
|
@@ -43,14 +43,18 @@ export const attributesSame = (
|
|
43
43
|
|
44
44
|
// Use type-specific default values when comparing
|
45
45
|
if (databaseAttribute.type === "integer") {
|
46
|
-
|
47
|
-
|
48
|
-
|
46
|
+
if (attr === "min") {
|
47
|
+
return (dbValue ?? -2147483647) === (configValue ?? -2147483647);
|
48
|
+
} else { // attr === "max"
|
49
|
+
return (dbValue ?? 2147483647) === (configValue ?? 2147483647);
|
50
|
+
}
|
49
51
|
}
|
50
52
|
if (databaseAttribute.type === "double" || databaseAttribute.type === "float") {
|
51
|
-
|
52
|
-
|
53
|
-
|
53
|
+
if (attr === "min") {
|
54
|
+
return (dbValue ?? -2147483647) === (configValue ?? -2147483647);
|
55
|
+
} else { // attr === "max"
|
56
|
+
return (dbValue ?? 2147483647) === (configValue ?? 2147483647);
|
57
|
+
}
|
54
58
|
}
|
55
59
|
}
|
56
60
|
|
@@ -443,60 +443,87 @@ export default appwriteConfig;
|
|
443
443
|
return [relatedCollectionName, key, isArray];
|
444
444
|
});
|
445
445
|
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
let
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
446
|
+
// Check if we have any relationships - if not, generate simple schema
|
447
|
+
const hasRelationships = relatedCollections.length > 0;
|
448
|
+
|
449
|
+
let schemaString = `${imports}\n\n`;
|
450
|
+
|
451
|
+
if (!hasRelationships) {
|
452
|
+
// Simple case: no relationships, generate single schema directly
|
453
|
+
schemaString += `export const ${pascalName}Schema = z.object({\n`;
|
454
|
+
schemaString += ` $id: z.string(),\n`;
|
455
|
+
schemaString += ` $createdAt: z.string(),\n`;
|
456
|
+
schemaString += ` $updatedAt: z.string(),\n`;
|
457
|
+
schemaString += ` $permissions: z.array(z.string()),\n`;
|
458
|
+
for (const attribute of attributes) {
|
459
|
+
if (attribute.type === "relationship") {
|
460
|
+
continue;
|
461
|
+
}
|
462
|
+
schemaString += ` ${attribute.key}: ${this.typeToZod(attribute)},\n`;
|
463
463
|
}
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
464
|
+
schemaString += `});\n\n`;
|
465
|
+
schemaString += `export type ${pascalName} = z.infer<typeof ${pascalName}Schema>;\n\n`;
|
466
|
+
} else {
|
467
|
+
// Complex case: has relationships, generate BaseSchema + extended schema pattern
|
468
|
+
let relatedTypes = "";
|
469
|
+
let relatedTypesLazy = "";
|
470
|
+
let curNum = 0;
|
471
|
+
let maxNum = relatedCollections.length;
|
472
|
+
|
473
|
+
relatedCollections.forEach((relatedCollection) => {
|
474
|
+
console.log(relatedCollection);
|
475
|
+
let relatedPascalName = toPascalCase(relatedCollection[0]);
|
476
|
+
let relatedCamelName = toCamelCase(relatedCollection[0]);
|
477
|
+
curNum++;
|
478
|
+
let endNameTypes = relatedPascalName;
|
479
|
+
let endNameLazy = `${relatedPascalName}Schema`;
|
480
|
+
if (relatedCollection[2] === "array") {
|
481
|
+
endNameTypes += "[]";
|
482
|
+
endNameLazy += ".array().default([])";
|
483
|
+
} else if (!(relatedCollection[2] === "array")) {
|
484
|
+
endNameTypes += " | null";
|
485
|
+
endNameLazy += ".nullish()";
|
486
|
+
}
|
487
|
+
imports += `import { ${relatedPascalName}Schema, type ${relatedPascalName} } from "./${relatedCamelName}";\n`;
|
488
|
+
relatedTypes += `${relatedCollection[1]}?: ${endNameTypes};\n`;
|
489
|
+
if (relatedTypes.length > 0 && curNum !== maxNum) {
|
490
|
+
relatedTypes += " ";
|
491
|
+
}
|
492
|
+
relatedTypesLazy += `${relatedCollection[1]}: z.lazy(() => ${endNameLazy}),\n`;
|
493
|
+
if (relatedTypesLazy.length > 0 && curNum !== maxNum) {
|
494
|
+
relatedTypesLazy += " ";
|
495
|
+
}
|
496
|
+
});
|
497
|
+
|
498
|
+
// Re-add imports after processing relationships
|
499
|
+
schemaString = `${imports}\n\n`;
|
500
|
+
|
501
|
+
schemaString += `export const ${pascalName}SchemaBase = z.object({\n`;
|
502
|
+
schemaString += ` $id: z.string(),\n`;
|
503
|
+
schemaString += ` $createdAt: z.string(),\n`;
|
504
|
+
schemaString += ` $updatedAt: z.string(),\n`;
|
505
|
+
schemaString += ` $permissions: z.array(z.string()),\n`;
|
506
|
+
for (const attribute of attributes) {
|
507
|
+
if (attribute.type === "relationship") {
|
508
|
+
continue;
|
509
|
+
}
|
510
|
+
schemaString += ` ${attribute.key}: ${this.typeToZod(attribute)},\n`;
|
468
511
|
}
|
469
|
-
|
470
|
-
|
471
|
-
|
512
|
+
schemaString += `});\n\n`;
|
513
|
+
schemaString += `export type ${pascalName}Base = z.infer<typeof ${pascalName}SchemaBase>`;
|
514
|
+
if (relatedTypes.length > 0) {
|
515
|
+
schemaString += ` & {\n ${relatedTypes}};\n\n`;
|
516
|
+
} else {
|
517
|
+
schemaString += `;\n\n`;
|
472
518
|
}
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
schemaString += ` $createdAt: z.string().optional(),\n`;
|
479
|
-
schemaString += ` $updatedAt: z.string().optional(),\n`;
|
480
|
-
for (const attribute of attributes) {
|
481
|
-
if (attribute.type === "relationship") {
|
482
|
-
continue;
|
519
|
+
schemaString += `export const ${pascalName}Schema: z.ZodType<${pascalName}Base> = ${pascalName}SchemaBase`;
|
520
|
+
if (relatedTypes.length > 0) {
|
521
|
+
schemaString += `.extend({\n ${relatedTypesLazy}});\n\n`;
|
522
|
+
} else {
|
523
|
+
schemaString += `;\n`;
|
483
524
|
}
|
484
|
-
schemaString += `
|
485
|
-
}
|
486
|
-
schemaString += `});\n\n`;
|
487
|
-
schemaString += `export type ${pascalName}Base = z.infer<typeof ${pascalName}SchemaBase>`;
|
488
|
-
if (relatedTypes.length > 0) {
|
489
|
-
schemaString += ` & {\n ${relatedTypes}};\n\n`;
|
490
|
-
} else {
|
491
|
-
schemaString += `;\n\n`;
|
492
|
-
}
|
493
|
-
schemaString += `export const ${pascalName}Schema: z.ZodType<${pascalName}Base> = ${pascalName}SchemaBase`;
|
494
|
-
if (relatedTypes.length > 0) {
|
495
|
-
schemaString += `.extend({\n ${relatedTypesLazy}});\n\n`;
|
496
|
-
} else {
|
497
|
-
schemaString += `;\n`;
|
525
|
+
schemaString += `export type ${pascalName} = z.infer<typeof ${pascalName}Schema>;\n\n`;
|
498
526
|
}
|
499
|
-
schemaString += `export type ${pascalName} = z.infer<typeof ${pascalName}Schema>;\n\n`;
|
500
527
|
|
501
528
|
return schemaString;
|
502
529
|
};
|
@@ -306,60 +306,87 @@ export class SchemaGenerator {
|
|
306
306
|
return [relatedCollectionName, key, isArray];
|
307
307
|
});
|
308
308
|
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
let
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
309
|
+
// Check if we have any relationships - if not, generate simple schema
|
310
|
+
const hasRelationships = relatedCollections.length > 0;
|
311
|
+
|
312
|
+
let schemaString = `${imports}\n\n`;
|
313
|
+
|
314
|
+
if (!hasRelationships) {
|
315
|
+
// Simple case: no relationships, generate single schema directly
|
316
|
+
schemaString += `export const ${pascalName}Schema = z.object({\n`;
|
317
|
+
schemaString += ` $id: z.string(),\n`;
|
318
|
+
schemaString += ` $createdAt: z.string(),\n`;
|
319
|
+
schemaString += ` $updatedAt: z.string(),\n`;
|
320
|
+
schemaString += ` $permissions: z.array(z.string()),\n`;
|
321
|
+
for (const attribute of attributes) {
|
322
|
+
if (attribute.type === "relationship") {
|
323
|
+
continue;
|
324
|
+
}
|
325
|
+
schemaString += ` ${attribute.key}: ${this.typeToZod(attribute)},\n`;
|
326
326
|
}
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
327
|
+
schemaString += `});\n\n`;
|
328
|
+
schemaString += `export type ${pascalName} = z.infer<typeof ${pascalName}Schema>;\n\n`;
|
329
|
+
} else {
|
330
|
+
// Complex case: has relationships, generate BaseSchema + extended schema pattern
|
331
|
+
let relatedTypes = "";
|
332
|
+
let relatedTypesLazy = "";
|
333
|
+
let curNum = 0;
|
334
|
+
let maxNum = relatedCollections.length;
|
335
|
+
|
336
|
+
relatedCollections.forEach((relatedCollection) => {
|
337
|
+
console.log(relatedCollection);
|
338
|
+
let relatedPascalName = toPascalCase(relatedCollection[0]);
|
339
|
+
let relatedCamelName = toCamelCase(relatedCollection[0]);
|
340
|
+
curNum++;
|
341
|
+
let endNameTypes = relatedPascalName;
|
342
|
+
let endNameLazy = `${relatedPascalName}Schema`;
|
343
|
+
if (relatedCollection[2] === "array") {
|
344
|
+
endNameTypes += "[]";
|
345
|
+
endNameLazy += ".array().default([])";
|
346
|
+
} else if (!(relatedCollection[2] === "array")) {
|
347
|
+
endNameTypes += " | null";
|
348
|
+
endNameLazy += ".nullish()";
|
349
|
+
}
|
350
|
+
imports += `import { ${relatedPascalName}Schema, type ${relatedPascalName} } from "./${relatedCamelName}";\n`;
|
351
|
+
relatedTypes += `${relatedCollection[1]}?: ${endNameTypes};\n`;
|
352
|
+
if (relatedTypes.length > 0 && curNum !== maxNum) {
|
353
|
+
relatedTypes += " ";
|
354
|
+
}
|
355
|
+
relatedTypesLazy += `${relatedCollection[1]}: z.lazy(() => ${endNameLazy}),\n`;
|
356
|
+
if (relatedTypesLazy.length > 0 && curNum !== maxNum) {
|
357
|
+
relatedTypesLazy += " ";
|
358
|
+
}
|
359
|
+
});
|
360
|
+
|
361
|
+
// Re-add imports after processing relationships
|
362
|
+
schemaString = `${imports}\n\n`;
|
363
|
+
|
364
|
+
schemaString += `export const ${pascalName}SchemaBase = z.object({\n`;
|
365
|
+
schemaString += ` $id: z.string(),\n`;
|
366
|
+
schemaString += ` $createdAt: z.string(),\n`;
|
367
|
+
schemaString += ` $updatedAt: z.string(),\n`;
|
368
|
+
schemaString += ` $permissions: z.array(z.string()),\n`;
|
369
|
+
for (const attribute of attributes) {
|
370
|
+
if (attribute.type === "relationship") {
|
371
|
+
continue;
|
372
|
+
}
|
373
|
+
schemaString += ` ${attribute.key}: ${this.typeToZod(attribute)},\n`;
|
331
374
|
}
|
332
|
-
|
333
|
-
|
334
|
-
|
375
|
+
schemaString += `});\n\n`;
|
376
|
+
schemaString += `export type ${pascalName}Base = z.infer<typeof ${pascalName}SchemaBase>`;
|
377
|
+
if (relatedTypes.length > 0) {
|
378
|
+
schemaString += ` & {\n ${relatedTypes}};\n\n`;
|
379
|
+
} else {
|
380
|
+
schemaString += `;\n\n`;
|
335
381
|
}
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
schemaString += ` $createdAt: z.string().optional(),\n`;
|
342
|
-
schemaString += ` $updatedAt: z.string().optional(),\n`;
|
343
|
-
for (const attribute of attributes) {
|
344
|
-
if (attribute.type === "relationship") {
|
345
|
-
continue;
|
382
|
+
schemaString += `export const ${pascalName}Schema: z.ZodType<${pascalName}Base> = ${pascalName}SchemaBase`;
|
383
|
+
if (relatedTypes.length > 0) {
|
384
|
+
schemaString += `.extend({\n ${relatedTypesLazy}});\n\n`;
|
385
|
+
} else {
|
386
|
+
schemaString += `;\n`;
|
346
387
|
}
|
347
|
-
schemaString += `
|
348
|
-
}
|
349
|
-
schemaString += `});\n\n`;
|
350
|
-
schemaString += `export type ${pascalName}Base = z.infer<typeof ${pascalName}SchemaBase>`;
|
351
|
-
if (relatedTypes.length > 0) {
|
352
|
-
schemaString += ` & {\n ${relatedTypes}};\n\n`;
|
353
|
-
} else {
|
354
|
-
schemaString += `;\n\n`;
|
355
|
-
}
|
356
|
-
schemaString += `export const ${pascalName}Schema: z.ZodType<${pascalName}Base> = ${pascalName}SchemaBase`;
|
357
|
-
if (relatedTypes.length > 0) {
|
358
|
-
schemaString += `.extend({\n ${relatedTypesLazy}});\n\n`;
|
359
|
-
} else {
|
360
|
-
schemaString += `;\n`;
|
388
|
+
schemaString += `export type ${pascalName} = z.infer<typeof ${pascalName}Schema>;\n\n`;
|
361
389
|
}
|
362
|
-
schemaString += `export type ${pascalName} = z.infer<typeof ${pascalName}Schema>;\n\n`;
|
363
390
|
|
364
391
|
return schemaString;
|
365
392
|
};
|