appwrite-utils-cli 1.6.6 → 1.6.8
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/collections/attributes.js +7 -0
- package/dist/collections/methods.js +4 -4
- package/dist/config/services/ConfigLoaderService.d.ts +17 -0
- package/dist/config/services/ConfigLoaderService.js +84 -0
- package/dist/migrations/yaml/generateImportSchemas.js +8 -0
- package/dist/utils/configDiscovery.js +9 -3
- package/dist/utils/setupFiles.js +16 -0
- package/package.json +1 -1
- package/src/collections/attributes.ts +11 -0
- package/src/collections/methods.ts +4 -4
- package/src/config/services/ConfigLoaderService.ts +119 -0
- package/src/migrations/yaml/generateImportSchemas.ts +8 -0
- package/src/utils/configDiscovery.ts +9 -3
- package/src/utils/setupFiles.ts +16 -0
@@ -607,6 +607,13 @@ const attributesSame = (databaseAttribute, configAttribute) => {
|
|
607
607
|
operation: 'attributesSame'
|
608
608
|
});
|
609
609
|
}
|
610
|
+
// Log differences if comparison failed (for debugging)
|
611
|
+
if (!result && differences.length > 0) {
|
612
|
+
MessageFormatter.debug(`Attribute '${configAttribute.key}' differences detected:`, { prefix: "Attributes" });
|
613
|
+
differences.forEach(diff => {
|
614
|
+
MessageFormatter.debug(` ${diff}`, { prefix: "Attributes" });
|
615
|
+
});
|
616
|
+
}
|
610
617
|
return result;
|
611
618
|
};
|
612
619
|
/**
|
@@ -224,9 +224,9 @@ export const createOrUpdateCollections = async (database, databaseId, config, de
|
|
224
224
|
attributes);
|
225
225
|
// Add delay after creating attributes
|
226
226
|
await delay(250);
|
227
|
-
//
|
227
|
+
// Prefer local config indexes, but fall back to collection's own indexes if no local config exists
|
228
228
|
const localCollectionConfig = config.collections?.find(c => c.name === collectionData.name || c.$id === collectionData.$id);
|
229
|
-
const indexesToUse = localCollectionConfig?.indexes
|
229
|
+
const indexesToUse = localCollectionConfig?.indexes ?? indexes ?? [];
|
230
230
|
MessageFormatter.progress("Creating Indexes", { prefix: "Collections" });
|
231
231
|
await createOrUpdateIndexesWithStatusCheck(databaseId, database, collectionToUse.$id, collectionToUse, indexesToUse);
|
232
232
|
// Delete indexes that exist on server but not in local config
|
@@ -428,9 +428,9 @@ export const createOrUpdateCollectionsViaAdapter = async (adapter, databaseId, c
|
|
428
428
|
}
|
429
429
|
}
|
430
430
|
}
|
431
|
-
//
|
431
|
+
// Prefer local config indexes, but fall back to collection's own indexes if no local config exists (TablesDB path)
|
432
432
|
const localTableConfig = config.collections?.find(c => c.name === collectionData.name || c.$id === collectionData.$id);
|
433
|
-
const idxs = (localTableConfig?.indexes
|
433
|
+
const idxs = (localTableConfig?.indexes ?? indexes ?? []);
|
434
434
|
for (const idx of idxs) {
|
435
435
|
try {
|
436
436
|
await adapter.createIndex({
|
@@ -90,6 +90,23 @@ export declare class ConfigLoaderService {
|
|
90
90
|
source2: string;
|
91
91
|
}>;
|
92
92
|
}>;
|
93
|
+
/**
|
94
|
+
* Loads tables first (higher priority), then collections (backward compatibility)
|
95
|
+
* Used for TablesDB projects (>= 1.8.0)
|
96
|
+
* @param tablesDir Path to the tables directory
|
97
|
+
* @param collectionsDir Path to the collections directory
|
98
|
+
* @returns Loading result with items, counts, and conflicts
|
99
|
+
*/
|
100
|
+
loadTablesFirst(tablesDir: string, collectionsDir: string): Promise<{
|
101
|
+
items: Collection[];
|
102
|
+
fromCollections: number;
|
103
|
+
fromTables: number;
|
104
|
+
conflicts: Array<{
|
105
|
+
name: string;
|
106
|
+
source1: string;
|
107
|
+
source2: string;
|
108
|
+
}>;
|
109
|
+
}>;
|
93
110
|
/**
|
94
111
|
* Validates that a configuration file can be loaded
|
95
112
|
* @param configPath Path to the configuration file
|
@@ -112,6 +112,42 @@ export class ConfigLoaderService {
|
|
112
112
|
};
|
113
113
|
}
|
114
114
|
}
|
115
|
+
// Load collections and tables from their respective directories
|
116
|
+
const configDir = path.dirname(yamlPath);
|
117
|
+
const collectionsDir = path.join(configDir, config.schemaConfig?.collectionsDirectory || "collections");
|
118
|
+
const tablesDir = path.join(configDir, config.schemaConfig?.tablesDirectory || "tables");
|
119
|
+
// Detect API mode to determine priority order
|
120
|
+
let apiMode = 'legacy';
|
121
|
+
try {
|
122
|
+
const { detectAppwriteVersionCached } = await import('../../utils/versionDetection.js');
|
123
|
+
const detection = await detectAppwriteVersionCached(config.appwriteEndpoint, config.appwriteProject, config.appwriteKey);
|
124
|
+
apiMode = detection.apiMode;
|
125
|
+
}
|
126
|
+
catch {
|
127
|
+
// Fallback to legacy if detection fails
|
128
|
+
}
|
129
|
+
// Load with correct priority based on API mode
|
130
|
+
const { items, conflicts, fromCollections, fromTables } = apiMode === 'tablesdb'
|
131
|
+
? await this.loadTablesFirst(tablesDir, collectionsDir)
|
132
|
+
: await this.loadCollectionsAndTables(collectionsDir, tablesDir);
|
133
|
+
config.collections = items;
|
134
|
+
// Report what was loaded
|
135
|
+
if (fromTables > 0 && fromCollections > 0) {
|
136
|
+
MessageFormatter.success(`Loaded ${items.length} total items: ${fromCollections} from collections/, ${fromTables} from tables/`, { prefix: "Config" });
|
137
|
+
}
|
138
|
+
else if (fromCollections > 0) {
|
139
|
+
MessageFormatter.success(`Loaded ${fromCollections} collections from collections/`, { prefix: "Config" });
|
140
|
+
}
|
141
|
+
else if (fromTables > 0) {
|
142
|
+
MessageFormatter.success(`Loaded ${fromTables} tables from tables/`, { prefix: "Config" });
|
143
|
+
}
|
144
|
+
// Report conflicts
|
145
|
+
if (conflicts.length > 0) {
|
146
|
+
MessageFormatter.warning(`Found ${conflicts.length} naming conflicts`, { prefix: "Config" });
|
147
|
+
conflicts.forEach(conflict => {
|
148
|
+
MessageFormatter.info(` - '${conflict.name}': ${conflict.source1} (used) vs ${conflict.source2} (skipped)`, { prefix: "Config" });
|
149
|
+
});
|
150
|
+
}
|
115
151
|
MessageFormatter.success(`Loaded YAML config from: ${yamlPath}`, {
|
116
152
|
prefix: "Config",
|
117
153
|
});
|
@@ -377,6 +413,54 @@ export class ConfigLoaderService {
|
|
377
413
|
conflicts,
|
378
414
|
};
|
379
415
|
}
|
416
|
+
/**
|
417
|
+
* Loads tables first (higher priority), then collections (backward compatibility)
|
418
|
+
* Used for TablesDB projects (>= 1.8.0)
|
419
|
+
* @param tablesDir Path to the tables directory
|
420
|
+
* @param collectionsDir Path to the collections directory
|
421
|
+
* @returns Loading result with items, counts, and conflicts
|
422
|
+
*/
|
423
|
+
async loadTablesFirst(tablesDir, collectionsDir) {
|
424
|
+
const items = [];
|
425
|
+
const loadedNames = new Set();
|
426
|
+
const conflicts = [];
|
427
|
+
// Load from tables/ directory first (HIGHER priority for TablesDB)
|
428
|
+
if (fs.existsSync(tablesDir)) {
|
429
|
+
const tables = await this.loadTables(tablesDir, { markAsTablesDir: true });
|
430
|
+
for (const table of tables) {
|
431
|
+
const name = table.name || table.tableId || table.$id || "";
|
432
|
+
loadedNames.add(name);
|
433
|
+
items.push(table);
|
434
|
+
}
|
435
|
+
}
|
436
|
+
// Load from collections/ directory second (LOWER priority, backward compatibility)
|
437
|
+
if (fs.existsSync(collectionsDir)) {
|
438
|
+
const collections = await this.loadCollections(collectionsDir);
|
439
|
+
for (const collection of collections) {
|
440
|
+
const name = collection.name || collection.$id || "";
|
441
|
+
// Check for conflicts - tables win
|
442
|
+
if (loadedNames.has(name)) {
|
443
|
+
conflicts.push({
|
444
|
+
name,
|
445
|
+
source1: "tables/",
|
446
|
+
source2: "collections/",
|
447
|
+
});
|
448
|
+
}
|
449
|
+
else {
|
450
|
+
loadedNames.add(name);
|
451
|
+
items.push(collection);
|
452
|
+
}
|
453
|
+
}
|
454
|
+
}
|
455
|
+
const fromTables = items.filter((item) => item._isFromTablesDir).length;
|
456
|
+
const fromCollections = items.filter((item) => !item._isFromTablesDir).length;
|
457
|
+
return {
|
458
|
+
items,
|
459
|
+
fromCollections,
|
460
|
+
fromTables,
|
461
|
+
conflicts,
|
462
|
+
};
|
463
|
+
}
|
380
464
|
/**
|
381
465
|
* Validates that a configuration file can be loaded
|
382
466
|
* @param configPath Path to the configuration file
|
@@ -462,6 +462,14 @@ export function generateCollectionSchema() {
|
|
462
462
|
"side": {
|
463
463
|
"type": "string",
|
464
464
|
"enum": ["parent", "child"]
|
465
|
+
},
|
466
|
+
"encrypt": {
|
467
|
+
"type": "boolean",
|
468
|
+
"description": "Whether the attribute should be encrypted"
|
469
|
+
},
|
470
|
+
"format": {
|
471
|
+
"type": "string",
|
472
|
+
"description": "Format for string attributes (e.g., email, url, ip)"
|
465
473
|
}
|
466
474
|
},
|
467
475
|
"required": ["key", "type"],
|
@@ -123,7 +123,9 @@ const YamlCollectionSchema = z.object({
|
|
123
123
|
twoWay: z.boolean().optional(),
|
124
124
|
twoWayKey: z.string().optional(),
|
125
125
|
onDelete: z.string().optional(),
|
126
|
-
side: z.string().optional()
|
126
|
+
side: z.string().optional(),
|
127
|
+
encrypt: z.boolean().optional(),
|
128
|
+
format: z.string().optional()
|
127
129
|
})).optional().default([]),
|
128
130
|
indexes: z.array(z.object({
|
129
131
|
key: z.string(),
|
@@ -168,7 +170,9 @@ export const loadYamlCollection = (filePath) => {
|
|
168
170
|
twoWay: attr.twoWay,
|
169
171
|
twoWayKey: attr.twoWayKey,
|
170
172
|
onDelete: attr.onDelete,
|
171
|
-
side: attr.side
|
173
|
+
side: attr.side,
|
174
|
+
encrypted: attr.encrypt,
|
175
|
+
format: attr.format
|
172
176
|
})),
|
173
177
|
indexes: parsedCollection.indexes.map(idx => ({
|
174
178
|
key: idx.key,
|
@@ -221,7 +225,9 @@ export const loadYamlTable = (filePath) => {
|
|
221
225
|
twoWay: attr.twoWay,
|
222
226
|
twoWayKey: attr.twoWayKey,
|
223
227
|
onDelete: attr.onDelete,
|
224
|
-
side: attr.side
|
228
|
+
side: attr.side,
|
229
|
+
encrypted: attr.encrypt,
|
230
|
+
format: attr.format
|
225
231
|
})),
|
226
232
|
indexes: parsedTable.indexes.map(idx => ({
|
227
233
|
key: idx.key,
|
package/dist/utils/setupFiles.js
CHANGED
@@ -479,6 +479,14 @@ importDefs: []
|
|
479
479
|
"type": "string",
|
480
480
|
"description": "Column description"
|
481
481
|
},
|
482
|
+
"encrypt": {
|
483
|
+
"type": "boolean",
|
484
|
+
"description": "Whether the column should be encrypted"
|
485
|
+
},
|
486
|
+
"format": {
|
487
|
+
"type": "string",
|
488
|
+
"description": "Format for string columns"
|
489
|
+
},
|
482
490
|
"min": {
|
483
491
|
"type": "number",
|
484
492
|
"description": "Minimum value for numeric columns"
|
@@ -673,6 +681,14 @@ importDefs: []
|
|
673
681
|
"type": "string",
|
674
682
|
"description": "Attribute description"
|
675
683
|
},
|
684
|
+
"encrypt": {
|
685
|
+
"type": "boolean",
|
686
|
+
"description": "Whether the attribute should be encrypted"
|
687
|
+
},
|
688
|
+
"format": {
|
689
|
+
"type": "string",
|
690
|
+
"description": "Format for string attributes"
|
691
|
+
},
|
676
692
|
"min": {
|
677
693
|
"type": "number",
|
678
694
|
"description": "Minimum value for numeric attributes"
|
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.6.
|
4
|
+
"version": "1.6.8",
|
5
5
|
"main": "src/main.ts",
|
6
6
|
"type": "module",
|
7
7
|
"repository": {
|
@@ -935,6 +935,17 @@ const attributesSame = (
|
|
935
935
|
});
|
936
936
|
}
|
937
937
|
|
938
|
+
// Log differences if comparison failed (for debugging)
|
939
|
+
if (!result && differences.length > 0) {
|
940
|
+
MessageFormatter.debug(
|
941
|
+
`Attribute '${configAttribute.key}' differences detected:`,
|
942
|
+
{ prefix: "Attributes" }
|
943
|
+
);
|
944
|
+
differences.forEach(diff => {
|
945
|
+
MessageFormatter.debug(` ${diff}`, { prefix: "Attributes" });
|
946
|
+
});
|
947
|
+
}
|
948
|
+
|
938
949
|
return result;
|
939
950
|
};
|
940
951
|
|
@@ -339,11 +339,11 @@ export const createOrUpdateCollections = async (
|
|
339
339
|
// Add delay after creating attributes
|
340
340
|
await delay(250);
|
341
341
|
|
342
|
-
//
|
342
|
+
// Prefer local config indexes, but fall back to collection's own indexes if no local config exists
|
343
343
|
const localCollectionConfig = config.collections?.find(
|
344
344
|
c => c.name === collectionData.name || c.$id === collectionData.$id
|
345
345
|
);
|
346
|
-
const indexesToUse = localCollectionConfig?.indexes
|
346
|
+
const indexesToUse = localCollectionConfig?.indexes ?? indexes ?? [];
|
347
347
|
|
348
348
|
MessageFormatter.progress("Creating Indexes", { prefix: "Collections" });
|
349
349
|
await createOrUpdateIndexesWithStatusCheck(
|
@@ -575,11 +575,11 @@ export const createOrUpdateCollectionsViaAdapter = async (
|
|
575
575
|
}
|
576
576
|
}
|
577
577
|
|
578
|
-
//
|
578
|
+
// Prefer local config indexes, but fall back to collection's own indexes if no local config exists (TablesDB path)
|
579
579
|
const localTableConfig = config.collections?.find(
|
580
580
|
c => c.name === collectionData.name || c.$id === collectionData.$id
|
581
581
|
);
|
582
|
-
const idxs = (localTableConfig?.indexes
|
582
|
+
const idxs = (localTableConfig?.indexes ?? indexes ?? []) as any[];
|
583
583
|
for (const idx of idxs) {
|
584
584
|
try {
|
585
585
|
await adapter.createIndex({
|
@@ -153,6 +153,64 @@ export class ConfigLoaderService {
|
|
153
153
|
}
|
154
154
|
}
|
155
155
|
|
156
|
+
// Load collections and tables from their respective directories
|
157
|
+
const configDir = path.dirname(yamlPath);
|
158
|
+
const collectionsDir = path.join(configDir, config.schemaConfig?.collectionsDirectory || "collections");
|
159
|
+
const tablesDir = path.join(configDir, config.schemaConfig?.tablesDirectory || "tables");
|
160
|
+
|
161
|
+
// Detect API mode to determine priority order
|
162
|
+
let apiMode: 'legacy' | 'tablesdb' = 'legacy';
|
163
|
+
try {
|
164
|
+
const { detectAppwriteVersionCached } = await import('../../utils/versionDetection.js');
|
165
|
+
const detection = await detectAppwriteVersionCached(
|
166
|
+
config.appwriteEndpoint,
|
167
|
+
config.appwriteProject,
|
168
|
+
config.appwriteKey
|
169
|
+
);
|
170
|
+
apiMode = detection.apiMode;
|
171
|
+
} catch {
|
172
|
+
// Fallback to legacy if detection fails
|
173
|
+
}
|
174
|
+
|
175
|
+
// Load with correct priority based on API mode
|
176
|
+
const { items, conflicts, fromCollections, fromTables } = apiMode === 'tablesdb'
|
177
|
+
? await this.loadTablesFirst(tablesDir, collectionsDir)
|
178
|
+
: await this.loadCollectionsAndTables(collectionsDir, tablesDir);
|
179
|
+
|
180
|
+
config.collections = items;
|
181
|
+
|
182
|
+
// Report what was loaded
|
183
|
+
if (fromTables > 0 && fromCollections > 0) {
|
184
|
+
MessageFormatter.success(
|
185
|
+
`Loaded ${items.length} total items: ${fromCollections} from collections/, ${fromTables} from tables/`,
|
186
|
+
{ prefix: "Config" }
|
187
|
+
);
|
188
|
+
} else if (fromCollections > 0) {
|
189
|
+
MessageFormatter.success(
|
190
|
+
`Loaded ${fromCollections} collections from collections/`,
|
191
|
+
{ prefix: "Config" }
|
192
|
+
);
|
193
|
+
} else if (fromTables > 0) {
|
194
|
+
MessageFormatter.success(
|
195
|
+
`Loaded ${fromTables} tables from tables/`,
|
196
|
+
{ prefix: "Config" }
|
197
|
+
);
|
198
|
+
}
|
199
|
+
|
200
|
+
// Report conflicts
|
201
|
+
if (conflicts.length > 0) {
|
202
|
+
MessageFormatter.warning(
|
203
|
+
`Found ${conflicts.length} naming conflicts`,
|
204
|
+
{ prefix: "Config" }
|
205
|
+
);
|
206
|
+
conflicts.forEach(conflict => {
|
207
|
+
MessageFormatter.info(
|
208
|
+
` - '${conflict.name}': ${conflict.source1} (used) vs ${conflict.source2} (skipped)`,
|
209
|
+
{ prefix: "Config" }
|
210
|
+
);
|
211
|
+
});
|
212
|
+
}
|
213
|
+
|
156
214
|
MessageFormatter.success(`Loaded YAML config from: ${yamlPath}`, {
|
157
215
|
prefix: "Config",
|
158
216
|
});
|
@@ -523,6 +581,67 @@ export class ConfigLoaderService {
|
|
523
581
|
};
|
524
582
|
}
|
525
583
|
|
584
|
+
/**
|
585
|
+
* Loads tables first (higher priority), then collections (backward compatibility)
|
586
|
+
* Used for TablesDB projects (>= 1.8.0)
|
587
|
+
* @param tablesDir Path to the tables directory
|
588
|
+
* @param collectionsDir Path to the collections directory
|
589
|
+
* @returns Loading result with items, counts, and conflicts
|
590
|
+
*/
|
591
|
+
public async loadTablesFirst(
|
592
|
+
tablesDir: string,
|
593
|
+
collectionsDir: string
|
594
|
+
): Promise<{
|
595
|
+
items: Collection[];
|
596
|
+
fromCollections: number;
|
597
|
+
fromTables: number;
|
598
|
+
conflicts: Array<{ name: string; source1: string; source2: string }>;
|
599
|
+
}> {
|
600
|
+
const items: Collection[] = [];
|
601
|
+
const loadedNames = new Set<string>();
|
602
|
+
const conflicts: Array<{ name: string; source1: string; source2: string }> = [];
|
603
|
+
|
604
|
+
// Load from tables/ directory first (HIGHER priority for TablesDB)
|
605
|
+
if (fs.existsSync(tablesDir)) {
|
606
|
+
const tables = await this.loadTables(tablesDir, { markAsTablesDir: true });
|
607
|
+
for (const table of tables) {
|
608
|
+
const name = table.name || table.tableId || table.$id || "";
|
609
|
+
loadedNames.add(name);
|
610
|
+
items.push(table);
|
611
|
+
}
|
612
|
+
}
|
613
|
+
|
614
|
+
// Load from collections/ directory second (LOWER priority, backward compatibility)
|
615
|
+
if (fs.existsSync(collectionsDir)) {
|
616
|
+
const collections = await this.loadCollections(collectionsDir);
|
617
|
+
for (const collection of collections) {
|
618
|
+
const name = collection.name || collection.$id || "";
|
619
|
+
|
620
|
+
// Check for conflicts - tables win
|
621
|
+
if (loadedNames.has(name)) {
|
622
|
+
conflicts.push({
|
623
|
+
name,
|
624
|
+
source1: "tables/",
|
625
|
+
source2: "collections/",
|
626
|
+
});
|
627
|
+
} else {
|
628
|
+
loadedNames.add(name);
|
629
|
+
items.push(collection);
|
630
|
+
}
|
631
|
+
}
|
632
|
+
}
|
633
|
+
|
634
|
+
const fromTables = items.filter((item: any) => item._isFromTablesDir).length;
|
635
|
+
const fromCollections = items.filter((item: any) => !item._isFromTablesDir).length;
|
636
|
+
|
637
|
+
return {
|
638
|
+
items,
|
639
|
+
fromCollections,
|
640
|
+
fromTables,
|
641
|
+
conflicts,
|
642
|
+
};
|
643
|
+
}
|
644
|
+
|
526
645
|
/**
|
527
646
|
* Validates that a configuration file can be loaded
|
528
647
|
* @param configPath Path to the configuration file
|
@@ -464,6 +464,14 @@ export function generateCollectionSchema(): any {
|
|
464
464
|
"side": {
|
465
465
|
"type": "string",
|
466
466
|
"enum": ["parent", "child"]
|
467
|
+
},
|
468
|
+
"encrypt": {
|
469
|
+
"type": "boolean",
|
470
|
+
"description": "Whether the attribute should be encrypted"
|
471
|
+
},
|
472
|
+
"format": {
|
473
|
+
"type": "string",
|
474
|
+
"description": "Format for string attributes (e.g., email, url, ip)"
|
467
475
|
}
|
468
476
|
},
|
469
477
|
"required": ["key", "type"],
|
@@ -139,7 +139,9 @@ const YamlCollectionSchema = z.object({
|
|
139
139
|
twoWay: z.boolean().optional(),
|
140
140
|
twoWayKey: z.string().optional(),
|
141
141
|
onDelete: z.string().optional(),
|
142
|
-
side: z.string().optional()
|
142
|
+
side: z.string().optional(),
|
143
|
+
encrypt: z.boolean().optional(),
|
144
|
+
format: z.string().optional()
|
143
145
|
})
|
144
146
|
).optional().default([]),
|
145
147
|
indexes: z.array(
|
@@ -191,7 +193,9 @@ export const loadYamlCollection = (filePath: string): CollectionCreate | null =>
|
|
191
193
|
twoWay: attr.twoWay,
|
192
194
|
twoWayKey: attr.twoWayKey,
|
193
195
|
onDelete: attr.onDelete as any,
|
194
|
-
side: attr.side as any
|
196
|
+
side: attr.side as any,
|
197
|
+
encrypted: (attr as any).encrypt,
|
198
|
+
format: (attr as any).format
|
195
199
|
})),
|
196
200
|
indexes: parsedCollection.indexes.map(idx => ({
|
197
201
|
key: idx.key,
|
@@ -247,7 +251,9 @@ export const loadYamlTable = (filePath: string): any | null => {
|
|
247
251
|
twoWay: attr.twoWay,
|
248
252
|
twoWayKey: attr.twoWayKey,
|
249
253
|
onDelete: attr.onDelete as any,
|
250
|
-
side: attr.side as any
|
254
|
+
side: attr.side as any,
|
255
|
+
encrypted: (attr as any).encrypt,
|
256
|
+
format: (attr as any).format
|
251
257
|
})),
|
252
258
|
indexes: parsedTable.indexes.map(idx => ({
|
253
259
|
key: idx.key,
|
package/src/utils/setupFiles.ts
CHANGED
@@ -516,6 +516,14 @@ importDefs: []
|
|
516
516
|
"type": "string",
|
517
517
|
"description": "Column description"
|
518
518
|
},
|
519
|
+
"encrypt": {
|
520
|
+
"type": "boolean",
|
521
|
+
"description": "Whether the column should be encrypted"
|
522
|
+
},
|
523
|
+
"format": {
|
524
|
+
"type": "string",
|
525
|
+
"description": "Format for string columns"
|
526
|
+
},
|
519
527
|
"min": {
|
520
528
|
"type": "number",
|
521
529
|
"description": "Minimum value for numeric columns"
|
@@ -710,6 +718,14 @@ importDefs: []
|
|
710
718
|
"type": "string",
|
711
719
|
"description": "Attribute description"
|
712
720
|
},
|
721
|
+
"encrypt": {
|
722
|
+
"type": "boolean",
|
723
|
+
"description": "Whether the attribute should be encrypted"
|
724
|
+
},
|
725
|
+
"format": {
|
726
|
+
"type": "string",
|
727
|
+
"description": "Format for string attributes"
|
728
|
+
},
|
713
729
|
"min": {
|
714
730
|
"type": "number",
|
715
731
|
"description": "Minimum value for numeric attributes"
|