@ftschopp/dynatable-migrations 1.0.0

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 (73) hide show
  1. package/.gitkeep +0 -0
  2. package/CHANGELOG.md +13 -0
  3. package/README.md +421 -0
  4. package/USAGE.md +557 -0
  5. package/bin/dynatable-migrate.js +30 -0
  6. package/dist/cli.d.ts +3 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +104 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/commands/create.d.ts +2 -0
  11. package/dist/commands/create.d.ts.map +1 -0
  12. package/dist/commands/create.js +123 -0
  13. package/dist/commands/create.js.map +1 -0
  14. package/dist/commands/down.d.ts +3 -0
  15. package/dist/commands/down.d.ts.map +1 -0
  16. package/dist/commands/down.js +37 -0
  17. package/dist/commands/down.js.map +1 -0
  18. package/dist/commands/init.d.ts +2 -0
  19. package/dist/commands/init.d.ts.map +1 -0
  20. package/dist/commands/init.js +70 -0
  21. package/dist/commands/init.js.map +1 -0
  22. package/dist/commands/status.d.ts +3 -0
  23. package/dist/commands/status.d.ts.map +1 -0
  24. package/dist/commands/status.js +84 -0
  25. package/dist/commands/status.js.map +1 -0
  26. package/dist/commands/up.d.ts +3 -0
  27. package/dist/commands/up.d.ts.map +1 -0
  28. package/dist/commands/up.js +37 -0
  29. package/dist/commands/up.js.map +1 -0
  30. package/dist/core/config.d.ts +29 -0
  31. package/dist/core/config.d.ts.map +1 -0
  32. package/dist/core/config.js +160 -0
  33. package/dist/core/config.js.map +1 -0
  34. package/dist/core/loader.d.ts +47 -0
  35. package/dist/core/loader.d.ts.map +1 -0
  36. package/dist/core/loader.js +226 -0
  37. package/dist/core/loader.js.map +1 -0
  38. package/dist/core/runner.d.ts +38 -0
  39. package/dist/core/runner.d.ts.map +1 -0
  40. package/dist/core/runner.js +166 -0
  41. package/dist/core/runner.js.map +1 -0
  42. package/dist/core/tracker.d.ts +19 -0
  43. package/dist/core/tracker.d.ts.map +1 -0
  44. package/dist/core/tracker.js +172 -0
  45. package/dist/core/tracker.js.map +1 -0
  46. package/dist/index.d.ts +16 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +48 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/templates/migration.d.ts +5 -0
  51. package/dist/templates/migration.d.ts.map +1 -0
  52. package/dist/templates/migration.js +96 -0
  53. package/dist/templates/migration.js.map +1 -0
  54. package/dist/types/index.d.ts +159 -0
  55. package/dist/types/index.d.ts.map +1 -0
  56. package/dist/types/index.js +3 -0
  57. package/dist/types/index.js.map +1 -0
  58. package/migrations/.gitkeep +0 -0
  59. package/package.json +43 -0
  60. package/src/cli.ts +106 -0
  61. package/src/commands/create.ts +110 -0
  62. package/src/commands/down.ts +42 -0
  63. package/src/commands/init.ts +37 -0
  64. package/src/commands/status.ts +92 -0
  65. package/src/commands/up.ts +39 -0
  66. package/src/core/config.ts +140 -0
  67. package/src/core/loader.ts +233 -0
  68. package/src/core/runner.ts +223 -0
  69. package/src/core/tracker.ts +219 -0
  70. package/src/index.ts +23 -0
  71. package/src/templates/migration.ts +92 -0
  72. package/src/types/index.ts +196 -0
  73. package/tsconfig.json +19 -0
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Migration template generator
3
+ */
4
+ export function generateMigrationTemplate(version: string, name: string): string {
5
+ return `import { Migration } from "@ftschopp/dynatable-migrations";
6
+
7
+ /**
8
+ * Migration: ${name}
9
+ * Version: ${version}
10
+ *
11
+ * Description:
12
+ * Add description of what this migration does here.
13
+ *
14
+ * Version type:
15
+ * - MAJOR (X.0.0): Breaking changes, incompatible schema changes
16
+ * - MINOR (0.X.0): New features, backwards-compatible changes
17
+ * - PATCH (0.0.X): Bug fixes, data corrections
18
+ */
19
+ export const migration: Migration = {
20
+ version: "${version}",
21
+ name: "${name}",
22
+ description: "Add description here",
23
+
24
+ /**
25
+ * Schema snapshot (optional)
26
+ * Document your schema changes here for reference
27
+ */
28
+ schema: {
29
+ // Example:
30
+ // User: {
31
+ // attributes: {
32
+ // username: { type: String, required: true },
33
+ // email: { type: String, required: false },
34
+ // }
35
+ // }
36
+ },
37
+
38
+ /**
39
+ * Apply migration
40
+ */
41
+ async up({ client, tableName, dynamodb }) {
42
+ console.log("Running migration: ${name}");
43
+
44
+ // Example: Add a new attribute to existing items
45
+ // const { ScanCommand, UpdateCommand } = dynamodb;
46
+ //
47
+ // const result = await client.send(new ScanCommand({
48
+ // TableName: tableName,
49
+ // FilterExpression: "begins_with(PK, :pk)",
50
+ // ExpressionAttributeValues: { ":pk": "USER#" }
51
+ // }));
52
+ //
53
+ // for (const item of result.Items || []) {
54
+ // await client.send(new UpdateCommand({
55
+ // TableName: tableName,
56
+ // Key: { PK: item.PK, SK: item.SK },
57
+ // UpdateExpression: "SET emailVerified = :value",
58
+ // ExpressionAttributeValues: { ":value": false }
59
+ // }));
60
+ // }
61
+
62
+ console.log("✅ Migration completed");
63
+ },
64
+
65
+ /**
66
+ * Rollback migration
67
+ */
68
+ async down({ client, tableName, dynamodb }) {
69
+ console.log("Rolling back migration: ${name}");
70
+
71
+ // Example: Remove the attribute added in up()
72
+ // const { ScanCommand, UpdateCommand } = dynamodb;
73
+ //
74
+ // const result = await client.send(new ScanCommand({
75
+ // TableName: tableName,
76
+ // FilterExpression: "begins_with(PK, :pk)",
77
+ // ExpressionAttributeValues: { ":pk": "USER#" }
78
+ // }));
79
+ //
80
+ // for (const item of result.Items || []) {
81
+ // await client.send(new UpdateCommand({
82
+ // TableName: tableName,
83
+ // Key: { PK: item.PK, SK: item.SK },
84
+ // UpdateExpression: "REMOVE email, emailVerified"
85
+ // }));
86
+ // }
87
+
88
+ console.log("✅ Rollback completed");
89
+ },
90
+ };
91
+ `;
92
+ }
@@ -0,0 +1,196 @@
1
+ import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
2
+ import type {
3
+ ScanCommand,
4
+ QueryCommand,
5
+ GetCommand,
6
+ PutCommand,
7
+ UpdateCommand,
8
+ DeleteCommand,
9
+ BatchGetCommand,
10
+ BatchWriteCommand,
11
+ TransactWriteCommand,
12
+ TransactGetCommand,
13
+ } from '@aws-sdk/lib-dynamodb';
14
+
15
+ /**
16
+ * DynamoDB commands available in migrations
17
+ */
18
+ export interface DynamoDBCommands {
19
+ ScanCommand: typeof ScanCommand;
20
+ QueryCommand: typeof QueryCommand;
21
+ GetCommand: typeof GetCommand;
22
+ PutCommand: typeof PutCommand;
23
+ UpdateCommand: typeof UpdateCommand;
24
+ DeleteCommand: typeof DeleteCommand;
25
+ BatchGetCommand: typeof BatchGetCommand;
26
+ BatchWriteCommand: typeof BatchWriteCommand;
27
+ TransactWriteCommand: typeof TransactWriteCommand;
28
+ TransactGetCommand: typeof TransactGetCommand;
29
+ }
30
+
31
+ /**
32
+ * Migration context provided to up/down functions
33
+ */
34
+ export interface MigrationContext {
35
+ client: DynamoDBDocumentClient;
36
+ tableName: string;
37
+ tracker: MigrationTracker;
38
+ config: MigrationConfig;
39
+ dynamodb: DynamoDBCommands;
40
+ }
41
+
42
+ /**
43
+ * Schema change record for tracking evolution
44
+ */
45
+ export interface SchemaChange {
46
+ entity: string;
47
+ changes: {
48
+ added?: string[];
49
+ removed?: string[];
50
+ modified?: Array<{
51
+ field: string;
52
+ from: any;
53
+ to: any;
54
+ }>;
55
+ };
56
+ }
57
+
58
+ /**
59
+ * Migration definition
60
+ */
61
+ export interface Migration {
62
+ version: string;
63
+ name: string;
64
+ description?: string;
65
+
66
+ // Optional schema snapshot for documentation
67
+ schema?: Record<string, any>;
68
+
69
+ // Migration functions
70
+ up: (context: MigrationContext) => Promise<void>;
71
+ down: (context: MigrationContext) => Promise<void>;
72
+ }
73
+
74
+ /**
75
+ * Migration record stored in DynamoDB
76
+ */
77
+ export interface MigrationRecord {
78
+ PK: string; // "SCHEMA#VERSION"
79
+ SK: string; // "v0001"
80
+ version: string;
81
+ name: string;
82
+ description?: string;
83
+ timestamp: string;
84
+ appliedAt: string;
85
+ status: 'applied' | 'rolled_back' | 'failed';
86
+ schemaDefinition?: Record<string, any>;
87
+ schemaChanges?: SchemaChange[];
88
+ checksum?: string; // Hash of migration file
89
+ error?: string; // Error message if failed
90
+ }
91
+
92
+ /**
93
+ * Current schema pointer record
94
+ */
95
+ export interface CurrentSchemaRecord {
96
+ GSI1PK: string; // "SCHEMA#CURRENT"
97
+ GSI1SK: string; // Current version
98
+ PK: string;
99
+ SK: string;
100
+ currentVersion: string;
101
+ updatedAt: string;
102
+ }
103
+
104
+ /**
105
+ * Migration configuration
106
+ */
107
+ export interface MigrationConfig {
108
+ tableName: string;
109
+ client: {
110
+ endpoint?: string;
111
+ region: string;
112
+ credentials?: {
113
+ accessKeyId: string;
114
+ secretAccessKey: string;
115
+ };
116
+ };
117
+ migrationsDir?: string;
118
+ trackingPrefix?: string; // Default: "_SCHEMA#VERSION"
119
+ gsi1Name?: string; // Default: "GSI1"
120
+ }
121
+
122
+ /**
123
+ * Migration tracker interface
124
+ */
125
+ export interface MigrationTracker {
126
+ /**
127
+ * Initialize migration tracking table/items if needed
128
+ */
129
+ initialize(): Promise<void>;
130
+
131
+ /**
132
+ * Get all applied migrations
133
+ */
134
+ getAppliedMigrations(): Promise<MigrationRecord[]>;
135
+
136
+ /**
137
+ * Get current schema version
138
+ */
139
+ getCurrentVersion(): Promise<string | null>;
140
+
141
+ /**
142
+ * Mark migration as applied
143
+ */
144
+ markAsApplied(
145
+ version: string,
146
+ name: string,
147
+ schemaDefinition?: Record<string, any>,
148
+ schemaChanges?: SchemaChange[]
149
+ ): Promise<void>;
150
+
151
+ /**
152
+ * Mark migration as rolled back
153
+ */
154
+ markAsRolledBack(version: string): Promise<void>;
155
+
156
+ /**
157
+ * Mark migration as failed
158
+ */
159
+ markAsFailed(version: string, error: string): Promise<void>;
160
+
161
+ /**
162
+ * Record schema changes
163
+ */
164
+ recordSchemaChange(change: SchemaChange): Promise<void>;
165
+
166
+ /**
167
+ * Get migration by version
168
+ */
169
+ getMigration(version: string): Promise<MigrationRecord | null>;
170
+
171
+ /**
172
+ * Check if migration was applied
173
+ */
174
+ isApplied(version: string): Promise<boolean>;
175
+ }
176
+
177
+ /**
178
+ * Migration file info
179
+ */
180
+ export interface MigrationFile {
181
+ version: string;
182
+ name: string;
183
+ filePath: string;
184
+ migration: Migration;
185
+ }
186
+
187
+ /**
188
+ * Migration status
189
+ */
190
+ export interface MigrationStatus {
191
+ version: string;
192
+ name: string;
193
+ status: 'pending' | 'applied' | 'rolled_back' | 'failed';
194
+ appliedAt?: string;
195
+ error?: string;
196
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "extends": "@repo/typescript-config/base.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "./src",
6
+ "module": "commonjs",
7
+ "target": "ES2020",
8
+ "declaration": true,
9
+ "declarationMap": true,
10
+ "sourceMap": true,
11
+ "esModuleInterop": true,
12
+ "skipLibCheck": true,
13
+ "strict": true,
14
+ "resolveJsonModule": true,
15
+ "moduleResolution": "node"
16
+ },
17
+ "include": ["src/**/*"],
18
+ "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
19
+ }