@ductape/cli 0.2.22 → 0.3.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 (103) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +7 -0
  3. package/dist/commands/generate.js +1 -1
  4. package/dist/commands/migrate-codebase.d.ts +176 -0
  5. package/dist/commands/migrate-codebase.js +753 -0
  6. package/dist/commands/migration-artifact.d.ts +32 -0
  7. package/dist/commands/migration-artifact.js +48 -0
  8. package/dist/commands/migration-assurance.d.ts +10 -0
  9. package/dist/commands/migration-assurance.js +120 -0
  10. package/dist/commands/migration-database.d.ts +21 -0
  11. package/dist/commands/migration-database.js +162 -0
  12. package/dist/commands/migration-e2e.d.ts +68 -0
  13. package/dist/commands/migration-e2e.js +189 -0
  14. package/dist/commands/migration-environments.d.ts +20 -0
  15. package/dist/commands/migration-environments.js +58 -0
  16. package/dist/commands/migration-generated.d.ts +68 -0
  17. package/dist/commands/migration-generated.js +217 -0
  18. package/dist/commands/migration-portfolio.d.ts +88 -0
  19. package/dist/commands/migration-portfolio.js +223 -0
  20. package/dist/commands/migration-products.d.ts +23 -0
  21. package/dist/commands/migration-products.js +88 -0
  22. package/dist/commands/migration-review.d.ts +248 -0
  23. package/dist/commands/migration-review.js +624 -0
  24. package/dist/commands/migration-secrets.d.ts +24 -0
  25. package/dist/commands/migration-secrets.js +93 -0
  26. package/dist/commands/migration-slice.d.ts +132 -0
  27. package/dist/commands/migration-slice.js +266 -0
  28. package/dist/commands/migration-verification.d.ts +12 -0
  29. package/dist/commands/migration-verification.js +194 -0
  30. package/dist/commands/products.d.ts +1 -0
  31. package/dist/commands/products.js +33 -1
  32. package/dist/commands/secrets.d.ts +8 -0
  33. package/dist/commands/secrets.js +44 -0
  34. package/dist/index.js +354 -2
  35. package/dist/lib/integrations.js +6 -1
  36. package/dist/lib/migration-artifact.d.ts +13 -0
  37. package/dist/lib/migration-artifact.js +103 -0
  38. package/package.json +8 -1
  39. package/API_PARITY.md +0 -58
  40. package/DB_MIGRATE_PLAN.md +0 -223
  41. package/ductape.example.ts +0 -18
  42. package/src/commands/apply.ts +0 -153
  43. package/src/commands/apps-import.ts +0 -43
  44. package/src/commands/apps.ts +0 -92
  45. package/src/commands/cloud.ts +0 -68
  46. package/src/commands/completion.ts +0 -119
  47. package/src/commands/db-migrate.ts +0 -209
  48. package/src/commands/db-schema.ts +0 -429
  49. package/src/commands/db.ts +0 -63
  50. package/src/commands/generate.ts +0 -74
  51. package/src/commands/graph.ts +0 -51
  52. package/src/commands/init.ts +0 -39
  53. package/src/commands/install.ts +0 -76
  54. package/src/commands/link.ts +0 -84
  55. package/src/commands/login.ts +0 -145
  56. package/src/commands/logout.ts +0 -7
  57. package/src/commands/platform.ts +0 -123
  58. package/src/commands/products.ts +0 -228
  59. package/src/commands/profiles.ts +0 -23
  60. package/src/commands/resources.ts +0 -213
  61. package/src/commands/secrets.ts +0 -46
  62. package/src/commands/unlink.ts +0 -15
  63. package/src/commands/whoami.ts +0 -27
  64. package/src/commands/workspaces.ts +0 -98
  65. package/src/index.ts +0 -523
  66. package/src/lib/api-client.ts +0 -88
  67. package/src/lib/app-import.ts +0 -82
  68. package/src/lib/apply-loaders.ts +0 -30
  69. package/src/lib/config.ts +0 -230
  70. package/src/lib/context-store.ts +0 -77
  71. package/src/lib/db-methods.ts +0 -56
  72. package/src/lib/db-types.ts +0 -104
  73. package/src/lib/encryption.ts +0 -12
  74. package/src/lib/forms/enums.ts +0 -52
  75. package/src/lib/forms/index.ts +0 -8
  76. package/src/lib/forms/prompt.ts +0 -209
  77. package/src/lib/forms/schemas.ts +0 -288
  78. package/src/lib/forms/types.ts +0 -27
  79. package/src/lib/http.ts +0 -76
  80. package/src/lib/integrations.ts +0 -105
  81. package/src/lib/interactive-opts.ts +0 -13
  82. package/src/lib/migration-files.ts +0 -58
  83. package/src/lib/output.ts +0 -39
  84. package/src/lib/platform-api.ts +0 -209
  85. package/src/lib/proxy/context.ts +0 -94
  86. package/src/lib/proxy/db-proxy.ts +0 -40
  87. package/src/lib/proxy/graph-proxy.ts +0 -64
  88. package/src/lib/proxy/sdk-proxy.ts +0 -58
  89. package/src/lib/read-body.ts +0 -57
  90. package/src/lib/resources.ts +0 -160
  91. package/src/lib/schema-loader.ts +0 -152
  92. package/src/lib/snippets.ts +0 -165
  93. package/src/lib/templates.ts +0 -157
  94. package/src/lib/workspace-context.ts +0 -43
  95. package/src/lib/workspaces.ts +0 -283
  96. package/test/apply-loaders.test.ts +0 -40
  97. package/test/encryption.test.ts +0 -20
  98. package/test/forms.test.ts +0 -25
  99. package/test/http.test.ts +0 -15
  100. package/test/platform-api.test.ts +0 -42
  101. package/test/resources.test.ts +0 -23
  102. package/test/workspace-resolve.test.ts +0 -29
  103. package/tsconfig.json +0 -15
@@ -1,119 +0,0 @@
1
- import { listResourceTypes } from '../lib/resources.js';
2
- import { DB_PROXY_METHODS, GRAPH_PROXY_METHODS } from '../lib/db-methods.js';
3
-
4
- const TOP_LEVEL = [
5
- 'login',
6
- 'logout',
7
- 'whoami',
8
- 'profiles',
9
- 'workspaces',
10
- 'link',
11
- 'unlink',
12
- 'init',
13
- 'install',
14
- 'start',
15
- 'stop',
16
- 'status',
17
- 'products',
18
- 'apps',
19
- 'resources',
20
- 'cloud',
21
- 'db',
22
- 'graph',
23
- 'secrets',
24
- 'generate',
25
- 'completion',
26
- ];
27
-
28
- const ENTITY_CRUD = 'list get create update delete';
29
-
30
- export function runCompletion(shell: 'bash' | 'zsh' | 'fish'): void {
31
- const resources = listResourceTypes();
32
- const crud = 'create list get update delete connect';
33
-
34
- if (shell === 'bash') {
35
- console.log(`
36
- _ductape_completions() {
37
- local cur="\${COMP_WORDS[COMP_CWORD]}"
38
- local prev="\${COMP_WORDS[COMP_CWORD-1]}"
39
- local cmd="\${COMP_WORDS[1]}"
40
-
41
- if [[ \${COMP_CWORD} -eq 1 ]]; then
42
- COMPREPLY=( $(compgen -W "${TOP_LEVEL.join(' ')}" -- "$cur") )
43
- return
44
- fi
45
-
46
- case "$cmd" in
47
- products)
48
- if [[ \${COMP_CWORD} -eq 2 ]]; then
49
- COMPREPLY=( $(compgen -W "${ENTITY_CRUD}" -- "$cur") )
50
- fi
51
- ;;
52
- apps)
53
- if [[ \${COMP_CWORD} -eq 2 ]]; then
54
- COMPREPLY=( $(compgen -W "import ${ENTITY_CRUD}" -- "$cur") )
55
- elif [[ \${COMP_CWORD} -eq 3 && "\${COMP_WORDS[2]}" == "import" ]]; then
56
- COMPREPLY=( $(compgen -f -- "$cur") )
57
- fi
58
- ;;
59
- resources)
60
- if [[ \${COMP_CWORD} -eq 2 ]]; then
61
- COMPREPLY=( $(compgen -W "types ${resources.join(' ')}" -- "$cur") )
62
- elif [[ \${COMP_CWORD} -eq 3 ]]; then
63
- COMPREPLY=( $(compgen -W "${crud}" -- "$cur") )
64
- fi
65
- ;;
66
- db)
67
- if [[ \${COMP_CWORD} -eq 2 ]]; then
68
- COMPREPLY=( $(compgen -W "${DB_PROXY_METHODS.join(' ')}" -- "$cur") )
69
- fi
70
- ;;
71
- graph)
72
- if [[ \${COMP_CWORD} -eq 2 ]]; then
73
- COMPREPLY=( $(compgen -W "${GRAPH_PROXY_METHODS.join(' ')}" -- "$cur") )
74
- fi
75
- ;;
76
- profiles|workspaces)
77
- if [[ \${COMP_CWORD} -eq 2 ]]; then
78
- COMPREPLY=( $(compgen -W "list use" -- "$cur") )
79
- fi
80
- ;;
81
- generate)
82
- if [[ \${COMP_CWORD} -eq 2 ]]; then
83
- COMPREPLY=( $(compgen -W "payload snippet" -- "$cur") )
84
- fi
85
- ;;
86
- esac
87
- }
88
- complete -F _ductape_completions ductape
89
- `);
90
- return;
91
- }
92
-
93
- if (shell === 'zsh') {
94
- console.log(`
95
- #compdef ductape
96
- _ductape() {
97
- local -a commands
98
- commands=(
99
- ${TOP_LEVEL.map((c) => `'${c}:command'`).join('\n ')}
100
- )
101
- _arguments '1: :->cmd' '*: :->args'
102
- case $state in
103
- cmd) _describe 'command' commands ;;
104
- args)
105
- case $words[1] in
106
- resources) _arguments '2: :(types ${resources.join(' ')})' '3: :(${crud.split(' ').join(' ')})' ;;
107
- db) _arguments '2: :(${DB_PROXY_METHODS.join(' ')})' ;;
108
- graph) _arguments '2: :(${GRAPH_PROXY_METHODS.join(' ')})' ;;
109
- esac
110
- ;;
111
- esac
112
- }
113
- _ductape
114
- `);
115
- return;
116
- }
117
-
118
- console.log(`# Fish: use ductape completion bash | source`);
119
- }
@@ -1,209 +0,0 @@
1
- import { findProjectConfig } from '../lib/config.js';
2
- import { loadSchemaFile } from '../lib/schema-loader.js';
3
- import { loadMigrationFiles } from '../lib/migration-files.js';
4
- import { getDbProxy, requireSession } from '../lib/proxy/context.js';
5
- import { fail, printJson } from '../lib/output.js';
6
- import type { DatabaseContext } from '../lib/context-store.js';
7
-
8
- interface MigrateOpts {
9
- env?: string;
10
- db?: string;
11
- dryRun?: boolean;
12
- }
13
-
14
- interface MigrateStatusOpts {
15
- env?: string;
16
- db?: string;
17
- json?: boolean;
18
- }
19
-
20
- interface MigrateRollbackOpts {
21
- env?: string;
22
- db?: string;
23
- n?: number;
24
- }
25
-
26
- function buildDbContext(dbTag: string, envSlug: string, productTag: string): DatabaseContext {
27
- return { database: dbTag, env: envSlug, product: productTag };
28
- }
29
-
30
- async function getAppliedTags(
31
- proxy: ReturnType<typeof getDbProxy>,
32
- dbContext: DatabaseContext,
33
- ): Promise<string[]> {
34
- try {
35
- const result = await proxy.execute<unknown>(
36
- 'migration.history',
37
- [],
38
- dbContext,
39
- );
40
- const list = Array.isArray(result)
41
- ? result
42
- : Array.isArray((result as { data?: unknown[] }).data)
43
- ? (result as { data: unknown[] }).data
44
- : [];
45
- return (list as Array<{ tag?: string }>).map((r) => r.tag ?? '').filter(Boolean);
46
- } catch {
47
- return [];
48
- }
49
- }
50
-
51
- export async function runDbMigrate(opts: MigrateOpts): Promise<void> {
52
- const found = findProjectConfig();
53
- if (!found) fail('No linked project. Run `ductape link` from your project directory.');
54
-
55
- const { dir } = found;
56
- const session = requireSession();
57
- const proxy = getDbProxy(session);
58
- const envSlug = opts.env ?? session.project.env_slug;
59
- const productTag = session.project.product_tag;
60
-
61
- const schemaEntries = loadSchemaFile(dir);
62
- const targets = opts.db ? schemaEntries.filter((e) => e.db === opts.db) : schemaEntries;
63
-
64
- if (targets.length === 0) {
65
- fail(opts.db ? `No db entry found for tag "${opts.db}".` : 'schema.json is empty.');
66
- }
67
-
68
- let totalApplied = 0;
69
- let totalDry = 0;
70
-
71
- for (const entry of targets) {
72
- const { db } = entry;
73
- const dbContext = buildDbContext(db, envSlug, productTag);
74
- const migrations = loadMigrationFiles(dir, db);
75
-
76
- if (migrations.length === 0) {
77
- console.log(`[${db}] No migration files found. Run \`ductape db schema generate\` first.`);
78
- continue;
79
- }
80
-
81
- const appliedTags = await getAppliedTags(proxy, dbContext);
82
- const pending = migrations.filter((m) => !appliedTags.includes(m.tag));
83
-
84
- if (pending.length === 0) {
85
- console.log(`[${db}] Already up to date.`);
86
- continue;
87
- }
88
-
89
- console.log(`[${db}] ${pending.length} pending migration(s).`);
90
-
91
- for (const migration of pending) {
92
- if (opts.dryRun) {
93
- console.log(` [dry-run] Would apply: ${migration.tag}`);
94
- totalDry++;
95
- continue;
96
- }
97
-
98
- process.stdout.write(` Applying ${migration.tag}... `);
99
- try {
100
- await proxy.execute(
101
- 'migration.run',
102
- [[migration]],
103
- dbContext,
104
- );
105
- console.log('done');
106
- totalApplied++;
107
- } catch (err) {
108
- console.log('failed');
109
- fail(`Migration "${migration.tag}" failed: ${err instanceof Error ? err.message : String(err)}`);
110
- }
111
- }
112
- }
113
-
114
- if (opts.dryRun) {
115
- console.log(`\nDry run: ${totalDry} migration(s) would be applied.`);
116
- } else {
117
- console.log(`\nApplied ${totalApplied} migration(s).`);
118
- }
119
- }
120
-
121
- export async function runDbMigrateStatus(opts: MigrateStatusOpts): Promise<void> {
122
- const found = findProjectConfig();
123
- if (!found) fail('No linked project. Run `ductape link` from your project directory.');
124
-
125
- const { dir } = found;
126
- const session = requireSession();
127
- const proxy = getDbProxy(session);
128
- const envSlug = opts.env ?? session.project.env_slug;
129
- const productTag = session.project.product_tag;
130
-
131
- const schemaEntries = loadSchemaFile(dir);
132
- const targets = opts.db ? schemaEntries.filter((e) => e.db === opts.db) : schemaEntries;
133
-
134
- const statusReport: Record<string, { applied: string[]; pending: string[] }> = {};
135
-
136
- for (const entry of targets) {
137
- const { db } = entry;
138
- const dbContext = buildDbContext(db, envSlug, productTag);
139
- const migrations = loadMigrationFiles(dir, db);
140
- const appliedTags = await getAppliedTags(proxy, dbContext);
141
-
142
- const applied = migrations.filter((m) => appliedTags.includes(m.tag)).map((m) => m.tag);
143
- const pending = migrations.filter((m) => !appliedTags.includes(m.tag)).map((m) => m.tag);
144
-
145
- statusReport[db] = { applied, pending };
146
-
147
- if (!opts.json) {
148
- console.log(`\n[${db}]`);
149
- if (applied.length > 0) {
150
- console.log(` Applied (${applied.length}):`);
151
- for (const t of applied) console.log(` + ${t}`);
152
- }
153
- if (pending.length > 0) {
154
- console.log(` Pending (${pending.length}):`);
155
- for (const t of pending) console.log(` - ${t}`);
156
- }
157
- if (applied.length === 0 && pending.length === 0) {
158
- console.log(' No migration files found.');
159
- }
160
- }
161
- }
162
-
163
- if (opts.json) printJson(statusReport, true);
164
- }
165
-
166
- export async function runDbMigrateRollback(opts: MigrateRollbackOpts): Promise<void> {
167
- const found = findProjectConfig();
168
- if (!found) fail('No linked project. Run `ductape link` from your project directory.');
169
-
170
- const { dir } = found;
171
- const session = requireSession();
172
- const proxy = getDbProxy(session);
173
- const envSlug = opts.env ?? session.project.env_slug;
174
- const productTag = session.project.product_tag;
175
- const rollbackCount = opts.n ?? 1;
176
-
177
- const schemaEntries = loadSchemaFile(dir);
178
- const targets = opts.db ? schemaEntries.filter((e) => e.db === opts.db) : schemaEntries;
179
-
180
- for (const entry of targets) {
181
- const { db } = entry;
182
- const dbContext = buildDbContext(db, envSlug, productTag);
183
- const migrations = loadMigrationFiles(dir, db);
184
- const appliedTags = await getAppliedTags(proxy, dbContext);
185
-
186
- const applied = migrations.filter((m) => appliedTags.includes(m.tag));
187
- const toRollback = applied.slice(-rollbackCount).reverse();
188
-
189
- if (toRollback.length === 0) {
190
- console.log(`[${db}] Nothing to roll back.`);
191
- continue;
192
- }
193
-
194
- for (const migration of toRollback) {
195
- process.stdout.write(` Rolling back ${migration.tag}... `);
196
- try {
197
- await proxy.execute(
198
- 'migration.rollback',
199
- [[migration], 1],
200
- dbContext,
201
- );
202
- console.log('done');
203
- } catch (err) {
204
- console.log('failed');
205
- fail(`Rollback of "${migration.tag}" failed: ${err instanceof Error ? err.message : String(err)}`);
206
- }
207
- }
208
- }
209
- }