@datamagik/cli 0.1.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 (86) hide show
  1. package/LICENSE +21 -0
  2. package/assets/dm-script-globals.d.ts +181 -0
  3. package/dist/api.d.ts +247 -0
  4. package/dist/api.js +200 -0
  5. package/dist/api.js.map +1 -0
  6. package/dist/commands/add.d.ts +28 -0
  7. package/dist/commands/add.js +260 -0
  8. package/dist/commands/add.js.map +1 -0
  9. package/dist/commands/dev.d.ts +25 -0
  10. package/dist/commands/dev.js +113 -0
  11. package/dist/commands/dev.js.map +1 -0
  12. package/dist/commands/init.d.ts +23 -0
  13. package/dist/commands/init.js +136 -0
  14. package/dist/commands/init.js.map +1 -0
  15. package/dist/commands/login.d.ts +16 -0
  16. package/dist/commands/login.js +42 -0
  17. package/dist/commands/login.js.map +1 -0
  18. package/dist/commands/publish.d.ts +23 -0
  19. package/dist/commands/publish.js +113 -0
  20. package/dist/commands/publish.js.map +1 -0
  21. package/dist/commands/script.d.ts +69 -0
  22. package/dist/commands/script.js +289 -0
  23. package/dist/commands/script.js.map +1 -0
  24. package/dist/commands/sql.d.ts +28 -0
  25. package/dist/commands/sql.js +124 -0
  26. package/dist/commands/sql.js.map +1 -0
  27. package/dist/commands/typegen.d.ts +13 -0
  28. package/dist/commands/typegen.js +50 -0
  29. package/dist/commands/typegen.js.map +1 -0
  30. package/dist/config.d.ts +45 -0
  31. package/dist/config.js +118 -0
  32. package/dist/config.js.map +1 -0
  33. package/dist/credentials.d.ts +17 -0
  34. package/dist/credentials.js +49 -0
  35. package/dist/credentials.js.map +1 -0
  36. package/dist/index.d.ts +2 -0
  37. package/dist/index.js +268 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/scriptfile.d.ts +10 -0
  40. package/dist/scriptfile.js +91 -0
  41. package/dist/scriptfile.js.map +1 -0
  42. package/dist/sqlfile.d.ts +9 -0
  43. package/dist/sqlfile.js +75 -0
  44. package/dist/sqlfile.js.map +1 -0
  45. package/dist/typegen/emit.d.ts +22 -0
  46. package/dist/typegen/emit.js +255 -0
  47. package/dist/typegen/emit.js.map +1 -0
  48. package/dist/typegen/meta.d.ts +84 -0
  49. package/dist/typegen/meta.js +209 -0
  50. package/dist/typegen/meta.js.map +1 -0
  51. package/package.json +35 -0
  52. package/templates/showcase/README.md +55 -0
  53. package/templates/showcase/_gitignore +4 -0
  54. package/templates/showcase/dm.config.json +16 -0
  55. package/templates/showcase/env.d.ts +7 -0
  56. package/templates/showcase/index.html +12 -0
  57. package/templates/showcase/package.json +25 -0
  58. package/templates/showcase/src/App.vue +67 -0
  59. package/templates/showcase/src/assets/datamagik-logo.png +0 -0
  60. package/templates/showcase/src/components/ShowcasePanel.vue +47 -0
  61. package/templates/showcase/src/components/panels/ContextPanel.vue +35 -0
  62. package/templates/showcase/src/components/panels/NavigatePanel.vue +38 -0
  63. package/templates/showcase/src/components/panels/OutputPanel.vue +50 -0
  64. package/templates/showcase/src/components/panels/PrintPanel.vue +68 -0
  65. package/templates/showcase/src/components/panels/QueryPanel.vue +52 -0
  66. package/templates/showcase/src/components/panels/ScriptPanel.vue +55 -0
  67. package/templates/showcase/src/components/panels/SerialPanel.vue +64 -0
  68. package/templates/showcase/src/dm-script-types.d.ts +13 -0
  69. package/templates/showcase/src/dm.generated.ts +65 -0
  70. package/templates/showcase/src/format.ts +13 -0
  71. package/templates/showcase/src/main.ts +5 -0
  72. package/templates/showcase/src/style.css +134 -0
  73. package/templates/showcase/tsconfig.json +17 -0
  74. package/templates/showcase/vite.config.ts +9 -0
  75. package/templates/simple/README.md +37 -0
  76. package/templates/simple/_gitignore +4 -0
  77. package/templates/simple/dm.config.json +10 -0
  78. package/templates/simple/env.d.ts +7 -0
  79. package/templates/simple/index.html +12 -0
  80. package/templates/simple/package.json +25 -0
  81. package/templates/simple/src/App.vue +71 -0
  82. package/templates/simple/src/dm.generated.ts +32 -0
  83. package/templates/simple/src/main.ts +5 -0
  84. package/templates/simple/src/style.css +63 -0
  85. package/templates/simple/tsconfig.json +17 -0
  86. package/templates/simple/vite.config.ts +9 -0
@@ -0,0 +1,124 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { requireCredentials } from '../credentials.js';
4
+ import { PlatformClient } from '../api.js';
5
+ import { parseSqlFile, serializeSqlFile } from '../sqlfile.js';
6
+ function fileSlug(name) {
7
+ const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
8
+ return slug || 'query';
9
+ }
10
+ function detailToMeta(d) {
11
+ const meta = { name: d.query_name };
12
+ if (d.description)
13
+ meta['description'] = d.description;
14
+ if (d.timeout_seconds)
15
+ meta['timeoutSeconds'] = d.timeout_seconds;
16
+ if (d.credential_name)
17
+ meta['credential'] = d.credential_name;
18
+ if (d.credential_id)
19
+ meta['credentialId'] = d.credential_id;
20
+ if (d.parameters && d.parameters.length)
21
+ meta['parameters'] = d.parameters;
22
+ meta['queryId'] = Number(d.query_id);
23
+ return meta;
24
+ }
25
+ const mstr = (m, k) => (typeof m[k] === 'string' ? m[k] : undefined);
26
+ const mnum = (m, k) => (typeof m[k] === 'number' ? m[k] : undefined);
27
+ function metaParams(m) {
28
+ return Array.isArray(m['parameters']) ? m['parameters'] : [];
29
+ }
30
+ /** `dm sql pull [id]` — write ODBC queries to <dir>/<slug>.sql with frontmatter. */
31
+ export async function pullSqlCommand(opts, deps = {}) {
32
+ const cwd = deps.cwd ?? process.cwd();
33
+ const creds = requireCredentials();
34
+ const client = deps.client ?? new PlatformClient(creds.url, creds.token);
35
+ const outDir = path.resolve(cwd, opts.dir ?? 'sql');
36
+ mkdirSync(outDir, { recursive: true });
37
+ const ids = opts.id !== undefined ? [Number(opts.id)] : (await client.listOdbcQueries()).map((q) => Number(q.query_id));
38
+ if (ids.length === 0) {
39
+ console.log(`No SQL queries found in this tenant (${creds.url}).`);
40
+ return;
41
+ }
42
+ for (const id of ids) {
43
+ const detail = await client.getOdbcQueryDetail(id);
44
+ const file = path.join(outDir, `${fileSlug(detail.query_name)}.sql`);
45
+ writeFileSync(file, serializeSqlFile(detailToMeta(detail), detail.query_text));
46
+ console.log(`Pulled [#${id}] ${detail.query_name} → ${path.relative(cwd, file)}`);
47
+ }
48
+ console.log('\nEdit, then: dm sql run <file> (read-only) or dm sql push <file>.');
49
+ }
50
+ /** `dm sql run <file> --param k=v` — read-only test-run against the engine. */
51
+ export async function runSqlCommand(file, opts, deps = {}) {
52
+ const cwd = deps.cwd ?? process.cwd();
53
+ const creds = requireCredentials();
54
+ const client = deps.client ?? new PlatformClient(creds.url, creds.token);
55
+ const filePath = path.resolve(cwd, file);
56
+ if (!existsSync(filePath))
57
+ throw new Error(`File not found: ${file}`);
58
+ const { meta, sql } = parseSqlFile(readFileSync(filePath, 'utf8'));
59
+ const credentialId = opts.credentialId !== undefined ? Number(opts.credentialId) : mnum(meta, 'credentialId');
60
+ if (credentialId === undefined || !Number.isInteger(credentialId) || credentialId <= 0) {
61
+ throw new Error('No credentialId — add it to the @dm-sql frontmatter (pull a query) or pass --credential-id <n>.');
62
+ }
63
+ const parameters = {};
64
+ for (const kv of opts.param ?? []) {
65
+ const eq = kv.indexOf('=');
66
+ if (eq === -1)
67
+ throw new Error(`--param expects key=value (got "${kv}")`);
68
+ parameters[kv.slice(0, eq)] = kv.slice(eq + 1);
69
+ }
70
+ const queryId = mnum(meta, 'queryId');
71
+ console.log(`Running SQL against ${creds.url} (test-run)…`);
72
+ const res = await client.testRunOdbc({
73
+ query_id: queryId !== undefined ? String(queryId) : undefined,
74
+ query_text: sql,
75
+ credential_id: credentialId,
76
+ parameters,
77
+ timeout_seconds: mnum(meta, 'timeoutSeconds') ?? 30,
78
+ });
79
+ if (res.status !== 'completed' && res.status !== 'success') {
80
+ console.log(`\n✗ ${res.status}: ${res.error ?? 'query failed'}`);
81
+ process.exitCode = 1;
82
+ return;
83
+ }
84
+ console.log(`\n✓ ${res.row_count ?? res.rows?.length ?? 0} rows in ${res.duration_ms ?? '?'}ms`);
85
+ if (res.columns?.length)
86
+ console.log(` columns: ${res.columns.join(', ')}`);
87
+ for (const row of (res.rows ?? []).slice(0, 10))
88
+ console.log(` ${JSON.stringify(row)}`);
89
+ if ((res.rows?.length ?? 0) > 10)
90
+ console.log(` … (${res.rows.length - 10} more)`);
91
+ }
92
+ /** `dm sql push <file>` — create or update the query in place (ODBC has no versions). */
93
+ export async function pushSqlCommand(file, opts, deps = {}) {
94
+ const cwd = deps.cwd ?? process.cwd();
95
+ const creds = requireCredentials();
96
+ const client = deps.client ?? new PlatformClient(creds.url, creds.token);
97
+ const filePath = path.resolve(cwd, file);
98
+ if (!existsSync(filePath))
99
+ throw new Error(`File not found: ${file}`);
100
+ const { meta, sql } = parseSqlFile(readFileSync(filePath, 'utf8'));
101
+ const name = mstr(meta, 'name');
102
+ if (!name)
103
+ throw new Error('frontmatter is missing "name" — required to save a query.');
104
+ const body = {
105
+ query_name: name,
106
+ query_text: sql.trim(),
107
+ description: mstr(meta, 'description') ?? '',
108
+ parameters: metaParams(meta),
109
+ timeout_seconds: mnum(meta, 'timeoutSeconds') ?? 30,
110
+ credential_id: mnum(meta, 'credentialId') ?? null,
111
+ };
112
+ const id = opts.id !== undefined ? Number(opts.id) : mnum(meta, 'queryId');
113
+ if (id !== undefined && Number.isInteger(id) && id > 0) {
114
+ await client.updateOdbcQuery(id, body);
115
+ console.log(`Updated SQL query [#${id}] "${name}" on ${creds.url}.`);
116
+ }
117
+ else {
118
+ const newId = await client.createOdbcQuery(body);
119
+ meta['queryId'] = newId;
120
+ writeFileSync(filePath, serializeSqlFile(meta, sql));
121
+ console.log(`Created SQL query [#${newId}] "${name}" on ${creds.url}.`);
122
+ }
123
+ }
124
+ //# sourceMappingURL=sql.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql.js","sourceRoot":"","sources":["../../src/commands/sql.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAyE,MAAM,WAAW,CAAC;AAClH,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAgB,MAAM,eAAe,CAAC;AAe7E,SAAS,QAAQ,CAAC,IAAY;IAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IACpF,OAAO,IAAI,IAAI,OAAO,CAAC;AACzB,CAAC;AAED,SAAS,YAAY,CAAC,CAAkB;IACtC,MAAM,IAAI,GAAY,EAAE,IAAI,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC;IAC7C,IAAI,CAAC,CAAC,WAAW;QAAE,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC;IACvD,IAAI,CAAC,CAAC,eAAe;QAAE,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,eAAe,CAAC;IAClE,IAAI,CAAC,CAAC,eAAe;QAAE,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,eAAe,CAAC;IAC9D,IAAI,CAAC,CAAC,aAAa;QAAE,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC;IAC5D,IAAI,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM;QAAE,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC;IAC3E,IAAI,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IACrC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,IAAI,GAAG,CAAC,CAAU,EAAE,CAAS,EAAsB,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;AACtH,MAAM,IAAI,GAAG,CAAC,CAAU,EAAE,CAAS,EAAsB,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;AAEtH,SAAS,UAAU,CAAC,CAAU;IAC5B,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC,YAAY,CAA0B,CAAC,CAAC,CAAC,EAAE,CAAC;AACzF,CAAC;AAED,oFAAoF;AACpF,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAoB,EAAE,OAAqD,EAAE;IAChH,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACtC,MAAM,KAAK,GAAG,kBAAkB,EAAE,CAAC;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,cAAc,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IACzE,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,KAAK,CAAC,CAAC;IACpD,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEvC,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,eAAe,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;IACxH,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,wCAAwC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;QACnE,OAAO;IACT,CAAC;IACD,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC;QACnD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QACrE,aAAa,CAAC,IAAI,EAAE,gBAAgB,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;QAC/E,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,MAAM,CAAC,UAAU,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;IACpF,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,qEAAqE,CAAC,CAAC;AACrF,CAAC;AAED,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAY,EAAE,IAAmB,EAAE,OAAqD,EAAE;IAC5H,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACtC,MAAM,KAAK,GAAG,kBAAkB,EAAE,CAAC;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,cAAc,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IACzE,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACzC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAC;IACtE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,YAAY,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;IAEnE,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IAC9G,IAAI,YAAY,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,YAAY,CAAC,IAAI,YAAY,IAAI,CAAC,EAAE,CAAC;QACvF,MAAM,IAAI,KAAK,CAAC,iGAAiG,CAAC,CAAC;IACrH,CAAC;IACD,MAAM,UAAU,GAA4B,EAAE,CAAC;IAC/C,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;QAClC,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC3B,IAAI,EAAE,KAAK,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,EAAE,IAAI,CAAC,CAAC;QAC1E,UAAU,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IACjD,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAEtC,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,CAAC,GAAG,cAAc,CAAC,CAAC;IAC5D,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC;QACnC,QAAQ,EAAE,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS;QAC7D,UAAU,EAAE,GAAG;QACf,aAAa,EAAE,YAAY;QAC3B,UAAU;QACV,eAAe,EAAE,IAAI,CAAC,IAAI,EAAE,gBAAgB,CAAC,IAAI,EAAE;KACpD,CAAC,CAAC;IAEH,IAAI,GAAG,CAAC,MAAM,KAAK,WAAW,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC3D,OAAO,CAAC,GAAG,CAAC,OAAO,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,KAAK,IAAI,cAAc,EAAE,CAAC,CAAC;QACjE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,OAAO,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,YAAY,GAAG,CAAC,WAAW,IAAI,GAAG,IAAI,CAAC,CAAC;IACjG,IAAI,GAAG,CAAC,OAAO,EAAE,MAAM;QAAE,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7E,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;QAAE,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACzF,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,EAAE;QAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,CAAC,IAAK,CAAC,MAAM,GAAG,EAAE,QAAQ,CAAC,CAAC;AACvF,CAAC;AAED,yFAAyF;AACzF,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAY,EAAE,IAAoB,EAAE,OAAqD,EAAE;IAC9H,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACtC,MAAM,KAAK,GAAG,kBAAkB,EAAE,CAAC;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,cAAc,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IACzE,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACzC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAC;IACtE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,YAAY,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;IAEnE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;IACxF,MAAM,IAAI,GAAG;QACX,UAAU,EAAE,IAAI;QAChB,UAAU,EAAE,GAAG,CAAC,IAAI,EAAE;QACtB,WAAW,EAAE,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC,IAAI,EAAE;QAC5C,UAAU,EAAE,UAAU,CAAC,IAAI,CAAC;QAC5B,eAAe,EAAE,IAAI,CAAC,IAAI,EAAE,gBAAgB,CAAC,IAAI,EAAE;QACnD,aAAa,EAAE,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,IAAI,IAAI;KAClD,CAAC;IAEF,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAC3E,IAAI,EAAE,KAAK,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;QACvD,MAAM,MAAM,CAAC,eAAe,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,uBAAuB,EAAE,MAAM,IAAI,QAAQ,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;IACvE,CAAC;SAAM,CAAC;QACN,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QACjD,IAAI,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC;QACxB,aAAa,CAAC,QAAQ,EAAE,gBAAgB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;QACrD,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,MAAM,IAAI,QAAQ,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;IAC1E,CAAC;AACH,CAAC"}
@@ -0,0 +1,13 @@
1
+ export interface TypegenOptions {
2
+ watch?: boolean;
3
+ out?: string;
4
+ }
5
+ /**
6
+ * `dm typegen [--watch] [--out src/dm.generated.ts]`
7
+ *
8
+ * Reads `dm.config.json`, pulls metadata for every declared source / serial
9
+ * series / printer from the platform (builder bearer auth), and emits the
10
+ * deterministic typed module `src/dm.generated.ts`. With `--watch`, re-runs
11
+ * whenever `dm.config.json` changes.
12
+ */
13
+ export declare function typegenCommand(opts: TypegenOptions): Promise<void>;
@@ -0,0 +1,50 @@
1
+ import { mkdirSync, readFileSync, watch, writeFileSync, existsSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { loadDmConfig } from '../config.js';
4
+ import { PlatformClient } from '../api.js';
5
+ import { requireCredentials } from '../credentials.js';
6
+ import { loadTypegenMeta } from '../typegen/meta.js';
7
+ import { emitGeneratedModule } from '../typegen/emit.js';
8
+ /**
9
+ * `dm typegen [--watch] [--out src/dm.generated.ts]`
10
+ *
11
+ * Reads `dm.config.json`, pulls metadata for every declared source / serial
12
+ * series / printer from the platform (builder bearer auth), and emits the
13
+ * deterministic typed module `src/dm.generated.ts`. With `--watch`, re-runs
14
+ * whenever `dm.config.json` changes.
15
+ */
16
+ export async function typegenCommand(opts) {
17
+ const outRel = opts.out ?? path.join('src', 'dm.generated.ts');
18
+ const cwd = process.cwd();
19
+ const run = async () => {
20
+ const config = loadDmConfig(cwd);
21
+ const creds = requireCredentials();
22
+ const client = new PlatformClient(creds.url, creds.token);
23
+ const meta = await loadTypegenMeta(config, client);
24
+ const code = emitGeneratedModule(meta);
25
+ const outFile = path.resolve(cwd, outRel);
26
+ mkdirSync(path.dirname(outFile), { recursive: true });
27
+ const before = existsSync(outFile) ? readFileSync(outFile, 'utf8') : null;
28
+ if (before === code) {
29
+ console.log(`${outRel} is up to date.`);
30
+ return;
31
+ }
32
+ writeFileSync(outFile, code);
33
+ console.log(`Wrote ${outRel} (${meta.tables.length} tables, ${meta.odbc.length} odbc, ${meta.scripts.length} scripts, ${meta.serials.length} series, ${meta.printers.length} printers).`);
34
+ };
35
+ await run();
36
+ if (opts.watch) {
37
+ const configFile = path.join(cwd, 'dm.config.json');
38
+ console.log(`Watching ${configFile} for changes... (ctrl-c to stop)`);
39
+ let timer;
40
+ watch(configFile, () => {
41
+ clearTimeout(timer);
42
+ timer = setTimeout(() => {
43
+ run().catch((err) => console.error(`typegen failed: ${String(err)}`));
44
+ }, 200);
45
+ });
46
+ // Keep the process alive while watching.
47
+ await new Promise(() => { });
48
+ }
49
+ }
50
+ //# sourceMappingURL=typegen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typegen.js","sourceRoot":"","sources":["../../src/commands/typegen.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /** Source kinds declarable in `dm.config.json` (manifest §2.2). */
2
+ export type SourceType = 'lookup_table' | 'odbc_query' | 'script';
3
+ export interface SourceDecl {
4
+ sourceId: number;
5
+ type: SourceType;
6
+ alias: string;
7
+ }
8
+ export interface SerialSeriesDecl {
9
+ seriesId: number;
10
+ alias: string;
11
+ }
12
+ export interface PrinterDecl {
13
+ printerId: number;
14
+ alias: string;
15
+ }
16
+ export interface AppContract {
17
+ inputs: unknown[];
18
+ outputs: unknown[];
19
+ events: unknown[];
20
+ }
21
+ /** Parsed and validated `dm.config.json`. */
22
+ export interface DmConfig {
23
+ appId: number;
24
+ entry: string;
25
+ sources: SourceDecl[];
26
+ serialSeries: SerialSeriesDecl[];
27
+ printers: PrinterDecl[] | 'all';
28
+ appContract: AppContract;
29
+ }
30
+ /** A valid alias / JS identifier (shared with `dm add`). */
31
+ export declare const ALIAS_RE: RegExp;
32
+ /** Error thrown for an invalid `dm.config.json`. */
33
+ export declare class DmConfigError extends Error {
34
+ constructor(message: string);
35
+ }
36
+ /**
37
+ * Validates a raw parsed `dm.config.json` object and applies defaults.
38
+ *
39
+ * Rules: positive-integer ids; aliases must be valid JS identifiers and
40
+ * unique across ALL categories (they share one generated registry);
41
+ * `printers` is either a declaration list or the string `"all"`.
42
+ */
43
+ export declare function validateDmConfig(raw: unknown): DmConfig;
44
+ /** Loads and validates `dm.config.json` from `dir` (default: cwd). */
45
+ export declare function loadDmConfig(dir?: string): DmConfig;
package/dist/config.js ADDED
@@ -0,0 +1,118 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ const SOURCE_TYPES = ['lookup_table', 'odbc_query', 'script'];
4
+ /** A valid alias / JS identifier (shared with `dm add`). */
5
+ export const ALIAS_RE = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
6
+ /** Error thrown for an invalid `dm.config.json`. */
7
+ export class DmConfigError extends Error {
8
+ constructor(message) {
9
+ super(message);
10
+ this.name = 'DmConfigError';
11
+ }
12
+ }
13
+ /**
14
+ * Validates a raw parsed `dm.config.json` object and applies defaults.
15
+ *
16
+ * Rules: positive-integer ids; aliases must be valid JS identifiers and
17
+ * unique across ALL categories (they share one generated registry);
18
+ * `printers` is either a declaration list or the string `"all"`.
19
+ */
20
+ export function validateDmConfig(raw) {
21
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
22
+ throw new DmConfigError('dm.config.json must be a JSON object');
23
+ }
24
+ const o = raw;
25
+ const appId = o['appId'];
26
+ if (typeof appId !== 'number' || !Number.isInteger(appId) || appId <= 0) {
27
+ throw new DmConfigError('dm.config.json: "appId" must be a positive integer');
28
+ }
29
+ const entry = o['entry'] ?? 'index.html';
30
+ if (typeof entry !== 'string' || entry === '') {
31
+ throw new DmConfigError('dm.config.json: "entry" must be a non-empty string');
32
+ }
33
+ const seenAliases = new Set();
34
+ const checkAlias = (alias, where) => {
35
+ if (typeof alias !== 'string' || !ALIAS_RE.test(alias)) {
36
+ throw new DmConfigError(`dm.config.json: ${where}: alias ${JSON.stringify(alias)} must be a valid identifier (letters, digits, _, $; not starting with a digit)`);
37
+ }
38
+ if (seenAliases.has(alias)) {
39
+ throw new DmConfigError(`dm.config.json: duplicate alias "${alias}" (aliases must be unique across sources, serialSeries, and printers)`);
40
+ }
41
+ seenAliases.add(alias);
42
+ return alias;
43
+ };
44
+ const checkId = (v, where) => {
45
+ if (typeof v !== 'number' || !Number.isInteger(v) || v <= 0) {
46
+ throw new DmConfigError(`dm.config.json: ${where} must be a positive integer`);
47
+ }
48
+ return v;
49
+ };
50
+ const sourcesRaw = o['sources'] ?? [];
51
+ if (!Array.isArray(sourcesRaw))
52
+ throw new DmConfigError('dm.config.json: "sources" must be an array');
53
+ const sources = sourcesRaw.map((s, i) => {
54
+ const so = (s ?? {});
55
+ const type = so['type'];
56
+ if (typeof type !== 'string' || !SOURCE_TYPES.includes(type)) {
57
+ throw new DmConfigError(`dm.config.json: sources[${i}].type must be one of ${SOURCE_TYPES.join(', ')}`);
58
+ }
59
+ return {
60
+ sourceId: checkId(so['sourceId'], `sources[${i}].sourceId`),
61
+ type: type,
62
+ alias: checkAlias(so['alias'], `sources[${i}]`),
63
+ };
64
+ });
65
+ const seriesRaw = o['serialSeries'] ?? [];
66
+ if (!Array.isArray(seriesRaw))
67
+ throw new DmConfigError('dm.config.json: "serialSeries" must be an array');
68
+ const serialSeries = seriesRaw.map((s, i) => {
69
+ const so = (s ?? {});
70
+ return {
71
+ seriesId: checkId(so['seriesId'], `serialSeries[${i}].seriesId`),
72
+ alias: checkAlias(so['alias'], `serialSeries[${i}]`),
73
+ };
74
+ });
75
+ const printersRaw = o['printers'] ?? [];
76
+ let printers;
77
+ if (printersRaw === 'all') {
78
+ printers = 'all';
79
+ }
80
+ else if (Array.isArray(printersRaw)) {
81
+ printers = printersRaw.map((p, i) => {
82
+ const po = (p ?? {});
83
+ return {
84
+ printerId: checkId(po['printerId'], `printers[${i}].printerId`),
85
+ alias: checkAlias(po['alias'], `printers[${i}]`),
86
+ };
87
+ });
88
+ }
89
+ else {
90
+ throw new DmConfigError('dm.config.json: "printers" must be an array of declarations or the string "all"');
91
+ }
92
+ const contractRaw = (o['appContract'] ?? {});
93
+ if (typeof contractRaw !== 'object' || Array.isArray(contractRaw)) {
94
+ throw new DmConfigError('dm.config.json: "appContract" must be an object');
95
+ }
96
+ const appContract = {
97
+ inputs: Array.isArray(contractRaw['inputs']) ? contractRaw['inputs'] : [],
98
+ outputs: Array.isArray(contractRaw['outputs']) ? contractRaw['outputs'] : [],
99
+ events: Array.isArray(contractRaw['events']) ? contractRaw['events'] : [],
100
+ };
101
+ return { appId, entry, sources, serialSeries, printers, appContract };
102
+ }
103
+ /** Loads and validates `dm.config.json` from `dir` (default: cwd). */
104
+ export function loadDmConfig(dir = process.cwd()) {
105
+ const file = path.join(dir, 'dm.config.json');
106
+ if (!existsSync(file)) {
107
+ throw new DmConfigError(`No dm.config.json found in ${dir}`);
108
+ }
109
+ let raw;
110
+ try {
111
+ raw = JSON.parse(readFileSync(file, 'utf8'));
112
+ }
113
+ catch (err) {
114
+ throw new DmConfigError(`dm.config.json is not valid JSON: ${String(err)}`);
115
+ }
116
+ return validateDmConfig(raw);
117
+ }
118
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /** Stored CLI credentials: platform URL + builder API key (`dcp_...`). */
2
+ export interface Credentials {
3
+ url: string;
4
+ token: string;
5
+ }
6
+ /**
7
+ * Resolves the config directory. Honors `DM_CONFIG_DIR` (used by tests),
8
+ * defaulting to `~/.config/datamagik`.
9
+ */
10
+ export declare function configDir(): string;
11
+ export declare function credentialsPath(): string;
12
+ /** Writes credentials with 0600 permissions (owner read/write only). */
13
+ export declare function saveCredentials(creds: Credentials): string;
14
+ /** Loads stored credentials, or null when not logged in. */
15
+ export declare function loadCredentials(): Credentials | null;
16
+ /** Loads credentials or exits with a helpful message. */
17
+ export declare function requireCredentials(): Credentials;
@@ -0,0 +1,49 @@
1
+ import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import { homedir } from 'node:os';
3
+ import path from 'node:path';
4
+ /**
5
+ * Resolves the config directory. Honors `DM_CONFIG_DIR` (used by tests),
6
+ * defaulting to `~/.config/datamagik`.
7
+ */
8
+ export function configDir() {
9
+ return process.env['DM_CONFIG_DIR'] ?? path.join(homedir(), '.config', 'datamagik');
10
+ }
11
+ export function credentialsPath() {
12
+ return path.join(configDir(), 'credentials.json');
13
+ }
14
+ /** Writes credentials with 0600 permissions (owner read/write only). */
15
+ export function saveCredentials(creds) {
16
+ const dir = configDir();
17
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
18
+ const file = credentialsPath();
19
+ writeFileSync(file, JSON.stringify(creds, null, 2) + '\n', { mode: 0o600 });
20
+ // mode in writeFileSync only applies on create; enforce on overwrite too.
21
+ chmodSync(file, 0o600);
22
+ return file;
23
+ }
24
+ /** Loads stored credentials, or null when not logged in. */
25
+ export function loadCredentials() {
26
+ const file = credentialsPath();
27
+ if (!existsSync(file))
28
+ return null;
29
+ try {
30
+ const raw = JSON.parse(readFileSync(file, 'utf8'));
31
+ if (typeof raw.url === 'string' && typeof raw.token === 'string') {
32
+ return { url: raw.url.replace(/\/$/, ''), token: raw.token };
33
+ }
34
+ return null;
35
+ }
36
+ catch {
37
+ return null;
38
+ }
39
+ }
40
+ /** Loads credentials or exits with a helpful message. */
41
+ export function requireCredentials() {
42
+ const creds = loadCredentials();
43
+ if (!creds) {
44
+ console.error('Not logged in. Run `dm login --url <platform-url>` first.');
45
+ process.exit(1);
46
+ }
47
+ return creds;
48
+ }
49
+ //# sourceMappingURL=credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxF,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAQ7B;;;GAGG;AACH,MAAM,UAAU,SAAS;IACvB,OAAO,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;AACtF,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,kBAAkB,CAAC,CAAC;AACpD,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,eAAe,CAAC,KAAkB;IAChD,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACjD,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;IAC/B,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC5E,0EAA0E;IAC1E,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACvB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,eAAe;IAC7B,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;IAC/B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAyB,CAAC;QAC3E,IAAI,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACjE,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC;QAC/D,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,kBAAkB;IAChC,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,2DAA2D,CAAC,CAAC;QAC3E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};