{"id":46486332,"url":"https://github.com/purpom-media-lab/amplify-data-migration","last_synced_at":"2026-03-06T09:32:08.596Z","repository":{"id":257189245,"uuid":"847010870","full_name":"purpom-media-lab/amplify-data-migration","owner":"purpom-media-lab","description":"Amplify Data Migration Tool","archived":false,"fork":false,"pushed_at":"2026-02-03T20:18:35.000Z","size":1716,"stargazers_count":5,"open_issues_count":10,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-04T09:19:04.607Z","etag":null,"topics":["amplify","dynamodb","migration"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/@purpom-media-lab/amplify-data-migration","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/purpom-media-lab.png","metadata":{"files":{"readme":"README.ja.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-08-24T15:39:14.000Z","updated_at":"2025-12-28T14:43:58.000Z","dependencies_parsed_at":"2024-09-15T08:08:16.329Z","dependency_job_id":"d0cd9dca-89b0-4ef5-b2be-a6cc31350861","html_url":"https://github.com/purpom-media-lab/amplify-data-migration","commit_stats":null,"previous_names":["purpom-media-lab/amplify-data-migration"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/purpom-media-lab/amplify-data-migration","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purpom-media-lab%2Famplify-data-migration","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purpom-media-lab%2Famplify-data-migration/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purpom-media-lab%2Famplify-data-migration/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purpom-media-lab%2Famplify-data-migration/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/purpom-media-lab","download_url":"https://codeload.github.com/purpom-media-lab/amplify-data-migration/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purpom-media-lab%2Famplify-data-migration/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30168981,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-06T07:56:45.623Z","status":"ssl_error","status_checked_at":"2026-03-06T07:55:55.621Z","response_time":250,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["amplify","dynamodb","migration"],"created_at":"2026-03-06T09:32:07.804Z","updated_at":"2026-03-06T09:32:08.579Z","avatar_url":"https://github.com/purpom-media-lab.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Amplify Data Migration Tool\n\n- [English](./README.md)\n\n### 機能\n\n- TypeScript でのマイグレーション処理の実装\n- DynamoDB Point-In-Time Recovery を利用した export の実行\n- 実行したマイグレーションの管理\n\n## Installation\n\n```sh\nnpm install -D @purpom-media-lab/amplify-data-migration\n```\n\n## Usage\n\n### Initialize\n\nマイグレーションテーブルの作成\n\n最初（アプリ\u0026環境毎）に、以下のコマンドでマイグレーションテーブルと S3 バケットを作成します。\n\n```sh\ndata-migration init --appId '\u003cappId\u003e' --branch '\u003cbranch name\u003e' --profile '\u003cprofile name\u003e'\n```\n\n#### Amplify Gen2 サンドボックス環境での利用\n\nAmplify Gen2 のサンドボックス環境を使用する場合、`--appId` と `--branch` を指定する代わりに `sandbox` サブコマンドを使用できます。\n\n```sh\ndata-migration sandbox init --profile '\u003cprofile name\u003e'\n```\n\n`sandbox` サブコマンドを使用すると、ローカル環境からサンドボックス識別子を自動的に検出し、それを使用してマイグレーションリソースを初期化します。\n\nサンドボックス識別子を明示的に指定することもできます:\n\n```sh\ndata-migration sandbox init --identifier '\u003csandbox-identifier\u003e' --profile '\u003cprofile name\u003e'\n```\n\n### Create Migration File\n\n以下のように、マイグレーションの名前を指定してマイグレーションファイルの雛形を作成できます。\n\n```sh\ndata-migration create --name \u003cmigration file name\u003e --migrationsDir \u003cpath to migration file directory\u003e\n```\n\n#### Update Models\n\n既に以下のように`Todo`モデルが存在したとします。\n\n```ts\nconst schema = a.schema({\n  Todo: a\n    .model({\n      content: a.string(),\n    })\n    .authorization((allow) =\u003e [allow.owner()]),\n});\n```\n\nリリース後に`completed`フィールドが必要になり、以下のように`Todo`モデルに`completed`フィールドを追加する必要があります。\n\n```ts\nconst schema = a.schema({\n  Todo: a\n    .model({\n      content: a.string(),\n      completed: a.boolean().required(),\n    })\n    .authorization((allow) =\u003e [allow.owner()]),\n});\n```\n\nモデルの変更により、`completed`フィールドが追加されますが、DynamoDB にある既存のデータには`completed`フィールドは存在しません。\nこのままでは必須のフィールドである `completed` フィールドがない既存レコードを `AppSync` 経由で取得しようとするとエラーが発生します。\n\n`amplify-data-migration`では以下のように`Migration`インタフェースを実装クラスにマイグレーション処理を実装します。\n以下は、`false`をもつ`completed`フィールドを追加するマイグレーションです。\n\n```ts\nimport {\n  Migration,\n  MigrationContext,\n  ModelTransformer,\n} from \"@purpom-media-lab/amplify-data-migration\";\n\nexport default class AddCompletedField_1725285846599 implements Migration {\n  readonly name = \"add_completed_field\";\n  readonly timestamp = 1725285846599;\n  async run(context: MigrationContext) {\n    type OldTodo = { id: string; content: string };\n    type NewTodo = { id: string; content: string; completed: boolean };\n    const transformer: ModelTransformer\u003cOldTodo, NewTodo\u003e = async (\n      oldModel\n    ) =\u003e {\n      return { ...oldModel, completed: false };\n    };\n    await context.modelClient.updateModel(\"Todo\", transformer);\n  }\n}\n```\n\n#### Put Models\n\nリリース前に存在しなかった`Profile`というモデルを追加したとします。`Profile`モデルはユーザー毎に存在し、\nアプリケーションは`Profile`モデルを必要とするため、マイグレーションでユーザー毎に`Profile`を DynamoDB に登録する必要があります。\n\n```ts\nconst schema = a.schema({\n  Profile: a\n    .model({\n      name: a.string().requred(),\n    })\n    .authorization((allow) =\u003e [allow.owner()]),\n});\n```\n\n`amplify-data-migration`では以下のように`ModelClient.putModel`メソッドを使って新規のデータを登録することができます。\n以下は、Cognit の UserPool のユーザーに対応する`Profile`を新規登録するマイグレーションです。\n\n```ts\nimport {\n  Migration,\n  MigrationContext,\n  ModelGenerator,\n} from \"@purpom-media-lab/amplify-data-migration\";\nimport {\n  CognitoIdentityProviderClient,\n  ListUsersCommand,\n} from \"@aws-sdk/client-cognito-identity-provider\";\n\nconst client = new CognitoIdentityProviderClient();\n\ntype Profile = {\n  id: string;\n  name: string;\n  owner: string;\n  createdAt?: string;\n  updatedAt?: string;\n};\n\nexport default class AddProfileModel_1725285846601 implements Migration {\n  readonly name = \"add_profile_model\";\n  readonly timestamp = 1725285846601;\n  private userPoolId: string = process.env.USER_POOL_ID!;\n\n  async run(context: MigrationContext) {\n    const userPoolId = this.userPoolId;\n    const generator: ModelGenerator\u003cProfile\u003e = async function* () {\n      let token;\n      do {\n        const command: ListUsersCommand = new ListUsersCommand({\n          UserPoolId: userPoolId,\n          Limit: 20,\n          PaginationToken: token,\n        });\n        const response = await client.send(command);\n        token = response.PaginationToken;\n        for (const user of response.Users ?? []) {\n          const owner = `${user.Username}::${user.Username}`;\n          const now = new Date().toISOString();\n          yield {\n            id: crypto.randomUUID(),\n            name:\n              user?.Attributes?.find((attribute) =\u003e attribute.Name === \"Email\")\n                ?.Value ?? \"\",\n            owner,\n            createdAt: now,\n            updatedAt: now,\n          };\n        }\n      } while (token);\n    };\n    await context.modelClient.putModel(\"Profile\", generator);\n  }\n}\n```\n\n### Run Migrations\n\n以下のように`data-migration migrate`コマンドを実行すると、`amplify-data-migration`は実行されていないマイグレーションを実行します。\n\n```sh\ndata-migration migrate --appId '\u003cappId\u003e' --branch '\u003cbranch name\u003e' --migrationsDir ./dist/migrations/ --profile '\u003cprofile name\u003e'\n```\n\nサンドボックス環境の場合:\n\n```sh\ndata-migration sandbox migrate --migrationsDir ./dist/migrations/ --profile '\u003cprofile name\u003e'\n```\n\n### Migrate from export data with Point-in-Time Recovery\n\n以下のように`Book`モデルが存在したとします。\n\n```ts\nconst schema = a.schema({\n  Book: a.model({\n    author: a.string(),\n    title: a.string(),\n  }),\n});\n```\n\nリリース後に`author`, `title`フィールドをキーにする変更が必要になり、以下のように`Book`モデルを変更したとします。\n\n```ts\nconst schema = a.schema({\n  Book: a\n    .model({\n      author: a.id().required(),\n      title: a.string(),\n    })\n    .identifier([\"author\", \"title\"])\n    .authorization((allow) =\u003e [allow.owner()]),\n});\n```\n\nAWS Amplify ではモデルのキーを変更した場合、DynamoDB テーブルが replace され、既存データが破棄されます。\nそのため、`Migration.run`関数の実装だけでは既存データをマイグレーションできません。\nこの場合、`Migration.export`関数で既存データのエクスポートを実装します。\n\n`Migration.export`関数では`context.modelClient.exportModel`を呼び出すことでモデルの既存データをエクスポートすることができます。\nそして、`Migration.run`関数で`context.modelClient.runImport`を呼び出すことでエクスポートしたデータを replace 後のテーブルにインポートすることができます。\n\n```ts\nimport {\n  ExportContext,\n  Migration,\n  MigrationContext,\n  ModelTransformer,\n} from \"@purpom-media-lab/amplify-data-migration\";\n\nexport default class ChangeBookKey_1725285846600 implements Migration {\n  readonly name = \"change_book_key\";\n  readonly timestamp = 1725285846600;\n\n  async export(\n    context: ExportContext\n  ): Promise\u003cRecord\u003cstring, DynamoDBExportKey\u003e\u003e {\n    // Export Book table to S3 bucket with Point-in-Time Recovery\n    const key = await context.modelClient.exportModel(\"Book\");\n    return { Book: key };\n  }\n\n  async run(context: MigrationContext) {\n    type OldBook = { id: string; author: string; title: string };\n    type NewBook = { author: string; title: string };\n    const newKeys: string[] = [];\n    const transformer: ModelTransformer\u003cOldBook, NewBook\u003e = async (\n      oldModel\n    ) =\u003e {\n      const { id, ...newModel } = oldModel;\n      if (newKeys.includes(`${newModel.author}:${newModel.title}`)) {\n        // Skip if the same key already exists.\n        return null;\n      }\n      newKeys.push(`${newModel.author}:${newModel.title}`);\n      return newModel;\n    };\n    // Import exported data to new Book table.\n    await context.modelClient.runImport(\"Book\", transformer);\n  }\n}\n```\n\n以下のように`data-migration export`コマンドを実行すると、`amplify-data-migration`は実行されていないマイグレーションの export を実行します。\n通常、このコマンドは`npx ampx pipeline-deploy`でデプロイを実行する前に呼び出すことを想定しています。\n\n```sh\ndata-migration export --appId '\u003cappId\u003e' --branch '\u003cbranch name\u003e' --profile '\u003cprofile name\u003e'\n```\n\nサンドボックス環境の場合:\n\n```sh\ndata-migration sandbox export --profile '\u003cprofile name\u003e'\n```\n\n### Destroy\n\nAmplify Data Migration Tool の利用をやめる場合、以下のコマンドでマイグレーションテーブルと S3 バケットを破棄します。\n\n```sh\ndata-migration destroy --appId '\u003cappId\u003e' --branch '\u003cbranch name\u003e' --profile '\u003cprofile name\u003e'\n```\n\nサンドボックス環境の場合:\n\n```sh\ndata-migration sandbox destroy --profile '\u003cprofile name\u003e'\n```\n\n## Development\n\n### Build\n\n```sh\nnpm run build\n```\n\n### Test\n\nテストには[LocalStack](https://github.com/localstack/localstack)を利用します。\nテスト実行前に以下のコマンドを実行して LoaclStack を起動してください。\n\n```sh\ndocker-compose up\n```\n\n以下のコマンドを実行してテストを実行します。\n\n```sh\nnpm test\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpurpom-media-lab%2Famplify-data-migration","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpurpom-media-lab%2Famplify-data-migration","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpurpom-media-lab%2Famplify-data-migration/lists"}