appwrite-utils-cli 1.7.8 → 1.8.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.
Files changed (111) hide show
  1. package/CHANGELOG.md +14 -199
  2. package/README.md +87 -30
  3. package/dist/adapters/AdapterFactory.js +5 -25
  4. package/dist/adapters/DatabaseAdapter.d.ts +17 -2
  5. package/dist/adapters/LegacyAdapter.d.ts +2 -1
  6. package/dist/adapters/LegacyAdapter.js +212 -16
  7. package/dist/adapters/TablesDBAdapter.d.ts +2 -12
  8. package/dist/adapters/TablesDBAdapter.js +261 -57
  9. package/dist/cli/commands/databaseCommands.js +10 -10
  10. package/dist/cli/commands/functionCommands.js +17 -8
  11. package/dist/collections/attributes.js +447 -125
  12. package/dist/collections/methods.js +197 -186
  13. package/dist/collections/tableOperations.d.ts +86 -0
  14. package/dist/collections/tableOperations.js +434 -0
  15. package/dist/collections/transferOperations.d.ts +3 -2
  16. package/dist/collections/transferOperations.js +93 -12
  17. package/dist/config/services/ConfigLoaderService.d.ts +7 -0
  18. package/dist/config/services/ConfigLoaderService.js +47 -1
  19. package/dist/config/yamlConfig.d.ts +221 -88
  20. package/dist/examples/yamlTerminologyExample.d.ts +1 -1
  21. package/dist/examples/yamlTerminologyExample.js +6 -3
  22. package/dist/functions/deployments.js +5 -23
  23. package/dist/functions/fnConfigDiscovery.d.ts +3 -0
  24. package/dist/functions/fnConfigDiscovery.js +108 -0
  25. package/dist/functions/methods.js +4 -2
  26. package/dist/functions/pathResolution.d.ts +37 -0
  27. package/dist/functions/pathResolution.js +185 -0
  28. package/dist/functions/templates/count-docs-in-collection/README.md +54 -0
  29. package/dist/functions/templates/count-docs-in-collection/package.json +25 -0
  30. package/dist/functions/templates/count-docs-in-collection/src/main.ts +159 -0
  31. package/dist/functions/templates/count-docs-in-collection/src/request.ts +9 -0
  32. package/dist/functions/templates/count-docs-in-collection/tsconfig.json +28 -0
  33. package/dist/functions/templates/hono-typescript/README.md +286 -0
  34. package/dist/functions/templates/hono-typescript/package.json +26 -0
  35. package/dist/functions/templates/hono-typescript/src/adapters/request.ts +74 -0
  36. package/dist/functions/templates/hono-typescript/src/adapters/response.ts +106 -0
  37. package/dist/functions/templates/hono-typescript/src/app.ts +180 -0
  38. package/dist/functions/templates/hono-typescript/src/context.ts +103 -0
  39. package/dist/functions/templates/hono-typescript/src/index.ts +54 -0
  40. package/dist/functions/templates/hono-typescript/src/middleware/appwrite.ts +119 -0
  41. package/dist/functions/templates/hono-typescript/tsconfig.json +20 -0
  42. package/dist/functions/templates/typescript-node/README.md +32 -0
  43. package/dist/functions/templates/typescript-node/package.json +25 -0
  44. package/dist/functions/templates/typescript-node/src/context.ts +103 -0
  45. package/dist/functions/templates/typescript-node/src/index.ts +29 -0
  46. package/dist/functions/templates/typescript-node/tsconfig.json +28 -0
  47. package/dist/functions/templates/uv/README.md +31 -0
  48. package/dist/functions/templates/uv/pyproject.toml +30 -0
  49. package/dist/functions/templates/uv/src/__init__.py +0 -0
  50. package/dist/functions/templates/uv/src/context.py +125 -0
  51. package/dist/functions/templates/uv/src/index.py +46 -0
  52. package/dist/interactiveCLI.js +18 -15
  53. package/dist/main.js +219 -81
  54. package/dist/migrations/appwriteToX.d.ts +88 -23
  55. package/dist/migrations/comprehensiveTransfer.d.ts +2 -0
  56. package/dist/migrations/comprehensiveTransfer.js +83 -6
  57. package/dist/migrations/dataLoader.d.ts +227 -69
  58. package/dist/migrations/dataLoader.js +3 -3
  59. package/dist/migrations/importController.js +3 -3
  60. package/dist/migrations/relationships.d.ts +8 -2
  61. package/dist/migrations/services/ImportOrchestrator.js +3 -3
  62. package/dist/migrations/transfer.js +159 -37
  63. package/dist/shared/attributeMapper.d.ts +20 -0
  64. package/dist/shared/attributeMapper.js +203 -0
  65. package/dist/shared/selectionDialogs.d.ts +1 -1
  66. package/dist/shared/selectionDialogs.js +39 -11
  67. package/dist/storage/schemas.d.ts +354 -92
  68. package/dist/utils/configDiscovery.js +4 -3
  69. package/dist/utils/versionDetection.d.ts +0 -4
  70. package/dist/utils/versionDetection.js +41 -173
  71. package/dist/utils/yamlConverter.js +89 -16
  72. package/dist/utils/yamlLoader.d.ts +1 -1
  73. package/dist/utils/yamlLoader.js +6 -2
  74. package/dist/utilsController.d.ts +2 -1
  75. package/dist/utilsController.js +151 -22
  76. package/package.json +7 -5
  77. package/scripts/copy-templates.ts +23 -0
  78. package/src/adapters/AdapterFactory.ts +119 -143
  79. package/src/adapters/DatabaseAdapter.ts +18 -3
  80. package/src/adapters/LegacyAdapter.ts +236 -105
  81. package/src/adapters/TablesDBAdapter.ts +773 -643
  82. package/src/cli/commands/databaseCommands.ts +19 -19
  83. package/src/cli/commands/functionCommands.ts +23 -14
  84. package/src/collections/attributes.ts +2054 -1611
  85. package/src/collections/methods.ts +208 -293
  86. package/src/collections/tableOperations.ts +506 -0
  87. package/src/collections/transferOperations.ts +218 -144
  88. package/src/config/services/ConfigLoaderService.ts +62 -1
  89. package/src/examples/yamlTerminologyExample.ts +10 -5
  90. package/src/functions/deployments.ts +10 -35
  91. package/src/functions/fnConfigDiscovery.ts +103 -0
  92. package/src/functions/methods.ts +4 -2
  93. package/src/functions/pathResolution.ts +227 -0
  94. package/src/interactiveCLI.ts +25 -20
  95. package/src/main.ts +557 -202
  96. package/src/migrations/comprehensiveTransfer.ts +126 -50
  97. package/src/migrations/dataLoader.ts +3 -3
  98. package/src/migrations/importController.ts +3 -3
  99. package/src/migrations/services/ImportOrchestrator.ts +3 -3
  100. package/src/migrations/transfer.ts +148 -131
  101. package/src/shared/attributeMapper.ts +229 -0
  102. package/src/shared/selectionDialogs.ts +65 -32
  103. package/src/utils/configDiscovery.ts +9 -3
  104. package/src/utils/versionDetection.ts +74 -228
  105. package/src/utils/yamlConverter.ts +94 -17
  106. package/src/utils/yamlLoader.ts +11 -4
  107. package/src/utilsController.ts +202 -36
  108. package/dist/utils/schemaStrings.d.ts +0 -14
  109. package/dist/utils/schemaStrings.js +0 -428
  110. package/dist/utils/sessionPreservationExample.d.ts +0 -1666
  111. package/dist/utils/sessionPreservationExample.js +0 -101
@@ -10,8 +10,9 @@
10
10
  * 3. Fallback: Default to legacy mode for safety
11
11
  */
12
12
 
13
- import { logger } from '../shared/logging.js';
14
- import { MessageFormatter } from '../shared/messageFormatter.js';
13
+ import { logger } from '../shared/logging.js';
14
+ import { MessageFormatter } from '../shared/messageFormatter.js';
15
+ import { Client, Databases, TablesDB, Query } from 'node-appwrite';
15
16
 
16
17
  export type ApiMode = 'legacy' | 'tablesdb';
17
18
 
@@ -30,11 +31,11 @@ export interface VersionDetectionResult {
30
31
  * @param apiKey - API key for authentication
31
32
  * @returns Promise resolving to version detection result
32
33
  */
33
- export async function detectAppwriteVersion(
34
- endpoint: string,
35
- project: string,
36
- apiKey: string
37
- ): Promise<VersionDetectionResult> {
34
+ export async function detectAppwriteVersion(
35
+ endpoint: string,
36
+ project: string,
37
+ apiKey: string
38
+ ): Promise<VersionDetectionResult> {
38
39
  const startTime = Date.now();
39
40
  // Clean endpoint URL
40
41
  const cleanEndpoint = endpoint.replace(/\/$/, '');
@@ -62,199 +63,72 @@ export async function detectAppwriteVersion(
62
63
  };
63
64
  }
64
65
 
65
- // STEP 2: Only proceed with endpoint probe if version >= 1.8.0 or version unknown
66
- // Try primary detection method: TablesDB endpoint probe
67
- try {
68
- logger.debug('Attempting TablesDB endpoint probe', {
69
- endpoint: cleanEndpoint,
70
- serverVersion: serverVersion || 'unknown',
71
- operation: 'detectAppwriteVersion'
72
- });
73
-
74
- const probeStartTime = Date.now();
75
- const tablesDbResult = await probeTablesDbEndpoint(cleanEndpoint, project, apiKey);
76
- const probeDuration = Date.now() - probeStartTime;
77
-
78
- if (tablesDbResult.apiMode === 'tablesdb') {
79
- logger.info('TablesDB detected via endpoint probe', {
80
- endpoint: cleanEndpoint,
81
- detectionMethod: tablesDbResult.detectionMethod,
82
- confidence: tablesDbResult.confidence,
83
- probeDuration,
84
- totalDuration: Date.now() - startTime,
85
- operation: 'detectAppwriteVersion'
86
- });
87
- return tablesDbResult;
88
- }
89
- } catch (error) {
90
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
91
- MessageFormatter.warning(`TablesDB endpoint probe failed: ${errorMessage}`, { prefix: "Version Detection" });
92
- logger.warn('TablesDB endpoint probe failed', {
93
- endpoint: cleanEndpoint,
94
- error: errorMessage,
95
- operation: 'detectAppwriteVersion'
96
- });
97
- }
98
-
99
- // Try secondary detection method: SDK feature detection
100
- try {
101
- logger.debug('Attempting SDK capability probe', {
102
- endpoint: cleanEndpoint,
103
- operation: 'detectAppwriteVersion'
104
- });
105
-
106
- const sdkProbeStartTime = Date.now();
107
- const sdkResult = await probeSdkCapabilities();
108
- const sdkProbeDuration = Date.now() - sdkProbeStartTime;
109
-
110
- if (sdkResult.apiMode === 'tablesdb') {
111
- logger.info('TablesDB detected via SDK capability probe', {
112
- endpoint: cleanEndpoint,
113
- detectionMethod: sdkResult.detectionMethod,
114
- confidence: sdkResult.confidence,
115
- sdkProbeDuration,
116
- totalDuration: Date.now() - startTime,
117
- operation: 'detectAppwriteVersion'
118
- });
119
- return sdkResult;
120
- }
121
- } catch (error) {
122
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
123
- MessageFormatter.warning(`SDK capability probe failed: ${errorMessage}`, { prefix: "Version Detection" });
124
- logger.warn('SDK capability probe failed', {
125
- endpoint: cleanEndpoint,
126
- error: errorMessage,
127
- operation: 'detectAppwriteVersion'
128
- });
129
- }
130
-
131
- // Fallback to legacy mode
132
- const fallbackResult = {
133
- apiMode: 'legacy' as ApiMode,
134
- detectionMethod: 'fallback' as const,
135
- confidence: 'low' as const
136
- };
66
+ // STEP 2: If version is unknown, use SDK probe (no fake HTTP endpoints)
67
+ try {
68
+ logger.debug('Attempting SDK-based TablesDB probe', {
69
+ endpoint: cleanEndpoint,
70
+ operation: 'detectAppwriteVersion'
71
+ });
72
+
73
+ const client = new Client().setEndpoint(cleanEndpoint).setProject(project);
74
+ if (apiKey && apiKey.trim().length > 0) client.setKey(apiKey);
75
+
76
+ const databases = new Databases(client);
77
+ // Try to get a database id to probe tables listing
78
+ let dbId: string | undefined;
79
+ try {
80
+ const dbList: any = await databases.list([Query.limit(1)]);
81
+ dbId = dbList?.databases?.[0]?.$id || dbList?.databases?.[0]?.id || dbList?.[0]?.$id;
82
+ } catch (e) {
83
+ // Ignore, we'll still attempt a conservative probe
84
+ logger.debug('Databases.list probe failed or returned no items', { operation: 'detectAppwriteVersion' });
85
+ }
86
+
87
+ const tables = new TablesDB(client);
88
+ if (dbId) {
89
+ // Probe listTables for the first database (limit 1)
90
+ await tables.listTables({ databaseId: dbId, queries: [Query.limit(1)] });
91
+ } else {
92
+ // No databases to probe; assume TablesDB available (cannot falsify-positively without a db)
93
+ logger.debug('No databases found to probe tables; assuming TablesDB if SDK available', { operation: 'detectAppwriteVersion' });
94
+ }
95
+
96
+ const result: VersionDetectionResult = {
97
+ apiMode: 'tablesdb',
98
+ detectionMethod: 'endpoint_probe', // repurpose label for SDK probe
99
+ confidence: 'medium',
100
+ serverVersion: serverVersion || undefined
101
+ };
102
+ logger.info('TablesDB detected via SDK probe', {
103
+ endpoint: cleanEndpoint,
104
+ result,
105
+ operation: 'detectAppwriteVersion'
106
+ });
107
+ return result;
108
+ } catch (error) {
109
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
110
+ logger.warn('SDK TablesDB probe failed; defaulting conservatively', {
111
+ endpoint: cleanEndpoint,
112
+ error: errorMessage,
113
+ operation: 'detectAppwriteVersion'
114
+ });
115
+ }
116
+
117
+ // Final fallback: default to tablesdb for modern environments when version unknown
118
+ const fallbackResult: VersionDetectionResult = {
119
+ apiMode: 'tablesdb',
120
+ detectionMethod: 'fallback',
121
+ confidence: 'low',
122
+ serverVersion: serverVersion || undefined
123
+ };
124
+ logger.info('Defaulting to TablesDB mode (fallback)', {
125
+ endpoint: cleanEndpoint,
126
+ result: fallbackResult,
127
+ operation: 'detectAppwriteVersion'
128
+ });
129
+ return fallbackResult;
130
+ }
137
131
 
138
- logger.info('Falling back to legacy mode', {
139
- endpoint: cleanEndpoint,
140
- totalDuration: Date.now() - startTime,
141
- result: fallbackResult,
142
- operation: 'detectAppwriteVersion'
143
- });
144
-
145
- return fallbackResult;
146
- }
147
-
148
- /**
149
- * Test TablesDB endpoint availability - most reliable detection method
150
- */
151
- async function probeTablesDbEndpoint(
152
- endpoint: string,
153
- project: string,
154
- apiKey: string
155
- ): Promise<VersionDetectionResult> {
156
- const startTime = Date.now();
157
- const url = `${endpoint}/tablesdb/`;
158
-
159
- logger.debug('Probing TablesDB endpoint', {
160
- url,
161
- project,
162
- operation: 'probeTablesDbEndpoint'
163
- });
164
-
165
- const response = await fetch(url, {
166
- method: 'GET',
167
- headers: {
168
- 'Content-Type': 'application/json',
169
- 'X-Appwrite-Project': project,
170
- 'X-Appwrite-Key': apiKey
171
- },
172
- // Short timeout for faster detection
173
- signal: AbortSignal.timeout(5000)
174
- });
175
-
176
- const duration = Date.now() - startTime;
177
-
178
- logger.debug('TablesDB endpoint response received', {
179
- url,
180
- status: response.status,
181
- statusText: response.statusText,
182
- duration,
183
- operation: 'probeTablesDbEndpoint'
184
- });
185
-
186
- if (response.ok) {
187
- // ONLY 200 OK means TablesDB available
188
- // 404 means endpoint doesn't exist (server < 1.8.0)
189
- const result = {
190
- apiMode: 'tablesdb' as ApiMode,
191
- detectionMethod: 'endpoint_probe' as const,
192
- confidence: 'high' as const
193
- };
194
-
195
- logger.info('TablesDB endpoint probe successful', {
196
- url,
197
- status: response.status,
198
- result,
199
- duration,
200
- operation: 'probeTablesDbEndpoint'
201
- });
202
-
203
- return result;
204
- }
205
-
206
- // 501 Not Implemented or other errors = no TablesDB support
207
- const error = new Error(`TablesDB endpoint returned ${response.status}: ${response.statusText}`);
208
- logger.debug('TablesDB endpoint probe failed', {
209
- url,
210
- status: response.status,
211
- statusText: response.statusText,
212
- duration,
213
- operation: 'probeTablesDbEndpoint'
214
- });
215
- throw error;
216
- }
217
-
218
- /**
219
- * SDK capability detection as secondary method
220
- */
221
- async function probeSdkCapabilities(): Promise<VersionDetectionResult> {
222
- try {
223
- // Try to import TablesDB SDK
224
- let TablesDBModule;
225
- try {
226
- TablesDBModule = await import('node-appwrite-tablesdb');
227
- } catch (importError) {
228
- // TablesDB SDK not available, will fall back to legacy
229
- }
230
-
231
- if (TablesDBModule?.TablesDB) {
232
- return {
233
- apiMode: 'tablesdb',
234
- detectionMethod: 'endpoint_probe',
235
- confidence: 'medium'
236
- };
237
- }
238
- } catch (error) {
239
- // TablesDB SDK not available, assume legacy
240
- }
241
-
242
- // Check for legacy SDK availability
243
- try {
244
- const { Databases } = await import('node-appwrite');
245
- if (Databases) {
246
- return {
247
- apiMode: 'legacy',
248
- detectionMethod: 'endpoint_probe',
249
- confidence: 'medium'
250
- };
251
- }
252
- } catch (error) {
253
- throw new Error('No Appwrite SDK available');
254
- }
255
-
256
- throw new Error('Unable to determine SDK capabilities');
257
- }
258
132
 
259
133
  /**
260
134
  * Cached version detection to avoid repeated API calls
@@ -381,35 +255,7 @@ export function isCloudAppwriteEndpoint(endpoint: string): boolean {
381
255
  * SDK feature detection as a fallback method
382
256
  * Attempts to dynamically import TablesDB to check availability
383
257
  */
384
- export async function detectSdkSupport(): Promise<{
385
- tablesDbAvailable: boolean;
386
- legacyAvailable: boolean;
387
- }> {
388
- const result = {
389
- tablesDbAvailable: false,
390
- legacyAvailable: false
391
- };
392
-
393
- // Test TablesDB SDK availability
394
- try {
395
- const tablesModule = await import('node-appwrite-tablesdb');
396
- if (tablesModule) {
397
- result.tablesDbAvailable = true;
398
- }
399
- } catch (error) {
400
- // TablesDB SDK not available
401
- }
402
-
403
- // Test legacy SDK availability
404
- try {
405
- await import('node-appwrite');
406
- result.legacyAvailable = true;
407
- } catch (error) {
408
- // Legacy SDK not available
409
- }
410
-
411
- return result;
412
- }
258
+ // Removed dynamic SDK capability checks to avoid confusion and side effects.
413
259
 
414
260
  /**
415
261
  * Clear version detection cache (useful for testing)
@@ -1,8 +1,95 @@
1
1
  import yaml from "js-yaml";
2
2
  import type { Collection, CollectionCreate } from "appwrite-utils";
3
+ import { Decimal } from "decimal.js";
3
4
 
4
- // Threshold for treating min/max values as undefined (1 trillion)
5
- const MIN_MAX_THRESHOLD = 1_000_000_000_000;
5
+ // Extreme values that Appwrite may return, which should be treated as undefined
6
+ const EXTREME_MIN_INTEGER = -9223372036854776000;
7
+ const EXTREME_MAX_INTEGER = 9223372036854776000;
8
+ const EXTREME_MIN_FLOAT = -1.7976931348623157e+308;
9
+ const EXTREME_MAX_FLOAT = 1.7976931348623157e+308;
10
+
11
+ /**
12
+ * Type guard to check if an attribute has min/max properties
13
+ */
14
+ const hasMinMaxProperties = (yamlAttr: any): boolean => {
15
+ return yamlAttr.type === 'integer' || yamlAttr.type === 'double' || yamlAttr.type === 'float';
16
+ };
17
+
18
+ /**
19
+ * Normalizes min/max values for integer and float attributes using Decimal.js for precision
20
+ * Validates that min < max and handles extreme database values
21
+ */
22
+ const normalizeMinMaxValues = (yamlAttr: any): { min?: number; max?: number } => {
23
+ if (!hasMinMaxProperties(yamlAttr)) {
24
+ return {};
25
+ }
26
+
27
+ const { type, min, max, key } = yamlAttr;
28
+ let normalizedMin = min;
29
+ let normalizedMax = max;
30
+
31
+ // Handle min value - only filter out extreme database values
32
+ if (normalizedMin !== undefined && normalizedMin !== null) {
33
+ const minValue = Number(normalizedMin);
34
+ const originalMin = normalizedMin;
35
+
36
+ // Check if it's an extreme database value (but don't filter out large numbers)
37
+ if (type === 'integer') {
38
+ if (minValue === EXTREME_MIN_INTEGER) {
39
+ console.debug(`Min value normalized to undefined for attribute '${yamlAttr.key}': extreme database value`);
40
+ normalizedMin = undefined;
41
+ }
42
+ } else { // float/double
43
+ if (minValue === EXTREME_MIN_FLOAT) {
44
+ console.debug(`Min value normalized to undefined for attribute '${yamlAttr.key}': extreme database value`);
45
+ normalizedMin = undefined;
46
+ }
47
+ }
48
+ }
49
+
50
+ // Handle max value - only filter out extreme database values
51
+ if (normalizedMax !== undefined && normalizedMax !== null) {
52
+ const maxValue = Number(normalizedMax);
53
+ const originalMax = normalizedMax;
54
+
55
+ // Check if it's an extreme database value (but don't filter out large numbers)
56
+ if (type === 'integer') {
57
+ if (maxValue === EXTREME_MAX_INTEGER) {
58
+ console.debug(`Max value normalized to undefined for attribute '${yamlAttr.key}': extreme database value`);
59
+ normalizedMax = undefined;
60
+ }
61
+ } else { // float/double
62
+ if (maxValue === EXTREME_MAX_FLOAT) {
63
+ console.debug(`Max value normalized to undefined for attribute '${yamlAttr.key}': extreme database value`);
64
+ normalizedMax = undefined;
65
+ }
66
+ }
67
+ }
68
+
69
+ // Validate that min < max using Decimal.js for safe comparison
70
+ if (normalizedMin !== undefined && normalizedMax !== undefined &&
71
+ normalizedMin !== null && normalizedMax !== null) {
72
+ try {
73
+ const minDecimal = new Decimal(normalizedMin.toString());
74
+ const maxDecimal = new Decimal(normalizedMax.toString());
75
+
76
+ if (minDecimal.greaterThanOrEqualTo(maxDecimal)) {
77
+ // Swap values to ensure min < max (graceful handling)
78
+ console.warn(`Swapping min/max values for attribute '${yamlAttr.key}' to fix validation: min (${normalizedMin}) must be less than max (${normalizedMax})`);
79
+ const temp = normalizedMin;
80
+ normalizedMin = normalizedMax;
81
+ normalizedMax = temp;
82
+ }
83
+ } catch (error) {
84
+ console.error(`Error comparing min/max values for attribute '${yamlAttr.key}':`, error);
85
+ // If Decimal comparison fails, set both to undefined to avoid API errors
86
+ normalizedMin = undefined;
87
+ normalizedMax = undefined;
88
+ }
89
+ }
90
+
91
+ return { min: normalizedMin, max: normalizedMax };
92
+ };
6
93
 
7
94
  export interface YamlCollectionData {
8
95
  name: string;
@@ -125,21 +212,11 @@ export function collectionToYaml(
125
212
 
126
213
  if ('xdefault' in attr && attr.xdefault !== undefined) yamlAttr.default = attr.xdefault;
127
214
 
128
- // Normalize min/max values - filter out extreme database values
129
- if ('min' in attr && attr.min !== undefined) {
130
- const minValue = Number(attr.min);
131
- // Only include min if it's within reasonable range (< 1 trillion)
132
- if (Math.abs(minValue) < MIN_MAX_THRESHOLD) {
133
- yamlAttr.min = attr.min;
134
- }
135
- }
136
-
137
- if ('max' in attr && attr.max !== undefined) {
138
- const maxValue = Number(attr.max);
139
- // Only include max if it's within reasonable range (< 1 trillion)
140
- if (Math.abs(maxValue) < MIN_MAX_THRESHOLD) {
141
- yamlAttr.max = attr.max;
142
- }
215
+ // Normalize min/max values using Decimal.js precision
216
+ if ('min' in attr || 'max' in attr) {
217
+ const { min, max } = normalizeMinMaxValues(attr);
218
+ if (min !== undefined) yamlAttr.min = min;
219
+ if (max !== undefined) yamlAttr.max = max;
143
220
  }
144
221
  if ('elements' in attr && attr.elements !== undefined) yamlAttr.elements = attr.elements;
145
222
  if ('relatedCollection' in attr && attr.relatedCollection !== undefined) yamlAttr.relatedCollection = attr.relatedCollection;
@@ -9,7 +9,10 @@ import {
9
9
  type YamlCollectionData,
10
10
  type YamlTerminologyConfig
11
11
  } from "./yamlConverter.js";
12
- import type { CollectionCreate } from "appwrite-utils";
12
+ import {
13
+ CollectionCreateSchema,
14
+ type CollectionCreate,
15
+ } from "appwrite-utils";
13
16
 
14
17
  /**
15
18
  * Enhanced YAML loader with dual terminology support
@@ -149,7 +152,7 @@ export class YamlLoader {
149
152
  // Always normalize to ensure consistent attribute terminology
150
153
  const normalized = normalizeYamlData(yamlData);
151
154
 
152
- return {
155
+ const collectionInput: CollectionCreate = {
153
156
  name: normalized.name,
154
157
  $id: normalized.id || normalized.name.toLowerCase().replace(/\s+/g, '_'),
155
158
  enabled: normalized.enabled !== false,
@@ -173,7 +176,9 @@ export class YamlLoader {
173
176
  twoWay: attr.twoWay,
174
177
  twoWayKey: attr.twoWayKey,
175
178
  onDelete: attr.onDelete as any,
176
- side: attr.side as any
179
+ side: attr.side as any,
180
+ encrypt: (attr as any).encrypt,
181
+ format: (attr as any).format
177
182
  })) || [],
178
183
  indexes: normalized.indexes?.map(idx => ({
179
184
  key: idx.key,
@@ -183,6 +188,8 @@ export class YamlLoader {
183
188
  })) || [],
184
189
  importDefs: normalized.importDefs || []
185
190
  };
191
+
192
+ return CollectionCreateSchema.parse(collectionInput);
186
193
  }
187
194
 
188
195
  /**
@@ -361,4 +368,4 @@ export class YamlLoader {
361
368
  */
362
369
  export function createYamlLoader(baseDirectory: string): YamlLoader {
363
370
  return new YamlLoader(baseDirectory);
364
- }
371
+ }