@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,172 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DynamoDBMigrationTracker = void 0;
4
+ const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
5
+ class DynamoDBMigrationTracker {
6
+ constructor(client, config) {
7
+ this.client = client;
8
+ this.tableName = config.tableName;
9
+ this.trackingPrefix = config.trackingPrefix || '_SCHEMA#VERSION';
10
+ this.gsi1Name = config.gsi1Name || 'GSI1';
11
+ }
12
+ async initialize() {
13
+ // Check if current version pointer exists, if not create it
14
+ const current = await this.getCurrentVersion();
15
+ if (!current) {
16
+ // Create initial version pointer
17
+ await this.client.send(new lib_dynamodb_1.PutCommand({
18
+ TableName: this.tableName,
19
+ Item: {
20
+ PK: `${this.trackingPrefix}#CURRENT`,
21
+ SK: `${this.trackingPrefix}#CURRENT`,
22
+ GSI1PK: 'SCHEMA#CURRENT',
23
+ GSI1SK: 'v0000',
24
+ currentVersion: 'v0000',
25
+ updatedAt: new Date().toISOString(),
26
+ },
27
+ }));
28
+ }
29
+ }
30
+ async getAppliedMigrations() {
31
+ const result = await this.client.send(new lib_dynamodb_1.QueryCommand({
32
+ TableName: this.tableName,
33
+ KeyConditionExpression: 'PK = :pk',
34
+ ExpressionAttributeValues: {
35
+ ':pk': this.trackingPrefix,
36
+ },
37
+ }));
38
+ return (result.Items || []);
39
+ }
40
+ async getCurrentVersion() {
41
+ const result = await this.client.send(new lib_dynamodb_1.GetCommand({
42
+ TableName: this.tableName,
43
+ Key: {
44
+ PK: `${this.trackingPrefix}#CURRENT`,
45
+ SK: `${this.trackingPrefix}#CURRENT`,
46
+ },
47
+ }));
48
+ return result.Item?.currentVersion || null;
49
+ }
50
+ async markAsApplied(version, name, schemaDefinition, schemaChanges) {
51
+ const now = new Date().toISOString();
52
+ // Create migration record
53
+ await this.client.send(new lib_dynamodb_1.PutCommand({
54
+ TableName: this.tableName,
55
+ Item: {
56
+ PK: this.trackingPrefix,
57
+ SK: version,
58
+ version,
59
+ name,
60
+ timestamp: now,
61
+ appliedAt: now,
62
+ status: 'applied',
63
+ schemaDefinition,
64
+ schemaChanges,
65
+ },
66
+ }));
67
+ // Update current version pointer
68
+ await this.client.send(new lib_dynamodb_1.UpdateCommand({
69
+ TableName: this.tableName,
70
+ Key: {
71
+ PK: `${this.trackingPrefix}#CURRENT`,
72
+ SK: `${this.trackingPrefix}#CURRENT`,
73
+ },
74
+ UpdateExpression: 'SET currentVersion = :version, updatedAt = :updatedAt, GSI1SK = :gsi1sk',
75
+ ExpressionAttributeValues: {
76
+ ':version': version,
77
+ ':updatedAt': now,
78
+ ':gsi1sk': version,
79
+ },
80
+ }));
81
+ }
82
+ async markAsRolledBack(version) {
83
+ await this.client.send(new lib_dynamodb_1.UpdateCommand({
84
+ TableName: this.tableName,
85
+ Key: {
86
+ PK: this.trackingPrefix,
87
+ SK: version,
88
+ },
89
+ UpdateExpression: 'SET #status = :status, rolledBackAt = :timestamp',
90
+ ExpressionAttributeNames: {
91
+ '#status': 'status',
92
+ },
93
+ ExpressionAttributeValues: {
94
+ ':status': 'rolled_back',
95
+ ':timestamp': new Date().toISOString(),
96
+ },
97
+ }));
98
+ // Find previous version and update current pointer
99
+ const migrations = await this.getAppliedMigrations();
100
+ const appliedMigrations = migrations
101
+ .filter((m) => m.status === 'applied' && m.version !== version)
102
+ .sort((a, b) => b.version.localeCompare(a.version));
103
+ const previousVersion = appliedMigrations[0]?.version || 'v0000';
104
+ await this.client.send(new lib_dynamodb_1.UpdateCommand({
105
+ TableName: this.tableName,
106
+ Key: {
107
+ PK: `${this.trackingPrefix}#CURRENT`,
108
+ SK: `${this.trackingPrefix}#CURRENT`,
109
+ },
110
+ UpdateExpression: 'SET currentVersion = :version, updatedAt = :updatedAt, GSI1SK = :gsi1sk',
111
+ ExpressionAttributeValues: {
112
+ ':version': previousVersion,
113
+ ':updatedAt': new Date().toISOString(),
114
+ ':gsi1sk': previousVersion,
115
+ },
116
+ }));
117
+ }
118
+ async markAsFailed(version, error) {
119
+ await this.client.send(new lib_dynamodb_1.UpdateCommand({
120
+ TableName: this.tableName,
121
+ Key: {
122
+ PK: this.trackingPrefix,
123
+ SK: version,
124
+ },
125
+ UpdateExpression: 'SET #status = :status, #error = :error, failedAt = :timestamp',
126
+ ExpressionAttributeNames: {
127
+ '#status': 'status',
128
+ '#error': 'error',
129
+ },
130
+ ExpressionAttributeValues: {
131
+ ':status': 'failed',
132
+ ':error': error,
133
+ ':timestamp': new Date().toISOString(),
134
+ },
135
+ }));
136
+ }
137
+ async recordSchemaChange(change) {
138
+ const currentVersion = await this.getCurrentVersion();
139
+ if (!currentVersion || currentVersion === 'v0000') {
140
+ throw new Error('Cannot record schema change: No migration has been applied yet');
141
+ }
142
+ // Append to schemaChanges array
143
+ await this.client.send(new lib_dynamodb_1.UpdateCommand({
144
+ TableName: this.tableName,
145
+ Key: {
146
+ PK: this.trackingPrefix,
147
+ SK: currentVersion,
148
+ },
149
+ UpdateExpression: 'SET schemaChanges = list_append(if_not_exists(schemaChanges, :empty_list), :change)',
150
+ ExpressionAttributeValues: {
151
+ ':empty_list': [],
152
+ ':change': [change],
153
+ },
154
+ }));
155
+ }
156
+ async getMigration(version) {
157
+ const result = await this.client.send(new lib_dynamodb_1.GetCommand({
158
+ TableName: this.tableName,
159
+ Key: {
160
+ PK: this.trackingPrefix,
161
+ SK: version,
162
+ },
163
+ }));
164
+ return result.Item || null;
165
+ }
166
+ async isApplied(version) {
167
+ const migration = await this.getMigration(version);
168
+ return migration?.status === 'applied';
169
+ }
170
+ }
171
+ exports.DynamoDBMigrationTracker = DynamoDBMigrationTracker;
172
+ //# sourceMappingURL=tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracker.js","sourceRoot":"","sources":["../../src/core/tracker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @ftschopp/dynatable-migrations
3
+ * DynamoDB migration tool for single table design with schema versioning
4
+ */
5
+ export * from './types';
6
+ export { DynamoDBMigrationTracker } from './core/tracker';
7
+ export { MigrationLoader } from './core/loader';
8
+ export { MigrationRunner } from './core/runner';
9
+ export { ConfigLoader, loadConfig } from './core/config';
10
+ export { generateMigrationTemplate } from './templates/migration';
11
+ export { createMigration } from './commands/create';
12
+ export { runMigrations } from './commands/up';
13
+ export { rollbackMigrations } from './commands/down';
14
+ export { showStatus } from './commands/status';
15
+ export { initProject } from './commands/init';
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,cAAc,SAAS,CAAC;AAGxB,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGzD,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAGlE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ /**
3
+ * @ftschopp/dynatable-migrations
4
+ * DynamoDB migration tool for single table design with schema versioning
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
18
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
19
+ };
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.initProject = exports.showStatus = exports.rollbackMigrations = exports.runMigrations = exports.createMigration = exports.generateMigrationTemplate = exports.loadConfig = exports.ConfigLoader = exports.MigrationRunner = exports.MigrationLoader = exports.DynamoDBMigrationTracker = void 0;
22
+ // Types
23
+ __exportStar(require("./types"), exports);
24
+ // Core
25
+ var tracker_1 = require("./core/tracker");
26
+ Object.defineProperty(exports, "DynamoDBMigrationTracker", { enumerable: true, get: function () { return tracker_1.DynamoDBMigrationTracker; } });
27
+ var loader_1 = require("./core/loader");
28
+ Object.defineProperty(exports, "MigrationLoader", { enumerable: true, get: function () { return loader_1.MigrationLoader; } });
29
+ var runner_1 = require("./core/runner");
30
+ Object.defineProperty(exports, "MigrationRunner", { enumerable: true, get: function () { return runner_1.MigrationRunner; } });
31
+ var config_1 = require("./core/config");
32
+ Object.defineProperty(exports, "ConfigLoader", { enumerable: true, get: function () { return config_1.ConfigLoader; } });
33
+ Object.defineProperty(exports, "loadConfig", { enumerable: true, get: function () { return config_1.loadConfig; } });
34
+ // Template
35
+ var migration_1 = require("./templates/migration");
36
+ Object.defineProperty(exports, "generateMigrationTemplate", { enumerable: true, get: function () { return migration_1.generateMigrationTemplate; } });
37
+ // Commands (for programmatic use)
38
+ var create_1 = require("./commands/create");
39
+ Object.defineProperty(exports, "createMigration", { enumerable: true, get: function () { return create_1.createMigration; } });
40
+ var up_1 = require("./commands/up");
41
+ Object.defineProperty(exports, "runMigrations", { enumerable: true, get: function () { return up_1.runMigrations; } });
42
+ var down_1 = require("./commands/down");
43
+ Object.defineProperty(exports, "rollbackMigrations", { enumerable: true, get: function () { return down_1.rollbackMigrations; } });
44
+ var status_1 = require("./commands/status");
45
+ Object.defineProperty(exports, "showStatus", { enumerable: true, get: function () { return status_1.showStatus; } });
46
+ var init_1 = require("./commands/init");
47
+ Object.defineProperty(exports, "initProject", { enumerable: true, get: function () { return init_1.initProject; } });
48
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;AAEH,QAAQ;AACR,0CAAwB;AAExB,OAAO;AACP,0CAA0D;AAAjD,mHAAA,wBAAwB,OAAA;AACjC,wCAAgD;AAAvC,yGAAA,eAAe,OAAA;AACxB,wCAAgD;AAAvC,yGAAA,eAAe,OAAA;AACxB,wCAAyD;AAAhD,sGAAA,YAAY,OAAA;AAAE,oGAAA,UAAU,OAAA;AAEjC,WAAW;AACX,mDAAkE;AAAzD,sHAAA,yBAAyB,OAAA;AAElC,kCAAkC;AAClC,4CAAoD;AAA3C,yGAAA,eAAe,OAAA;AACxB,oCAA8C;AAArC,mGAAA,aAAa,OAAA;AACtB,wCAAqD;AAA5C,0GAAA,kBAAkB,OAAA;AAC3B,4CAA+C;AAAtC,oGAAA,UAAU,OAAA;AACnB,wCAA8C;AAArC,mGAAA,WAAW,OAAA"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Migration template generator
3
+ */
4
+ export declare function generateMigrationTemplate(version: string, name: string): string;
5
+ //# sourceMappingURL=migration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration.d.ts","sourceRoot":"","sources":["../../src/templates/migration.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAwF/E"}
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateMigrationTemplate = generateMigrationTemplate;
4
+ /**
5
+ * Migration template generator
6
+ */
7
+ function generateMigrationTemplate(version, name) {
8
+ return `import { Migration } from "@ftschopp/dynatable-migrations";
9
+
10
+ /**
11
+ * Migration: ${name}
12
+ * Version: ${version}
13
+ *
14
+ * Description:
15
+ * Add description of what this migration does here.
16
+ *
17
+ * Version type:
18
+ * - MAJOR (X.0.0): Breaking changes, incompatible schema changes
19
+ * - MINOR (0.X.0): New features, backwards-compatible changes
20
+ * - PATCH (0.0.X): Bug fixes, data corrections
21
+ */
22
+ export const migration: Migration = {
23
+ version: "${version}",
24
+ name: "${name}",
25
+ description: "Add description here",
26
+
27
+ /**
28
+ * Schema snapshot (optional)
29
+ * Document your schema changes here for reference
30
+ */
31
+ schema: {
32
+ // Example:
33
+ // User: {
34
+ // attributes: {
35
+ // username: { type: String, required: true },
36
+ // email: { type: String, required: false },
37
+ // }
38
+ // }
39
+ },
40
+
41
+ /**
42
+ * Apply migration
43
+ */
44
+ async up({ client, tableName, dynamodb }) {
45
+ console.log("Running migration: ${name}");
46
+
47
+ // Example: Add a new attribute to existing items
48
+ // const { ScanCommand, UpdateCommand } = dynamodb;
49
+ //
50
+ // const result = await client.send(new ScanCommand({
51
+ // TableName: tableName,
52
+ // FilterExpression: "begins_with(PK, :pk)",
53
+ // ExpressionAttributeValues: { ":pk": "USER#" }
54
+ // }));
55
+ //
56
+ // for (const item of result.Items || []) {
57
+ // await client.send(new UpdateCommand({
58
+ // TableName: tableName,
59
+ // Key: { PK: item.PK, SK: item.SK },
60
+ // UpdateExpression: "SET emailVerified = :value",
61
+ // ExpressionAttributeValues: { ":value": false }
62
+ // }));
63
+ // }
64
+
65
+ console.log("✅ Migration completed");
66
+ },
67
+
68
+ /**
69
+ * Rollback migration
70
+ */
71
+ async down({ client, tableName, dynamodb }) {
72
+ console.log("Rolling back migration: ${name}");
73
+
74
+ // Example: Remove the attribute added in up()
75
+ // const { ScanCommand, UpdateCommand } = dynamodb;
76
+ //
77
+ // const result = await client.send(new ScanCommand({
78
+ // TableName: tableName,
79
+ // FilterExpression: "begins_with(PK, :pk)",
80
+ // ExpressionAttributeValues: { ":pk": "USER#" }
81
+ // }));
82
+ //
83
+ // for (const item of result.Items || []) {
84
+ // await client.send(new UpdateCommand({
85
+ // TableName: tableName,
86
+ // Key: { PK: item.PK, SK: item.SK },
87
+ // UpdateExpression: "REMOVE email, emailVerified"
88
+ // }));
89
+ // }
90
+
91
+ console.log("✅ Rollback completed");
92
+ },
93
+ };
94
+ `;
95
+ }
96
+ //# sourceMappingURL=migration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration.js","sourceRoot":"","sources":["../../src/templates/migration.ts"],"names":[],"mappings":";;AAGA,8DAwFC;AA3FD;;GAEG;AACH,SAAgB,yBAAyB,CAAC,OAAe,EAAE,IAAY;IACrE,OAAO;;;gBAGO,IAAI;cACN,OAAO;;;;;;;;;;;cAWP,OAAO;WACV,IAAI;;;;;;;;;;;;;;;;;;;;;sCAqBuB,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;2CA2BC,IAAI;;;;;;;;;;;;;;;;;;;;;;CAsB9C,CAAC;AACF,CAAC"}
@@ -0,0 +1,159 @@
1
+ import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
2
+ import type { ScanCommand, QueryCommand, GetCommand, PutCommand, UpdateCommand, DeleteCommand, BatchGetCommand, BatchWriteCommand, TransactWriteCommand, TransactGetCommand } from '@aws-sdk/lib-dynamodb';
3
+ /**
4
+ * DynamoDB commands available in migrations
5
+ */
6
+ export interface DynamoDBCommands {
7
+ ScanCommand: typeof ScanCommand;
8
+ QueryCommand: typeof QueryCommand;
9
+ GetCommand: typeof GetCommand;
10
+ PutCommand: typeof PutCommand;
11
+ UpdateCommand: typeof UpdateCommand;
12
+ DeleteCommand: typeof DeleteCommand;
13
+ BatchGetCommand: typeof BatchGetCommand;
14
+ BatchWriteCommand: typeof BatchWriteCommand;
15
+ TransactWriteCommand: typeof TransactWriteCommand;
16
+ TransactGetCommand: typeof TransactGetCommand;
17
+ }
18
+ /**
19
+ * Migration context provided to up/down functions
20
+ */
21
+ export interface MigrationContext {
22
+ client: DynamoDBDocumentClient;
23
+ tableName: string;
24
+ tracker: MigrationTracker;
25
+ config: MigrationConfig;
26
+ dynamodb: DynamoDBCommands;
27
+ }
28
+ /**
29
+ * Schema change record for tracking evolution
30
+ */
31
+ export interface SchemaChange {
32
+ entity: string;
33
+ changes: {
34
+ added?: string[];
35
+ removed?: string[];
36
+ modified?: Array<{
37
+ field: string;
38
+ from: any;
39
+ to: any;
40
+ }>;
41
+ };
42
+ }
43
+ /**
44
+ * Migration definition
45
+ */
46
+ export interface Migration {
47
+ version: string;
48
+ name: string;
49
+ description?: string;
50
+ schema?: Record<string, any>;
51
+ up: (context: MigrationContext) => Promise<void>;
52
+ down: (context: MigrationContext) => Promise<void>;
53
+ }
54
+ /**
55
+ * Migration record stored in DynamoDB
56
+ */
57
+ export interface MigrationRecord {
58
+ PK: string;
59
+ SK: string;
60
+ version: string;
61
+ name: string;
62
+ description?: string;
63
+ timestamp: string;
64
+ appliedAt: string;
65
+ status: 'applied' | 'rolled_back' | 'failed';
66
+ schemaDefinition?: Record<string, any>;
67
+ schemaChanges?: SchemaChange[];
68
+ checksum?: string;
69
+ error?: string;
70
+ }
71
+ /**
72
+ * Current schema pointer record
73
+ */
74
+ export interface CurrentSchemaRecord {
75
+ GSI1PK: string;
76
+ GSI1SK: string;
77
+ PK: string;
78
+ SK: string;
79
+ currentVersion: string;
80
+ updatedAt: string;
81
+ }
82
+ /**
83
+ * Migration configuration
84
+ */
85
+ export interface MigrationConfig {
86
+ tableName: string;
87
+ client: {
88
+ endpoint?: string;
89
+ region: string;
90
+ credentials?: {
91
+ accessKeyId: string;
92
+ secretAccessKey: string;
93
+ };
94
+ };
95
+ migrationsDir?: string;
96
+ trackingPrefix?: string;
97
+ gsi1Name?: string;
98
+ }
99
+ /**
100
+ * Migration tracker interface
101
+ */
102
+ export interface MigrationTracker {
103
+ /**
104
+ * Initialize migration tracking table/items if needed
105
+ */
106
+ initialize(): Promise<void>;
107
+ /**
108
+ * Get all applied migrations
109
+ */
110
+ getAppliedMigrations(): Promise<MigrationRecord[]>;
111
+ /**
112
+ * Get current schema version
113
+ */
114
+ getCurrentVersion(): Promise<string | null>;
115
+ /**
116
+ * Mark migration as applied
117
+ */
118
+ markAsApplied(version: string, name: string, schemaDefinition?: Record<string, any>, schemaChanges?: SchemaChange[]): Promise<void>;
119
+ /**
120
+ * Mark migration as rolled back
121
+ */
122
+ markAsRolledBack(version: string): Promise<void>;
123
+ /**
124
+ * Mark migration as failed
125
+ */
126
+ markAsFailed(version: string, error: string): Promise<void>;
127
+ /**
128
+ * Record schema changes
129
+ */
130
+ recordSchemaChange(change: SchemaChange): Promise<void>;
131
+ /**
132
+ * Get migration by version
133
+ */
134
+ getMigration(version: string): Promise<MigrationRecord | null>;
135
+ /**
136
+ * Check if migration was applied
137
+ */
138
+ isApplied(version: string): Promise<boolean>;
139
+ }
140
+ /**
141
+ * Migration file info
142
+ */
143
+ export interface MigrationFile {
144
+ version: string;
145
+ name: string;
146
+ filePath: string;
147
+ migration: Migration;
148
+ }
149
+ /**
150
+ * Migration status
151
+ */
152
+ export interface MigrationStatus {
153
+ version: string;
154
+ name: string;
155
+ status: 'pending' | 'applied' | 'rolled_back' | 'failed';
156
+ appliedAt?: string;
157
+ error?: string;
158
+ }
159
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":""}
File without changes
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@ftschopp/dynatable-migrations",
3
+ "version": "1.0.0",
4
+ "description": "DynamoDB migration tool for single table design with schema versioning",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "bin": {
8
+ "dynatable-migrate": "./bin/dynatable-migrate.js"
9
+ },
10
+ "publishConfig": {
11
+ "access": "public"
12
+ },
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "dev": "tsc --watch",
16
+ "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist",
17
+ "test": "echo \"No tests yet!\""
18
+ },
19
+ "keywords": [
20
+ "dynamodb",
21
+ "migrations",
22
+ "single-table-design",
23
+ "schema-versioning",
24
+ "cli"
25
+ ],
26
+ "devDependencies": {
27
+ "@repo/eslint-config": "*",
28
+ "@repo/typescript-config": "*",
29
+ "@types/jest": "^30.0.0",
30
+ "@types/node": "^25.0.3",
31
+ "jest": "^30.2.0",
32
+ "ts-jest": "^29.4.6",
33
+ "typescript": "5.9.3"
34
+ },
35
+ "dependencies": {
36
+ "@aws-sdk/client-dynamodb": "^3.965.0",
37
+ "@aws-sdk/lib-dynamodb": "^3.965.0",
38
+ "chalk": "^5.6.2",
39
+ "commander": "^14.0.2",
40
+ "ora": "^9.0.0",
41
+ "ts-node": "^10.9.2"
42
+ }
43
+ }