@ductape/cli 0.2.23 → 0.3.1

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 (104) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +7 -0
  3. package/dist/commands/db-migrate.js +47 -8
  4. package/dist/commands/migrate-codebase.d.ts +190 -0
  5. package/dist/commands/migrate-codebase.js +776 -0
  6. package/dist/commands/migration-artifact.d.ts +28 -0
  7. package/dist/commands/migration-artifact.js +101 -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-capabilities.d.ts +53 -0
  11. package/dist/commands/migration-capabilities.js +66 -0
  12. package/dist/commands/migration-database.d.ts +26 -0
  13. package/dist/commands/migration-database.js +162 -0
  14. package/dist/commands/migration-e2e.d.ts +68 -0
  15. package/dist/commands/migration-e2e.js +189 -0
  16. package/dist/commands/migration-environments.d.ts +20 -0
  17. package/dist/commands/migration-environments.js +58 -0
  18. package/dist/commands/migration-generated.d.ts +68 -0
  19. package/dist/commands/migration-generated.js +217 -0
  20. package/dist/commands/migration-portfolio.d.ts +88 -0
  21. package/dist/commands/migration-portfolio.js +223 -0
  22. package/dist/commands/migration-products.d.ts +23 -0
  23. package/dist/commands/migration-products.js +88 -0
  24. package/dist/commands/migration-review.d.ts +248 -0
  25. package/dist/commands/migration-review.js +624 -0
  26. package/dist/commands/migration-secrets.d.ts +24 -0
  27. package/dist/commands/migration-secrets.js +93 -0
  28. package/dist/commands/migration-slice.d.ts +132 -0
  29. package/dist/commands/migration-slice.js +266 -0
  30. package/dist/commands/migration-verification.d.ts +12 -0
  31. package/dist/commands/migration-verification.js +194 -0
  32. package/dist/commands/products.d.ts +1 -0
  33. package/dist/commands/products.js +33 -1
  34. package/dist/commands/secrets.d.ts +8 -0
  35. package/dist/commands/secrets.js +44 -0
  36. package/dist/index.js +376 -4
  37. package/dist/lib/migration-artifact.d.ts +19 -0
  38. package/dist/lib/migration-artifact.js +114 -0
  39. package/package.json +8 -1
  40. package/API_PARITY.md +0 -58
  41. package/DB_MIGRATE_PLAN.md +0 -223
  42. package/ductape.example.ts +0 -18
  43. package/src/commands/apply.ts +0 -153
  44. package/src/commands/apps-import.ts +0 -43
  45. package/src/commands/apps.ts +0 -92
  46. package/src/commands/cloud.ts +0 -68
  47. package/src/commands/completion.ts +0 -119
  48. package/src/commands/db-migrate.ts +0 -209
  49. package/src/commands/db-schema.ts +0 -429
  50. package/src/commands/db.ts +0 -63
  51. package/src/commands/generate.ts +0 -74
  52. package/src/commands/graph.ts +0 -51
  53. package/src/commands/init.ts +0 -39
  54. package/src/commands/install.ts +0 -76
  55. package/src/commands/link.ts +0 -84
  56. package/src/commands/login.ts +0 -145
  57. package/src/commands/logout.ts +0 -7
  58. package/src/commands/platform.ts +0 -123
  59. package/src/commands/products.ts +0 -228
  60. package/src/commands/profiles.ts +0 -23
  61. package/src/commands/resources.ts +0 -213
  62. package/src/commands/secrets.ts +0 -46
  63. package/src/commands/unlink.ts +0 -15
  64. package/src/commands/whoami.ts +0 -27
  65. package/src/commands/workspaces.ts +0 -98
  66. package/src/index.ts +0 -523
  67. package/src/lib/api-client.ts +0 -88
  68. package/src/lib/app-import.ts +0 -82
  69. package/src/lib/apply-loaders.ts +0 -30
  70. package/src/lib/config.ts +0 -230
  71. package/src/lib/context-store.ts +0 -77
  72. package/src/lib/db-methods.ts +0 -56
  73. package/src/lib/db-types.ts +0 -104
  74. package/src/lib/encryption.ts +0 -12
  75. package/src/lib/forms/enums.ts +0 -52
  76. package/src/lib/forms/index.ts +0 -8
  77. package/src/lib/forms/prompt.ts +0 -209
  78. package/src/lib/forms/schemas.ts +0 -288
  79. package/src/lib/forms/types.ts +0 -27
  80. package/src/lib/http.ts +0 -76
  81. package/src/lib/integrations.ts +0 -110
  82. package/src/lib/interactive-opts.ts +0 -13
  83. package/src/lib/migration-files.ts +0 -58
  84. package/src/lib/output.ts +0 -39
  85. package/src/lib/platform-api.ts +0 -209
  86. package/src/lib/proxy/context.ts +0 -94
  87. package/src/lib/proxy/db-proxy.ts +0 -40
  88. package/src/lib/proxy/graph-proxy.ts +0 -64
  89. package/src/lib/proxy/sdk-proxy.ts +0 -58
  90. package/src/lib/read-body.ts +0 -57
  91. package/src/lib/resources.ts +0 -160
  92. package/src/lib/schema-loader.ts +0 -152
  93. package/src/lib/snippets.ts +0 -165
  94. package/src/lib/templates.ts +0 -157
  95. package/src/lib/workspace-context.ts +0 -43
  96. package/src/lib/workspaces.ts +0 -283
  97. package/test/apply-loaders.test.ts +0 -40
  98. package/test/encryption.test.ts +0 -20
  99. package/test/forms.test.ts +0 -25
  100. package/test/http.test.ts +0 -15
  101. package/test/platform-api.test.ts +0 -42
  102. package/test/resources.test.ts +0 -23
  103. package/test/workspace-resolve.test.ts +0 -29
  104. 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
- }