@ldsg/cli 0.3.31 → 0.3.33

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 (70) hide show
  1. package/.rush/temp/package-deps_build.json +27 -27
  2. package/.rush/temp/shrinkwrap-deps.json +58 -3
  3. package/.tsbuildinfo +1 -1
  4. package/CHANGELOG.json +52 -0
  5. package/CHANGELOG.md +15 -1
  6. package/README.md +5 -2
  7. package/dist/__tests__/commands.test.js +104 -104
  8. package/dist/__tests__/formatter.test.js +66 -63
  9. package/dist/__tests__/formatter.test.js.map +1 -1
  10. package/dist/__tests__/json-file-mutator.test.js +48 -45
  11. package/dist/__tests__/json-file-mutator.test.js.map +1 -1
  12. package/dist/__tests__/source-resolver.test.js +39 -39
  13. package/dist/cli.js +89 -89
  14. package/dist/cli.js.map +1 -1
  15. package/dist/commands/resource/convert.d.ts +1 -1
  16. package/dist/commands/resource/convert.js +9 -7
  17. package/dist/commands/resource/convert.js.map +1 -1
  18. package/dist/commands/resource/create.d.ts +2 -2
  19. package/dist/commands/resource/create.js +5 -5
  20. package/dist/commands/resource/delete.d.ts +2 -2
  21. package/dist/commands/resource/delete.js.map +1 -1
  22. package/dist/commands/resource/diff.d.ts +2 -2
  23. package/dist/commands/resource/diff.js +8 -8
  24. package/dist/commands/resource/get.d.ts +1 -1
  25. package/dist/commands/resource/list.d.ts +2 -2
  26. package/dist/commands/resource/list.js +11 -11
  27. package/dist/commands/resource/list.js.map +1 -1
  28. package/dist/commands/resource/tree.d.ts +1 -1
  29. package/dist/commands/resource/update.d.ts +2 -2
  30. package/dist/commands/resource/update.js +1 -1
  31. package/dist/constants.js +2 -2
  32. package/dist/types/get-extend-app-data-params.d.ts +2 -2
  33. package/dist/types/resource-record.d.ts +2 -2
  34. package/dist/utils/formatter.d.ts +1 -1
  35. package/dist/utils/formatter.js +25 -25
  36. package/dist/utils/get-extend-app-data-params-using-npm-ldsg-module.d.ts +1 -1
  37. package/dist/utils/get-extend-app-data-params-using-npm-ldsg-module.js +12 -12
  38. package/dist/utils/get-extend-app-data-params-using-npm-ldsg-module.js.map +1 -1
  39. package/dist/utils/get-extend-app-data-params-using-workspace-ldsg-module/index.d.ts +1 -1
  40. package/dist/utils/get-extend-app-data-params-using-workspace-ldsg-module/index.js +20 -20
  41. package/dist/utils/get-extend-app-data-params-using-workspace-ldsg-module/index.js.map +1 -1
  42. package/dist/utils/json-file-mutator.d.ts +2 -2
  43. package/dist/utils/json-file-mutator.js +4 -4
  44. package/dist/utils/json-file-mutator.js.map +1 -1
  45. package/dist/utils/source-resolver.d.ts +1 -1
  46. package/dist/utils/source-resolver.js +15 -15
  47. package/dist/utils/source-resolver.js.map +1 -1
  48. package/jest.config.js +8 -8
  49. package/package.json +13 -10
  50. package/src/__tests__/commands.test.ts +116 -116
  51. package/src/__tests__/formatter.test.ts +68 -65
  52. package/src/__tests__/json-file-mutator.test.ts +57 -52
  53. package/src/__tests__/source-resolver.test.ts +43 -43
  54. package/src/cli.ts +132 -114
  55. package/src/commands/resource/convert.ts +13 -11
  56. package/src/commands/resource/create.ts +8 -8
  57. package/src/commands/resource/delete.ts +6 -4
  58. package/src/commands/resource/diff.ts +10 -10
  59. package/src/commands/resource/get.ts +2 -2
  60. package/src/commands/resource/list.ts +20 -18
  61. package/src/commands/resource/tree.ts +2 -2
  62. package/src/commands/resource/update.ts +4 -4
  63. package/src/constants.ts +2 -2
  64. package/src/types/get-extend-app-data-params.ts +5 -3
  65. package/src/types/resource-record.ts +2 -2
  66. package/src/utils/formatter.ts +27 -27
  67. package/src/utils/get-extend-app-data-params-using-npm-ldsg-module.ts +20 -16
  68. package/src/utils/get-extend-app-data-params-using-workspace-ldsg-module/index.ts +28 -26
  69. package/src/utils/json-file-mutator.ts +18 -12
  70. package/src/utils/source-resolver.ts +26 -21
package/src/cli.ts CHANGED
@@ -1,51 +1,57 @@
1
1
  #!/usr/bin/env node
2
- import { readFileSync } from 'fs';
3
- import { join } from 'path';
4
- import { convertApaasResourceRecordsToResourceRecords } from '@ldsg/apaas-to-runtime';
5
- import { AppData } from '@ldsg/types';
2
+ import { readFileSync } from "fs";
3
+ import { join } from "path";
4
+ import { convertApaasResourceRecordsToResourceRecords } from "@ldsg/apaas-to-runtime";
5
+ import { AppData } from "@ldsg/types";
6
6
  import {
7
7
  extendAppData,
8
8
  ExtendAppDataParams,
9
9
  loadAppResourceRecords,
10
10
  prepare,
11
- ZipAppDataLayout
12
- } from '@ldsg/utils';
13
- import { Command } from 'commander';
14
- import { DEFAULT_OUTPUT_PATH, DEFAULT_SOURCE_FILE, DEFAULT_SOURCE_PATH } from './constants';
15
- import { getExtendAppDataParamsUsingNpmLdsgModule } from './utils/get-extend-app-data-params-using-npm-ldsg-module';
16
- import { getExtendAppDataParamsUsingWorkspaceLdsgModule } from './utils/get-extend-app-data-params-using-workspace-ldsg-module';
17
- import { resolveSource, isStdinSource, getSourceDescription } from './utils/source-resolver';
11
+ ZipAppDataLayout,
12
+ } from "@ldsg/utils";
13
+ import { Command } from "commander";
14
+ import { DEFAULT_OUTPUT_PATH, DEFAULT_SOURCE_FILE, DEFAULT_SOURCE_PATH } from "./constants";
15
+ import { getExtendAppDataParamsUsingNpmLdsgModule } from "./utils/get-extend-app-data-params-using-npm-ldsg-module";
16
+ import { getExtendAppDataParamsUsingWorkspaceLdsgModule } from "./utils/get-extend-app-data-params-using-workspace-ldsg-module";
17
+ import { resolveSource, isStdinSource, getSourceDescription } from "./utils/source-resolver";
18
18
  import {
19
19
  formatSuccess,
20
20
  formatError,
21
21
  formatJson,
22
22
  formatPrettyList,
23
23
  formatPrettyTree,
24
- formatPrettyDiff
25
- } from './utils/formatter';
26
- import { createResource } from './commands/resource/create';
27
- import { updateResource } from './commands/resource/update';
28
- import { deleteResource } from './commands/resource/delete';
29
- import { listResources, getTree } from './commands/resource/list';
30
- import { getResource } from './commands/resource/get';
31
- import { convertResource } from './commands/resource/convert';
32
- import { diffResource } from './commands/resource/diff';
33
-
34
- const { version } = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
24
+ formatPrettyDiff,
25
+ } from "./utils/formatter";
26
+ import { createResource } from "./commands/resource/create";
27
+ import { updateResource } from "./commands/resource/update";
28
+ import { deleteResource } from "./commands/resource/delete";
29
+ import { listResources, getTree } from "./commands/resource/list";
30
+ import { getResource } from "./commands/resource/get";
31
+ import { convertResource } from "./commands/resource/convert";
32
+ import { diffResource } from "./commands/resource/diff";
33
+
34
+ const { version } = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8"));
35
35
 
36
36
  const program = new Command();
37
37
 
38
- program.name('ldsg').description('LDSG CLI tools').version(version);
38
+ program.name("ldsg").description("LDSG CLI tools").version(version);
39
39
 
40
40
  program
41
- .command('generate')
42
- .aliases(['g', 'gen'])
43
- .description('Generate standalone application from resource records')
44
- .option('--app-data-uri <uri>', 'runtime app data URI')
45
- .option('--apaas-app-data-uri <uri>', 'aPaaS app data URI (GraphQL)')
46
- .option('--apaas-app-data-expression <expression>', 'JSONata expression for aPaaS data extraction')
47
- .option('--using-workspace-ldsg-module', 'use workspace ldsg module mode')
48
- .option('-o, --output <path>', `output directory for prepared app code (default: ${DEFAULT_OUTPUT_PATH})`)
41
+ .command("generate")
42
+ .aliases(["g", "gen"])
43
+ .description("Generate standalone application from resource records")
44
+ .option("--app-data-uri <uri>", "runtime app data URI")
45
+ .option("--apaas-app-data-uri <uri>", "aPaaS app data URI (GraphQL)")
46
+ .option(
47
+ "--apaas-app-data-expression <expression>",
48
+ "JSONata expression for aPaaS data extraction",
49
+ )
50
+ .option("--using-workspace-ldsg-module", "use workspace ldsg module mode")
51
+ .option(
52
+ "-o, --output <path>",
53
+ `output directory for prepared app code (default: ${DEFAULT_OUTPUT_PATH})`,
54
+ )
49
55
  .action(async (options) => {
50
56
  const outputPath = options.output || DEFAULT_OUTPUT_PATH;
51
57
 
@@ -54,14 +60,14 @@ program
54
60
  const { resourceRecords, sourceType } = await loadAppResourceRecords({
55
61
  appDataUri: options.appDataUri,
56
62
  apaasAppDataUri: options.apaasAppDataUri,
57
- apaasAppDataExpression: options.apaasAppDataExpression
63
+ apaasAppDataExpression: options.apaasAppDataExpression,
58
64
  });
59
65
 
60
66
  let appData: AppData;
61
67
 
62
- if (sourceType === 'apaas') {
68
+ if (sourceType === "apaas") {
63
69
  const { targetResourceRecords } = convertApaasResourceRecordsToResourceRecords({
64
- resourceRecords
70
+ resourceRecords,
65
71
  });
66
72
  appData = { resourceRecords: targetResourceRecords };
67
73
  } else {
@@ -81,20 +87,20 @@ program
81
87
  await prepare({
82
88
  ...extendAppDataRes,
83
89
  outputPath,
84
- ...(usingWorkspaceLdsgModule ? { layout: ZipAppDataLayout.FLAT } : {})
90
+ ...(usingWorkspaceLdsgModule ? { layout: ZipAppDataLayout.FLAT } : {}),
85
91
  });
86
92
  });
87
93
 
88
- const resource = program.command('resource').aliases(['r']).description('Manage resource records');
94
+ const resource = program.command("resource").aliases(["r"]).description("Manage resource records");
89
95
 
90
96
  resource
91
- .command('list')
92
- .description('List resource records by filter')
93
- .option('--source <path>', `data source (default: ${DEFAULT_SOURCE_PATH})`)
94
- .option('--kind <kind>', 'filter by resource kind')
95
- .option('--parent-id <id>', 'filter by parent id')
96
- .option('--root-id <id>', 'filter by root resource id')
97
- .option('--pretty', 'human-readable output')
97
+ .command("list")
98
+ .description("List resource records by filter")
99
+ .option("--source <path>", `data source (default: ${DEFAULT_SOURCE_PATH})`)
100
+ .option("--kind <kind>", "filter by resource kind")
101
+ .option("--parent-id <id>", "filter by parent id")
102
+ .option("--root-id <id>", "filter by root resource id")
103
+ .option("--pretty", "human-readable output")
98
104
  .action(async (options) => {
99
105
  try {
100
106
  const sourceDesc = getSourceDescription(options.source);
@@ -102,7 +108,7 @@ resource
102
108
  const { total, resources } = await listResources(sourceData.resourceRecords, {
103
109
  kind: options.kind,
104
110
  parentId: options.parentId,
105
- rootId: options.rootId
111
+ rootId: options.rootId,
106
112
  });
107
113
 
108
114
  if (options.pretty) {
@@ -112,37 +118,37 @@ resource
112
118
  id: r.id,
113
119
  kind: r.kind,
114
120
  parentId: r.parentId,
115
- title: (r.settings as Record<string, unknown>)?.title as string | undefined
116
- }))
117
- )
121
+ title: (r.settings as Record<string, unknown>)?.title as string | undefined,
122
+ })),
123
+ ),
118
124
  );
119
125
  } else {
120
126
  console.log(formatJson(formatSuccess({ source: sourceDesc, total, resources })));
121
127
  }
122
128
  } catch (error) {
123
- console.error(formatJson(formatError('LIST_ERROR', (error as Error).message)));
129
+ console.error(formatJson(formatError("LIST_ERROR", (error as Error).message)));
124
130
  process.exit(1);
125
131
  }
126
132
  });
127
133
 
128
134
  resource
129
- .command('get <id>')
130
- .description('Get a resource record by id')
131
- .option('--source <path>', `data source (default: ${DEFAULT_SOURCE_PATH})`)
132
- .option('--children', 'include direct children')
133
- .option('--tree', 'include full subtree')
134
- .option('--pretty', 'human-readable output')
135
+ .command("get <id>")
136
+ .description("Get a resource record by id")
137
+ .option("--source <path>", `data source (default: ${DEFAULT_SOURCE_PATH})`)
138
+ .option("--children", "include direct children")
139
+ .option("--tree", "include full subtree")
140
+ .option("--pretty", "human-readable output")
135
141
  .action(async (id, options) => {
136
142
  try {
137
143
  const sourceDesc = getSourceDescription(options.source);
138
144
  const sourceData = await resolveSource(options.source);
139
145
  const record = await getResource(sourceData.resourceRecords, id, {
140
146
  children: options.children,
141
- tree: options.tree
147
+ tree: options.tree,
142
148
  });
143
149
 
144
150
  if (!record) {
145
- console.error(formatJson(formatError('NOT_FOUND', `Resource with id "${id}" not found`)));
151
+ console.error(formatJson(formatError("NOT_FOUND", `Resource with id "${id}" not found`)));
146
152
  process.exit(1);
147
153
  }
148
154
 
@@ -152,17 +158,17 @@ resource
152
158
  console.log(formatJson(formatSuccess({ source: sourceDesc, record })));
153
159
  }
154
160
  } catch (error) {
155
- console.error(formatJson(formatError('GET_ERROR', (error as Error).message)));
161
+ console.error(formatJson(formatError("GET_ERROR", (error as Error).message)));
156
162
  process.exit(1);
157
163
  }
158
164
  });
159
165
 
160
166
  resource
161
- .command('tree [root-id]')
162
- .description('Display resource tree')
163
- .option('--source <path>', `data source (default: ${DEFAULT_SOURCE_PATH})`)
164
- .option('--show-kind', 'show resource kind prefix')
165
- .option('--pretty', 'human-readable output')
167
+ .command("tree [root-id]")
168
+ .description("Display resource tree")
169
+ .option("--source <path>", `data source (default: ${DEFAULT_SOURCE_PATH})`)
170
+ .option("--show-kind", "show resource kind prefix")
171
+ .option("--pretty", "human-readable output")
166
172
  .action(async (rootId, options) => {
167
173
  try {
168
174
  const sourceDesc = getSourceDescription(options.source);
@@ -175,26 +181,28 @@ resource
175
181
  console.log(formatJson(formatSuccess({ source: sourceDesc, ...result })));
176
182
  }
177
183
  } catch (error) {
178
- console.error(formatJson(formatError('TREE_ERROR', (error as Error).message)));
184
+ console.error(formatJson(formatError("TREE_ERROR", (error as Error).message)));
179
185
  process.exit(1);
180
186
  }
181
187
  });
182
188
 
183
189
  resource
184
- .command('create')
185
- .description('Create a new resource record')
186
- .option('--source <path>', `data source (default: ${DEFAULT_SOURCE_PATH})`)
187
- .option('--kind <kind>', 'resource kind')
188
- .option('--parent-id <id>', 'parent resource id')
189
- .option('--settings <json>', 'resource settings as JSON string')
190
- .option('--from-file <path>', 'read full resource record from JSON file')
191
- .option('--from-stdin', 'read full resource record from stdin')
192
- .option('--dry-run', 'preview without writing')
190
+ .command("create")
191
+ .description("Create a new resource record")
192
+ .option("--source <path>", `data source (default: ${DEFAULT_SOURCE_PATH})`)
193
+ .option("--kind <kind>", "resource kind")
194
+ .option("--parent-id <id>", "parent resource id")
195
+ .option("--settings <json>", "resource settings as JSON string")
196
+ .option("--from-file <path>", "read full resource record from JSON file")
197
+ .option("--from-stdin", "read full resource record from stdin")
198
+ .option("--dry-run", "preview without writing")
193
199
  .action(async (options) => {
194
200
  try {
195
201
  if (isStdinSource(options.source)) {
196
202
  console.error(
197
- formatJson(formatError('STDIN_NOT_WRITABLE', 'stdin source does not support write operations'))
203
+ formatJson(
204
+ formatError("STDIN_NOT_WRITABLE", "stdin source does not support write operations"),
205
+ ),
198
206
  );
199
207
  process.exit(1);
200
208
  }
@@ -204,15 +212,15 @@ resource
204
212
  let fromFileRecord: Record<string, unknown> | undefined;
205
213
 
206
214
  if (options.fromFile) {
207
- const fs = await import('fs-extra');
215
+ const fs = await import("fs-extra");
208
216
  fromFileRecord = await fs.readJson(options.fromFile);
209
217
  } else if (options.fromStdin) {
210
218
  const chunks: Buffer[] = [];
211
- process.stdin.setEncoding('utf-8');
219
+ process.stdin.setEncoding("utf-8");
212
220
  for await (const chunk of process.stdin) {
213
221
  chunks.push(Buffer.from(chunk));
214
222
  }
215
- const raw = Buffer.concat(chunks).toString('utf-8');
223
+ const raw = Buffer.concat(chunks).toString("utf-8");
216
224
  fromFileRecord = JSON.parse(raw);
217
225
  }
218
226
 
@@ -227,27 +235,29 @@ resource
227
235
  parentId: options.parentId,
228
236
  settings,
229
237
  fromFileRecord: fromFileRecord as never,
230
- dryRun: options.dryRun
238
+ dryRun: options.dryRun,
231
239
  });
232
240
 
233
241
  console.log(formatJson(formatSuccess({ record, dryRun: options.dryRun ?? false })));
234
242
  } catch (error) {
235
- console.error(formatJson(formatError('CREATE_ERROR', (error as Error).message)));
243
+ console.error(formatJson(formatError("CREATE_ERROR", (error as Error).message)));
236
244
  process.exit(1);
237
245
  }
238
246
  });
239
247
 
240
248
  resource
241
- .command('update <id>')
242
- .description('Update a resource record')
243
- .option('--source <path>', `data source (default: ${DEFAULT_SOURCE_PATH})`)
244
- .option('--settings <json>', 'resource settings to merge (JSON string, required)')
245
- .option('--dry-run', 'preview without writing')
249
+ .command("update <id>")
250
+ .description("Update a resource record")
251
+ .option("--source <path>", `data source (default: ${DEFAULT_SOURCE_PATH})`)
252
+ .option("--settings <json>", "resource settings to merge (JSON string, required)")
253
+ .option("--dry-run", "preview without writing")
246
254
  .action(async (id, options) => {
247
255
  try {
248
256
  if (isStdinSource(options.source)) {
249
257
  console.error(
250
- formatJson(formatError('STDIN_NOT_WRITABLE', 'stdin source does not support write operations'))
258
+ formatJson(
259
+ formatError("STDIN_NOT_WRITABLE", "stdin source does not support write operations"),
260
+ ),
251
261
  );
252
262
  process.exit(1);
253
263
  }
@@ -255,7 +265,9 @@ resource
255
265
  const sourceData = await resolveSource(options.source);
256
266
 
257
267
  if (!options.settings) {
258
- console.error(formatJson(formatError('MISSING_SETTINGS', 'Required option: --settings <json>')));
268
+ console.error(
269
+ formatJson(formatError("MISSING_SETTINGS", "Required option: --settings <json>")),
270
+ );
259
271
  process.exit(1);
260
272
  }
261
273
 
@@ -264,26 +276,28 @@ resource
264
276
  sourceData,
265
277
  id,
266
278
  settings,
267
- dryRun: options.dryRun
279
+ dryRun: options.dryRun,
268
280
  });
269
281
 
270
282
  console.log(formatJson(formatSuccess({ record, dryRun: options.dryRun ?? false })));
271
283
  } catch (error) {
272
- console.error(formatJson(formatError('UPDATE_ERROR', (error as Error).message)));
284
+ console.error(formatJson(formatError("UPDATE_ERROR", (error as Error).message)));
273
285
  process.exit(1);
274
286
  }
275
287
  });
276
288
 
277
289
  resource
278
- .command('delete <id>')
279
- .description('Delete a resource record and its children')
280
- .option('--source <path>', `data source (default: ${DEFAULT_SOURCE_PATH})`)
281
- .option('--dry-run', 'preview deletion scope without writing')
290
+ .command("delete <id>")
291
+ .description("Delete a resource record and its children")
292
+ .option("--source <path>", `data source (default: ${DEFAULT_SOURCE_PATH})`)
293
+ .option("--dry-run", "preview deletion scope without writing")
282
294
  .action(async (id, options) => {
283
295
  try {
284
296
  if (isStdinSource(options.source)) {
285
297
  console.error(
286
- formatJson(formatError('STDIN_NOT_WRITABLE', 'stdin source does not support write operations'))
298
+ formatJson(
299
+ formatError("STDIN_NOT_WRITABLE", "stdin source does not support write operations"),
300
+ ),
287
301
  );
288
302
  process.exit(1);
289
303
  }
@@ -292,7 +306,7 @@ resource
292
306
  const { removed } = await deleteResource({
293
307
  sourceData,
294
308
  id,
295
- dryRun: options.dryRun
309
+ dryRun: options.dryRun,
296
310
  });
297
311
 
298
312
  console.log(
@@ -300,27 +314,29 @@ resource
300
314
  formatSuccess({
301
315
  dryRun: options.dryRun ?? false,
302
316
  removedCount: removed.length,
303
- removed: removed.map((r) => ({ id: r.id, kind: r.kind }))
304
- })
305
- )
317
+ removed: removed.map((r) => ({ id: r.id, kind: r.kind })),
318
+ }),
319
+ ),
306
320
  );
307
321
  } catch (error) {
308
- console.error(formatJson(formatError('DELETE_ERROR', (error as Error).message)));
322
+ console.error(formatJson(formatError("DELETE_ERROR", (error as Error).message)));
309
323
  process.exit(1);
310
324
  }
311
325
  });
312
326
 
313
327
  resource
314
- .command('convert')
315
- .description('Convert resource records between aPaaS and Runtime formats')
316
- .option('--from <format>', 'source format (apaas or runtime)')
317
- .option('--to <format>', 'target format (apaas or runtime)')
318
- .option('--input <path>', 'input file path')
319
- .option('--output <path>', 'output file path (omit for stdout)')
328
+ .command("convert")
329
+ .description("Convert resource records between aPaaS and Runtime formats")
330
+ .option("--from <format>", "source format (apaas or runtime)")
331
+ .option("--to <format>", "target format (apaas or runtime)")
332
+ .option("--input <path>", "input file path")
333
+ .option("--output <path>", "output file path (omit for stdout)")
320
334
  .action(async (options) => {
321
335
  try {
322
336
  if (!options.from || !options.to || !options.input) {
323
- console.error(formatJson(formatError('MISSING_ARGS', 'Required options: --from, --to, --input')));
337
+ console.error(
338
+ formatJson(formatError("MISSING_ARGS", "Required options: --from, --to, --input")),
339
+ );
324
340
  process.exit(1);
325
341
  }
326
342
 
@@ -328,7 +344,7 @@ resource
328
344
  from: options.from,
329
345
  to: options.to,
330
346
  input: options.input,
331
- output: options.output
347
+ output: options.output,
332
348
  });
333
349
 
334
350
  if (result.outputPath) {
@@ -337,21 +353,23 @@ resource
337
353
  console.log(formatJson(formatSuccess({ data: result.data })));
338
354
  }
339
355
  } catch (error) {
340
- console.error(formatJson(formatError('CONVERT_ERROR', (error as Error).message)));
356
+ console.error(formatJson(formatError("CONVERT_ERROR", (error as Error).message)));
341
357
  process.exit(1);
342
358
  }
343
359
  });
344
360
 
345
361
  resource
346
- .command('diff <id>')
347
- .description('Diff a resource between two sources')
348
- .option('--source-a <path>', 'first source file (required)')
349
- .option('--source-b <path>', 'second source file (required)')
350
- .option('--pretty', 'human-readable output')
362
+ .command("diff <id>")
363
+ .description("Diff a resource between two sources")
364
+ .option("--source-a <path>", "first source file (required)")
365
+ .option("--source-b <path>", "second source file (required)")
366
+ .option("--pretty", "human-readable output")
351
367
  .action(async (id, options) => {
352
368
  try {
353
369
  if (!options.sourceA || !options.sourceB) {
354
- console.error(formatJson(formatError('MISSING_ARGS', 'Required options: --source-a, --source-b')));
370
+ console.error(
371
+ formatJson(formatError("MISSING_ARGS", "Required options: --source-a, --source-b")),
372
+ );
355
373
  process.exit(1);
356
374
  }
357
375
 
@@ -363,7 +381,7 @@ resource
363
381
  sourceB: getSourceDescription(options.sourceB),
364
382
  id,
365
383
  recordsA: sourceDataA.resourceRecords,
366
- recordsB: sourceDataB.resourceRecords
384
+ recordsB: sourceDataB.resourceRecords,
367
385
  });
368
386
 
369
387
  if (options.pretty) {
@@ -372,7 +390,7 @@ resource
372
390
  console.log(formatJson(formatSuccess(result)));
373
391
  }
374
392
  } catch (error) {
375
- console.error(formatJson(formatError('DIFF_ERROR', (error as Error).message)));
393
+ console.error(formatJson(formatError("DIFF_ERROR", (error as Error).message)));
376
394
  process.exit(1);
377
395
  }
378
396
  });
@@ -1,6 +1,6 @@
1
- import fs from 'fs-extra';
2
- import { convertApaasResourceRecordsToResourceRecords } from '@ldsg/apaas-to-runtime';
3
- import { ResourceRecords } from '@ldsg/types';
1
+ import fs from "fs-extra";
2
+ import { convertApaasResourceRecordsToResourceRecords } from "@ldsg/apaas-to-runtime";
3
+ import { ResourceRecords } from "@ldsg/types";
4
4
 
5
5
  export interface ConvertOptions {
6
6
  from: string;
@@ -10,15 +10,15 @@ export interface ConvertOptions {
10
10
  }
11
11
 
12
12
  export async function convertResource(
13
- options: ConvertOptions
13
+ options: ConvertOptions,
14
14
  ): Promise<{ outputPath?: string; data: ResourceRecords }> {
15
15
  const { from, to, input, output } = options;
16
16
 
17
- if (from === 'runtime' && to === 'apaas') {
18
- throw new Error('Runtime → aPaaS conversion is not supported yet');
17
+ if (from === "runtime" && to === "apaas") {
18
+ throw new Error("Runtime → aPaaS conversion is not supported yet");
19
19
  }
20
20
 
21
- if (from !== 'apaas' || to !== 'runtime') {
21
+ if (from !== "apaas" || to !== "runtime") {
22
22
  throw new Error(`Unsupported conversion: ${from} → ${to}`);
23
23
  }
24
24
 
@@ -31,19 +31,21 @@ export async function convertResource(
31
31
 
32
32
  if (Array.isArray(rawData)) {
33
33
  resourceRecords = rawData as ResourceRecords;
34
- } else if (rawData && typeof rawData === 'object' && Array.isArray(rawData.resourceRecords)) {
34
+ } else if (rawData && typeof rawData === "object" && Array.isArray(rawData.resourceRecords)) {
35
35
  resourceRecords = rawData.resourceRecords as ResourceRecords;
36
36
  } else {
37
- throw new Error('Invalid input format: expected an array or { resourceRecords: [] }');
37
+ throw new Error("Invalid input format: expected an array or { resourceRecords: [] }");
38
38
  }
39
39
 
40
40
  const { targetResourceRecords } = convertApaasResourceRecordsToResourceRecords({
41
- resourceRecords
41
+ resourceRecords,
42
42
  });
43
43
 
44
44
  if (output) {
45
45
  const isArrayInput = Array.isArray(rawData);
46
- const outputData = isArrayInput ? targetResourceRecords : { resourceRecords: targetResourceRecords };
46
+ const outputData = isArrayInput
47
+ ? targetResourceRecords
48
+ : { resourceRecords: targetResourceRecords };
47
49
  await fs.writeJson(output, outputData, { spaces: 2 });
48
50
  return { outputPath: output, data: targetResourceRecords };
49
51
  }
@@ -1,6 +1,6 @@
1
- import { ResourceRecord } from '@ldsg/types';
2
- import { SourceData } from '../../types/resource-record';
3
- import { appendRecord, generateId } from '../../utils/json-file-mutator';
1
+ import { ResourceRecord } from "@ldsg/types";
2
+ import { SourceData } from "../../types/resource-record";
3
+ import { appendRecord, generateId } from "../../utils/json-file-mutator";
4
4
 
5
5
  export interface CreateOptions {
6
6
  sourceData: SourceData;
@@ -20,27 +20,27 @@ export async function createResource(options: CreateOptions): Promise<{ record:
20
20
  if (options.fromFileRecord) {
21
21
  const partial = options.fromFileRecord;
22
22
  if (!partial.kind) {
23
- throw new Error('Missing required field: kind');
23
+ throw new Error("Missing required field: kind");
24
24
  }
25
25
  record = {
26
26
  id: partial.id || generateId(),
27
27
  kind: partial.kind,
28
28
  parentId: partial.parentId ?? sourceData.resourceRecords[0]?.parentId ?? null,
29
- settings: (partial.settings || {}) as Record<string, unknown>
29
+ settings: (partial.settings || {}) as Record<string, unknown>,
30
30
  };
31
31
  } else {
32
32
  if (!options.kind) {
33
- throw new Error('Missing required option: --kind');
33
+ throw new Error("Missing required option: --kind");
34
34
  }
35
35
  if (options.parentId === undefined) {
36
- throw new Error('Missing required option: --parent-id');
36
+ throw new Error("Missing required option: --parent-id");
37
37
  }
38
38
 
39
39
  record = {
40
40
  id: options.id || generateId(),
41
41
  kind: options.kind,
42
42
  parentId: options.parentId ?? null,
43
- settings: options.settings || {}
43
+ settings: options.settings || {},
44
44
  };
45
45
  }
46
46
 
@@ -1,6 +1,6 @@
1
- import { ResourceRecord } from '@ldsg/types';
2
- import { SourceData } from '../../types/resource-record';
3
- import { removeRecord } from '../../utils/json-file-mutator';
1
+ import { ResourceRecord } from "@ldsg/types";
2
+ import { SourceData } from "../../types/resource-record";
3
+ import { removeRecord } from "../../utils/json-file-mutator";
4
4
 
5
5
  export interface DeleteOptions {
6
6
  sourceData: SourceData;
@@ -8,7 +8,9 @@ export interface DeleteOptions {
8
8
  dryRun?: boolean;
9
9
  }
10
10
 
11
- export async function deleteResource(options: DeleteOptions): Promise<{ removed: ResourceRecord[] }> {
11
+ export async function deleteResource(
12
+ options: DeleteOptions,
13
+ ): Promise<{ removed: ResourceRecord[] }> {
12
14
  const { sourceData, id, dryRun } = options;
13
15
  const result = await removeRecord(sourceData, id, dryRun);
14
16
  return { removed: result.removed };
@@ -1,8 +1,8 @@
1
- import { ResourceRecords } from '@ldsg/types';
2
- import { DiffResult } from '../../types/resource-record';
1
+ import { ResourceRecords } from "@ldsg/types";
2
+ import { DiffResult } from "../../types/resource-record";
3
3
 
4
4
  function isObject(value: unknown): value is Record<string, unknown> {
5
- return value !== null && typeof value === 'object' && !Array.isArray(value);
5
+ return value !== null && typeof value === "object" && !Array.isArray(value);
6
6
  }
7
7
 
8
8
  interface DiffEntry {
@@ -15,7 +15,7 @@ interface DiffEntry {
15
15
  function deepDiff(
16
16
  objA: Record<string, unknown>,
17
17
  objB: Record<string, unknown>,
18
- basePath = ''
18
+ basePath = "",
19
19
  ): {
20
20
  changed: DiffEntry[];
21
21
  added: DiffEntry[];
@@ -65,14 +65,14 @@ export async function diffResource(options: DiffOptions): Promise<DiffResult> {
65
65
 
66
66
  const result: DiffResult = {
67
67
  id,
68
- kind: (recordA || recordB)?.kind || '',
68
+ kind: (recordA || recordB)?.kind || "",
69
69
  sourceA,
70
70
  sourceB,
71
71
  changed: [],
72
72
  added: [],
73
73
  removed: [],
74
74
  sideA: recordA,
75
- sideB: recordB
75
+ sideB: recordB,
76
76
  };
77
77
 
78
78
  if (!recordA || !recordB) {
@@ -81,17 +81,17 @@ export async function diffResource(options: DiffOptions): Promise<DiffResult> {
81
81
 
82
82
  if (recordA.kind !== recordB.kind) {
83
83
  result.changed.push({
84
- path: 'kind',
84
+ path: "kind",
85
85
  from: recordA.kind,
86
- to: recordB.kind
86
+ to: recordB.kind,
87
87
  });
88
88
  }
89
89
 
90
90
  if (recordA.parentId !== recordB.parentId) {
91
91
  result.changed.push({
92
- path: 'parentId',
92
+ path: "parentId",
93
93
  from: recordA.parentId || null,
94
- to: recordB.parentId || null
94
+ to: recordB.parentId || null,
95
95
  });
96
96
  }
97
97