Skip to content

Commit 4600be9

Browse files
Copilothuangyiirene
andcommitted
Add migration examples in TypeScript and YAML formats
Co-authored-by: huangyiirene <7665279+huangyiirene@users.noreply.github.com>
1 parent 9f228a8 commit 4600be9

4 files changed

Lines changed: 698 additions & 0 deletions
Lines changed: 366 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,366 @@
1+
/**
2+
* Example: Schema Migration with ObjectQL
3+
*
4+
* This example demonstrates how to define schema evolution instructions
5+
* for objects and fields using the ObjectQL migration types.
6+
*
7+
* These migration instructions express declarative schema changes that
8+
* can be interpreted by migration tools or AI agents to safely evolve
9+
* your data model over time.
10+
*/
11+
12+
import {
13+
MigrationConfig,
14+
FieldUpdateInstruction,
15+
FieldDeleteInstruction,
16+
ObjectUpdateInstruction,
17+
ObjectDeleteInstruction,
18+
SchemaChangeInstruction
19+
} from '../packages/foundation/types/src/index';
20+
21+
// ========================================
22+
// Example 1: Field Rename Migration
23+
// ========================================
24+
25+
const renameFieldMigration: MigrationConfig = {
26+
id: 'v1.1_rename_username',
27+
version: '1.1.0',
28+
name: 'Rename Username Field',
29+
description: 'Rename username to user_name for consistency across objects',
30+
author: 'dev-team',
31+
created_at: '2026-01-14T00:00:00Z',
32+
steps: [
33+
{
34+
id: 'step_1',
35+
name: 'Rename username field in users object',
36+
description: 'Update field name from username to user_name',
37+
instruction: {
38+
type: 'field_update',
39+
object_name: 'users',
40+
field_name: 'username',
41+
new_field_name: 'user_name',
42+
changes: {
43+
label: 'User Name'
44+
},
45+
data_migration_strategy: 'auto',
46+
description: 'Rename for naming consistency',
47+
reason: 'Align with naming conventions across all objects'
48+
} as FieldUpdateInstruction,
49+
reversible: true
50+
}
51+
],
52+
reversible: true,
53+
tags: ['refactor', 'naming']
54+
};
55+
56+
// ========================================
57+
// Example 2: Field Type Change Migration
58+
// ========================================
59+
60+
const changeFieldTypeMigration: MigrationConfig = {
61+
id: 'v1.2_convert_price_to_currency',
62+
version: '1.2.0',
63+
name: 'Convert Price to Currency Type',
64+
description: 'Change price field from number to currency type for better formatting',
65+
author: 'product-team',
66+
created_at: '2026-01-15T00:00:00Z',
67+
steps: [
68+
{
69+
id: 'step_1',
70+
name: 'Convert product price field',
71+
instruction: {
72+
type: 'field_update',
73+
object_name: 'products',
74+
field_name: 'price',
75+
changes: {
76+
type: 'currency',
77+
label: 'Price (USD)',
78+
defaultValue: 0
79+
},
80+
data_migration_strategy: 'manual',
81+
transform_script: `
82+
// Custom transformation for existing records
83+
function transform(oldValue) {
84+
if (typeof oldValue === 'number') {
85+
return oldValue;
86+
}
87+
return 0;
88+
}
89+
`,
90+
description: 'Convert from number to currency type',
91+
reason: 'Support proper currency formatting and calculations'
92+
} as FieldUpdateInstruction,
93+
reversible: false, // Type changes are typically not auto-reversible
94+
depends_on: []
95+
}
96+
],
97+
reversible: false,
98+
tags: ['schema', 'type-change']
99+
};
100+
101+
// ========================================
102+
// Example 3: Remove Deprecated Fields
103+
// ========================================
104+
105+
const removeDeprecatedFieldsMigration: MigrationConfig = {
106+
id: 'v2.0_cleanup_legacy_fields',
107+
version: '2.0.0',
108+
name: 'Remove Legacy Fields',
109+
description: 'Clean up deprecated fields that are no longer used',
110+
author: 'dev-team',
111+
created_at: '2026-02-01T00:00:00Z',
112+
steps: [
113+
{
114+
id: 'step_1',
115+
name: 'Remove legacy_id from users',
116+
instruction: {
117+
type: 'field_delete',
118+
object_name: 'users',
119+
field_name: 'legacy_id',
120+
deletion_strategy: 'archive',
121+
archive_location: 'backups/users_legacy_id',
122+
description: 'Remove deprecated legacy_id field',
123+
reason: 'Field no longer needed after migration to new ID system'
124+
} as FieldDeleteInstruction,
125+
reversible: true
126+
},
127+
{
128+
id: 'step_2',
129+
name: 'Remove old_status from projects',
130+
instruction: {
131+
type: 'field_delete',
132+
object_name: 'projects',
133+
field_name: 'old_status',
134+
deletion_strategy: 'soft',
135+
description: 'Remove deprecated status field',
136+
reason: 'Replaced by new status state machine'
137+
} as FieldDeleteInstruction,
138+
reversible: true,
139+
depends_on: ['step_1']
140+
}
141+
],
142+
reversible: true,
143+
tags: ['cleanup', 'deprecated']
144+
};
145+
146+
// ========================================
147+
// Example 4: Object Rename Migration
148+
// ========================================
149+
150+
const renameObjectMigration: MigrationConfig = {
151+
id: 'v1.3_rename_customer_to_account',
152+
version: '1.3.0',
153+
name: 'Rename Customer to Account',
154+
description: 'Rename customer object to account for CRM consistency',
155+
author: 'product-team',
156+
created_at: '2026-01-20T00:00:00Z',
157+
steps: [
158+
{
159+
id: 'step_1',
160+
name: 'Rename customer object',
161+
instruction: {
162+
type: 'object_update',
163+
object_name: 'customers',
164+
new_object_name: 'accounts',
165+
changes: {
166+
label: 'Account',
167+
description: 'Business accounts and customers',
168+
icon: 'standard:account'
169+
},
170+
description: 'Rename object for CRM terminology',
171+
reason: 'Align with standard CRM naming (Salesforce-like)'
172+
} as ObjectUpdateInstruction,
173+
reversible: true
174+
}
175+
],
176+
reversible: true,
177+
tags: ['refactor', 'crm']
178+
};
179+
180+
// ========================================
181+
// Example 5: Remove Temporary Object
182+
// ========================================
183+
184+
const removeTempObjectMigration: MigrationConfig = {
185+
id: 'v1.5_remove_temp_imports',
186+
version: '1.5.0',
187+
name: 'Remove Temporary Import Table',
188+
description: 'Clean up temporary import table after migration',
189+
author: 'dev-team',
190+
created_at: '2026-01-25T00:00:00Z',
191+
steps: [
192+
{
193+
id: 'step_1',
194+
name: 'Delete temp_imports object',
195+
instruction: {
196+
type: 'object_delete',
197+
object_name: 'temp_imports',
198+
deletion_strategy: 'archive',
199+
archive_location: 'backups/temp_imports_archive',
200+
cascade_strategy: 'nullify',
201+
description: 'Remove temporary import staging table',
202+
reason: 'Completed migration to new import system'
203+
} as ObjectDeleteInstruction,
204+
reversible: true
205+
}
206+
],
207+
reversible: true,
208+
tags: ['cleanup', 'temporary']
209+
};
210+
211+
// ========================================
212+
// Example 6: Complex Multi-Step Migration
213+
// ========================================
214+
215+
const complexMigration: MigrationConfig = {
216+
id: 'v2.1_refactor_user_profile',
217+
version: '2.1.0',
218+
name: 'Refactor User Profile Structure',
219+
description: 'Comprehensive update to user profile data model',
220+
author: 'dev-team',
221+
created_at: '2026-03-01T00:00:00Z',
222+
steps: [
223+
{
224+
id: 'step_1',
225+
name: 'Add new bio field',
226+
instruction: {
227+
type: 'field_update',
228+
object_name: 'users',
229+
field_name: 'bio',
230+
changes: {
231+
type: 'textarea',
232+
label: 'Biography',
233+
max_length: 500
234+
},
235+
data_migration_strategy: 'clear'
236+
} as FieldUpdateInstruction,
237+
reversible: true
238+
},
239+
{
240+
id: 'step_2',
241+
name: 'Make email unique and required',
242+
instruction: {
243+
type: 'field_update',
244+
object_name: 'users',
245+
field_name: 'email',
246+
changes: {
247+
required: true,
248+
unique: true
249+
},
250+
data_migration_strategy: 'auto'
251+
} as FieldUpdateInstruction,
252+
reversible: true,
253+
depends_on: ['step_1']
254+
},
255+
{
256+
id: 'step_3',
257+
name: 'Remove deprecated nickname field',
258+
instruction: {
259+
type: 'field_delete',
260+
object_name: 'users',
261+
field_name: 'nickname',
262+
deletion_strategy: 'archive',
263+
archive_location: 'backups/users_nickname'
264+
} as FieldDeleteInstruction,
265+
reversible: true,
266+
depends_on: ['step_1', 'step_2']
267+
},
268+
{
269+
id: 'step_4',
270+
name: 'Update user object metadata',
271+
instruction: {
272+
type: 'object_update',
273+
object_name: 'users',
274+
changes: {
275+
label: 'System User',
276+
description: 'Registered system users with profiles'
277+
}
278+
} as ObjectUpdateInstruction,
279+
reversible: true,
280+
depends_on: ['step_3']
281+
}
282+
],
283+
reversible: true,
284+
depends_on: ['v2.0_cleanup_legacy_fields'],
285+
tags: ['schema', 'refactor', 'major']
286+
};
287+
288+
// ========================================
289+
// Example 7: Migration File Format (YAML)
290+
// ========================================
291+
292+
/**
293+
* Migrations can also be defined in YAML format for AI-friendliness.
294+
* File naming convention: <migration_id>.migration.yml
295+
*
296+
* Example: v1.1_rename_username.migration.yml
297+
*
298+
* ```yaml
299+
* id: v1.1_rename_username
300+
* version: 1.1.0
301+
* name: Rename Username Field
302+
* description: Rename username to user_name for consistency
303+
* author: dev-team
304+
* created_at: 2026-01-14T00:00:00Z
305+
*
306+
* steps:
307+
* - id: step_1
308+
* name: Rename username field
309+
* instruction:
310+
* type: field_update
311+
* object_name: users
312+
* field_name: username
313+
* new_field_name: user_name
314+
* changes:
315+
* label: User Name
316+
* data_migration_strategy: auto
317+
* reversible: true
318+
*
319+
* reversible: true
320+
* tags:
321+
* - refactor
322+
* - naming
323+
* ```
324+
*/
325+
326+
// ========================================
327+
// Usage Example
328+
// ========================================
329+
330+
export function demonstrateMigrationUsage() {
331+
console.log('Migration Examples for ObjectQL');
332+
console.log('================================\n');
333+
334+
console.log('1. Field Rename Migration:');
335+
console.log(JSON.stringify(renameFieldMigration, null, 2));
336+
console.log('\n');
337+
338+
console.log('2. Field Type Change Migration:');
339+
console.log(JSON.stringify(changeFieldTypeMigration, null, 2));
340+
console.log('\n');
341+
342+
console.log('3. Remove Deprecated Fields:');
343+
console.log(JSON.stringify(removeDeprecatedFieldsMigration, null, 2));
344+
console.log('\n');
345+
346+
console.log('4. Object Rename Migration:');
347+
console.log(JSON.stringify(renameObjectMigration, null, 2));
348+
console.log('\n');
349+
350+
console.log('5. Remove Temporary Object:');
351+
console.log(JSON.stringify(removeTempObjectMigration, null, 2));
352+
console.log('\n');
353+
354+
console.log('6. Complex Multi-Step Migration:');
355+
console.log(JSON.stringify(complexMigration, null, 2));
356+
}
357+
358+
// Export all examples
359+
export {
360+
renameFieldMigration,
361+
changeFieldTypeMigration,
362+
removeDeprecatedFieldsMigration,
363+
renameObjectMigration,
364+
removeTempObjectMigration,
365+
complexMigration
366+
};

0 commit comments

Comments
 (0)