@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
package/dist/index.js ADDED
@@ -0,0 +1,268 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { initCommand } from './commands/init.js';
4
+ import { addCommand } from './commands/add.js';
5
+ import { pullCommand, runCommand, pushCommand, commitCommand, statusCommand } from './commands/script.js';
6
+ import { pullSqlCommand, runSqlCommand, pushSqlCommand } from './commands/sql.js';
7
+ import { loginCommand } from './commands/login.js';
8
+ import { typegenCommand } from './commands/typegen.js';
9
+ import { devCommand } from './commands/dev.js';
10
+ import { publishCommand } from './commands/publish.js';
11
+ const program = new Command();
12
+ program
13
+ .name('dm')
14
+ .description(`DataMagik CLI — build, type, run, and ship custom Vue SPA apps for the DataMagik Application Designer.
15
+
16
+ Typical lifecycle:
17
+ dm init my-app scaffold a starter (simple or showcase)
18
+ cd my-app && npm install
19
+ dm login --url <platform> store a builder API key
20
+ dm add search the tenant and declare a resource
21
+ dm typegen generate typed src/dm.generated.ts
22
+ dm dev hot-reload dev server against live data
23
+ dm publish build + ship a new version (goes live)
24
+
25
+ Config & state:
26
+ dm.config.json your app id + declared resources (commit it)
27
+ src/dm.generated.ts typed alias surface (regenerated by typegen; commit it)
28
+ ~/.config/datamagik/credentials.json stored { url, token } (0600)`)
29
+ .version('0.1.0')
30
+ .showHelpAfterError('(run `dm <command> --help` for usage)');
31
+ program
32
+ .command('init')
33
+ .summary('scaffold a new SPA starter project')
34
+ .description(`Scaffold a Vue 3 + Vite starter wired to @datamagik/app-sdk.
35
+
36
+ Templates:
37
+ showcase platform-styled app with a working example for every SDK area
38
+ (context, data query, scripts, serials, printing, navigation,
39
+ output events) — recommended for learning the framework.
40
+ simple minimal app: connect, show context, run one data query.
41
+
42
+ The generated dm.config.json uses placeholder resource ids. Set "appId" and
43
+ add real resources with \`dm add\`, then run \`dm typegen\`.`)
44
+ .argument('[dir]', 'target directory (defaults to the current directory)')
45
+ .option('--template <kind>', 'starter template: simple | showcase (prompts when omitted)')
46
+ .option('--app <id>', 'application id to write into dm.config.json')
47
+ .option('--force', 'scaffold into a non-empty directory')
48
+ .addHelpText('after', `
49
+ Examples:
50
+ dm init my-app # prompt for template, scaffold ./my-app
51
+ dm init my-app --template showcase # full showcase app
52
+ dm init . --template simple --app 12 # minimal app in the current dir, appId 12`)
53
+ .action(async (dir, opts) => {
54
+ await initCommand({ dir, ...opts });
55
+ });
56
+ program
57
+ .command('add')
58
+ .summary('search the tenant and declare a resource in dm.config.json')
59
+ .description(`Browse the active tenant's resources, pick one, declare it in dm.config.json
60
+ with a chosen alias, and regenerate src/dm.generated.ts.
61
+
62
+ Resource types: lookup_table, odbc_query, script, serial_series, printer
63
+ (synonyms accepted: table, odbc/sql/query, series/serial, printer).
64
+
65
+ Interactive on a TTY (prompts for type, selection, and alias). Fully scriptable
66
+ by passing the type and an id (or unique search term) as arguments. Requires
67
+ \`dm login\` first.`)
68
+ .argument('[type]', 'resource type (prompts when omitted)')
69
+ .argument('[id-or-search]', 'numeric id (selects directly) or a name search term')
70
+ .option('--alias <name>', 'alias to declare (derived from the resource name when omitted)')
71
+ .option('--no-typegen', 'do not run dm typegen after adding')
72
+ .option('--yes', 'assume yes / non-interactive (no prompts)')
73
+ .addHelpText('after', `
74
+ Examples:
75
+ dm add # fully interactive: pick type, search, alias
76
+ dm add lookup_table # list lookup tables, then pick one
77
+ dm add script receipt # search scripts matching "receipt"
78
+ dm add printer 11 --alias line1Zebra # declare printer #11 as line1Zebra
79
+ dm add odbc 7 --alias openOrders --no-typegen`)
80
+ .action(async (type, query, opts) => {
81
+ await addCommand({ type, query, alias: opts.alias, noTypegen: opts.typegen === false, yes: opts.yes });
82
+ });
83
+ const script = program
84
+ .command('script')
85
+ .summary('author script-engine scripts locally (pull / run / push / commit / status)')
86
+ .description(`Local-first authoring for script-engine scripts: pull a script to a .js file
87
+ with full frontmatter + autocomplete for the V8 sandbox globals (plex, odbc,
88
+ context, …), edit locally, and dry-run it against the cloud engine. Requires
89
+ \`dm login\`. See \`dm script <sub> --help\`.`);
90
+ script
91
+ .command('pull')
92
+ .summary('pull script(s) to local .js files with frontmatter + types')
93
+ .description(`Write each script to <dir>/<slug>.js with a @dm-script frontmatter block (its
94
+ full attribute set) and drop the ambient types + jsconfig so the V8 globals
95
+ autocomplete. Pulls all scripts unless an id is given.`)
96
+ .argument('[id]', 'script id to pull (pulls all when omitted)')
97
+ .option('--dir <dir>', 'output directory', 'scripts')
98
+ .addHelpText('after', `
99
+ Examples:
100
+ dm script pull # pull every script into ./scripts
101
+ dm script pull 1107 # pull one script
102
+ dm script pull --dir src/scripts`)
103
+ .action(async (id, opts) => {
104
+ await pullCommand({ id, dir: opts.dir });
105
+ });
106
+ script
107
+ .command('run')
108
+ .summary('dry-run a local script against the engine (read-only)')
109
+ .description(`Send a local script's code to the engine's read-only test-run with a simulated
110
+ context and print the console logs + output. Never saves a version. The scriptId
111
+ comes from the file's @dm-script frontmatter (or --id).`)
112
+ .argument('<file>', 'path to the local script .js file')
113
+ .option('--id <id>', 'script id (overrides the frontmatter scriptId)')
114
+ .option('--context <key=val...>', 'simulated context params (repeatable)', collect, [])
115
+ .addHelpText('after', `
116
+ Examples:
117
+ dm script run scripts/milton-ar-daily.js
118
+ dm script run scripts/milton-ar-daily.js --context order=42 --context line=L1`)
119
+ .action(async (file, opts) => {
120
+ await runCommand(file, { id: opts.id, context: opts.context });
121
+ });
122
+ script
123
+ .command('push')
124
+ .summary('save a script’s metadata to the platform (no code version)')
125
+ .description(`Update an existing script's attributes (name, description, tags, timeout, …)
126
+ from the file's frontmatter via PUT. Does NOT save code — use \`dm script commit\`
127
+ to deploy code as a new version. Requires a scriptId in the frontmatter.`)
128
+ .argument('<file>', 'path to the local script .js file')
129
+ .option('--id <id>', 'script id (overrides the frontmatter scriptId)')
130
+ .addHelpText('after', '\nExample:\n dm script push scripts/milton-ar-daily.js')
131
+ .action(async (file, opts) => {
132
+ await pushCommand(file, opts);
133
+ });
134
+ script
135
+ .command('commit')
136
+ .summary('deploy: save metadata + code as a new version (goes live)')
137
+ .description(`Create the script if it has no id (writing the new id back to the file), sync
138
+ its metadata, and save the code as a new version — the current/live version.`)
139
+ .argument('<file>', 'path to the local script .js file')
140
+ .option('--id <id>', 'script id (overrides the frontmatter scriptId)')
141
+ .option('-m, --message <text>', 'version notes')
142
+ .addHelpText('after', '\nExample:\n dm script commit scripts/milton-ar-daily.js -m "fix rounding"')
143
+ .action(async (file, opts) => {
144
+ await commitCommand(file, opts);
145
+ });
146
+ script
147
+ .command('status')
148
+ .summary('show how a local script differs from the engine')
149
+ .description('Compare the local file’s attributes + code against the current version on the platform.')
150
+ .argument('<file>', 'path to the local script .js file')
151
+ .option('--id <id>', 'script id (overrides the frontmatter scriptId)')
152
+ .action(async (file, opts) => {
153
+ await statusCommand(file, opts);
154
+ });
155
+ const sql = program
156
+ .command('sql')
157
+ .summary('author ODBC/SQL queries locally (pull / run / push)')
158
+ .description(`Local-first authoring for ODBC queries: pull a query to a .sql file with
159
+ @dm-sql frontmatter, dry-run it against the engine, and push changes back.
160
+ ODBC queries are not versioned, so push updates in place. Requires \`dm login\`.`);
161
+ sql
162
+ .command('pull')
163
+ .summary('pull SQL query/queries to local .sql files')
164
+ .description('Write each ODBC query to <dir>/<slug>.sql with @dm-sql frontmatter. Pulls all unless an id is given.')
165
+ .argument('[id]', 'query id to pull (pulls all when omitted)')
166
+ .option('--dir <dir>', 'output directory', 'sql')
167
+ .addHelpText('after', '\nExamples:\n dm sql pull\n dm sql pull 7 --dir src/sql')
168
+ .action(async (id, opts) => {
169
+ await pullSqlCommand({ id, dir: opts.dir });
170
+ });
171
+ sql
172
+ .command('run')
173
+ .summary('dry-run a local SQL query against the engine (read-only)')
174
+ .description('Send the local SQL to the engine’s read-only test-run and print rows. Uses the frontmatter credentialId (or --credential-id).')
175
+ .argument('<file>', 'path to the local .sql file')
176
+ .option('--id <id>', 'query id (overrides the frontmatter queryId)')
177
+ .option('--credential-id <id>', 'ODBC credential id (overrides the frontmatter credentialId)')
178
+ .option('--param <key=val...>', 'query parameters (repeatable)', collect, [])
179
+ .addHelpText('after', '\nExample:\n dm sql run sql/open-orders.sql --param status=OPEN')
180
+ .action(async (file, opts) => {
181
+ await runSqlCommand(file, { id: opts.id, credentialId: opts.credentialId, param: opts.param });
182
+ });
183
+ sql
184
+ .command('push')
185
+ .summary('create or update a SQL query in place')
186
+ .description('Save the local .sql file’s frontmatter + text to the platform (creates if no queryId, else updates). ODBC queries are not versioned.')
187
+ .argument('<file>', 'path to the local .sql file')
188
+ .option('--id <id>', 'query id (overrides the frontmatter queryId)')
189
+ .addHelpText('after', '\nExample:\n dm sql push sql/open-orders.sql')
190
+ .action(async (file, opts) => {
191
+ await pushSqlCommand(file, opts);
192
+ });
193
+ program
194
+ .command('login')
195
+ .summary('store platform credentials')
196
+ .description(`Store { url, token } in ~/.config/datamagik/credentials.json (mode 0600).
197
+
198
+ Create an API key in the platform UI (Settings → API Keys) and paste it when
199
+ prompted, or pass it with --token. The url is remembered and used by add,
200
+ typegen, dev, and publish.`)
201
+ .option('--url <platform>', 'platform base URL', 'https://data-magik.com')
202
+ .option('--token <token>', 'API key (dcp_...) created in the platform UI (prompted when omitted)')
203
+ .addHelpText('after', `
204
+ Examples:
205
+ dm login --url https://staging.data-magik.com
206
+ dm login --url https://data-magik.com --token dcp_xxxxxxxx`)
207
+ .action(async (opts) => {
208
+ await loginCommand(opts);
209
+ });
210
+ program
211
+ .command('typegen')
212
+ .summary('generate the typed dm.generated.ts module')
213
+ .description(`Read dm.config.json, fetch metadata for every declared resource from the
214
+ platform, and emit the typed module src/dm.generated.ts (deterministic — commit
215
+ it). Re-run after changing dm.config.json (or use --watch). Requires \`dm login\`.`)
216
+ .option('--watch', 're-generate when dm.config.json changes')
217
+ .option('--out <file>', 'output file', 'src/dm.generated.ts')
218
+ .addHelpText('after', `
219
+ Examples:
220
+ dm typegen
221
+ dm typegen --watch
222
+ dm typegen --out src/types/dm.generated.ts`)
223
+ .action(async (opts) => {
224
+ await typegenCommand(opts);
225
+ });
226
+ program
227
+ .command('dev')
228
+ .summary('run the dev server against live platform data')
229
+ .description(`Start the project's Vite dev server with the DataMagik auth proxy and a
230
+ simulated host context. /api/* calls are proxied to the platform with your
231
+ builder bearer; --context flags become context.params. Prints an in-platform
232
+ dev URL you open to test inside the real shell. Requires \`dm login\`.`)
233
+ .option('--app <id>', 'app id (defaults to dm.config.json appId)')
234
+ .option('--port <port>', 'dev server port', '5173')
235
+ .option('--context <key=val...>', 'simulated context params (repeatable)', collect, [])
236
+ .addHelpText('after', `
237
+ Examples:
238
+ dm dev
239
+ dm dev --app 12 --port 5174
240
+ dm dev --context order=42 --context line=L1`)
241
+ .action(async (opts) => {
242
+ await devCommand(opts);
243
+ });
244
+ program
245
+ .command('publish')
246
+ .summary('build and ship a new version (goes live)')
247
+ .description(`Run vite build, zip dist/, and publish a new SPA version to the platform.
248
+ The new version goes live immediately. Use --skip-build to publish an existing
249
+ dist/ as-is. Requires \`dm login\`.`)
250
+ .option('--app <id>', 'app id (defaults to dm.config.json appId)')
251
+ .option('--message <text>', 'change description for the new version')
252
+ .option('--skip-build', 'skip vite build and publish the existing dist/')
253
+ .addHelpText('after', `
254
+ Examples:
255
+ dm publish --message "first version"
256
+ dm publish --app 12 --message "fix label layout"
257
+ dm publish --skip-build --message "re-publish current dist"`)
258
+ .action(async (opts) => {
259
+ await publishCommand(opts);
260
+ });
261
+ function collect(value, previous) {
262
+ return [...previous, value];
263
+ }
264
+ program.parseAsync(process.argv).catch((err) => {
265
+ console.error(err instanceof Error ? err.message : String(err));
266
+ process.exit(1);
267
+ });
268
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export type MetaValue = string | number | boolean | string[];
2
+ export type ScriptMeta = Record<string, MetaValue>;
3
+ export interface ScriptFile {
4
+ meta: ScriptMeta;
5
+ code: string;
6
+ }
7
+ /** Parses a `@dm-script` file into `{ meta, code }`. Missing block → empty meta. */
8
+ export declare function parseScriptFile(text: string): ScriptFile;
9
+ /** Serializes `{ meta, code }` back into a `@dm-script` file. */
10
+ export declare function serializeScriptFile(meta: ScriptMeta, code: string): string;
@@ -0,0 +1,91 @@
1
+ // Parse/serialize the single-file frontmatter that carries a script's full
2
+ // attribute set (see docs/design/script-engine-local-dev.md). A script file is
3
+ // a `/* @dm-script ... */` block (key: value lines) followed by the code body.
4
+ const MARKER = '@dm-script';
5
+ // Stable emit order; only keys that are present are written.
6
+ const FIELD_ORDER = [
7
+ 'name', 'description', 'category', 'tags', 'active', 'timeoutSeconds',
8
+ 'maxMemoryMB', 'priority', 'isReportGenerator', 'reportType',
9
+ 'generateDocuments', 'outputFormat', 'titleJsonPath', 'summaryJsonPath',
10
+ 'waitForGeneration', 'credentials', 'allowedDomains', 'schedule', 'scriptId',
11
+ ];
12
+ const SAFE_BARE = /^[A-Za-z0-9_$./\-*]+$/;
13
+ function parseValue(raw) {
14
+ const v = raw.trim();
15
+ if (v.startsWith('[') && v.endsWith(']')) {
16
+ const inner = v.slice(1, -1).trim();
17
+ if (inner === '')
18
+ return [];
19
+ return inner.split(',').map((s) => unquote(s.trim()));
20
+ }
21
+ if (v === 'true')
22
+ return true;
23
+ if (v === 'false')
24
+ return false;
25
+ if (/^-?\d+$/.test(v))
26
+ return Number(v);
27
+ return unquote(v);
28
+ }
29
+ function unquote(s) {
30
+ if (s.startsWith('"')) {
31
+ try {
32
+ return JSON.parse(s);
33
+ }
34
+ catch {
35
+ return s.slice(1, -1);
36
+ }
37
+ }
38
+ return s;
39
+ }
40
+ function serializeScalar(v) {
41
+ if (typeof v === 'string')
42
+ return SAFE_BARE.test(v) ? v : JSON.stringify(v);
43
+ return String(v);
44
+ }
45
+ function serializeValue(v) {
46
+ if (Array.isArray(v))
47
+ return `[${v.map((s) => serializeScalar(s)).join(', ')}]`;
48
+ return serializeScalar(v);
49
+ }
50
+ /** Parses a `@dm-script` file into `{ meta, code }`. Missing block → empty meta. */
51
+ export function parseScriptFile(text) {
52
+ const start = text.indexOf(`/* ${MARKER}`);
53
+ if (start === -1)
54
+ return { meta: {}, code: text };
55
+ const end = text.indexOf('*/', start);
56
+ if (end === -1)
57
+ return { meta: {}, code: text };
58
+ const block = text.slice(start + `/* ${MARKER}`.length, end);
59
+ const meta = {};
60
+ for (const line of block.split('\n')) {
61
+ const trimmed = line.trim();
62
+ if (trimmed === '' || trimmed.startsWith('#'))
63
+ continue;
64
+ const colon = trimmed.indexOf(':');
65
+ if (colon === -1)
66
+ continue;
67
+ const key = trimmed.slice(0, colon).trim();
68
+ let value = trimmed.slice(colon + 1).trim();
69
+ // Strip a trailing `# comment`, but never inside a quoted string.
70
+ if (!value.startsWith('"'))
71
+ value = value.replace(/\s+#.*$/, '');
72
+ if (key)
73
+ meta[key] = parseValue(value);
74
+ }
75
+ // Code is everything after the closing `*/` (drop the immediate newline).
76
+ const code = text.slice(end + 2).replace(/^\r?\n/, '');
77
+ return { meta, code };
78
+ }
79
+ /** Serializes `{ meta, code }` back into a `@dm-script` file. */
80
+ export function serializeScriptFile(meta, code) {
81
+ const keys = [
82
+ ...FIELD_ORDER.filter((k) => k in meta),
83
+ ...Object.keys(meta).filter((k) => !FIELD_ORDER.includes(k)),
84
+ ];
85
+ const lines = [`/* ${MARKER}`];
86
+ for (const k of keys)
87
+ lines.push(` ${k}: ${serializeValue(meta[k])}`);
88
+ lines.push('*/');
89
+ return `${lines.join('\n')}\n${code.replace(/^\r?\n/, '')}`;
90
+ }
91
+ //# sourceMappingURL=scriptfile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scriptfile.js","sourceRoot":"","sources":["../src/scriptfile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export type SqlMeta = Record<string, unknown>;
2
+ export interface SqlFile {
3
+ meta: SqlMeta;
4
+ sql: string;
5
+ }
6
+ /** Parses a `@dm-sql` file into `{ meta, sql }`. No frontmatter → all SQL. */
7
+ export declare function parseSqlFile(text: string): SqlFile;
8
+ /** Serializes `{ meta, sql }` back into a `@dm-sql` file. */
9
+ export declare function serializeSqlFile(meta: SqlMeta, sql: string): string;
@@ -0,0 +1,75 @@
1
+ // Parse/serialize the `@dm-sql` frontmatter for ODBC/SQL queries: a leading
2
+ // block of `-- key: value` line comments followed by the raw SQL body. Values
3
+ // may be JSON (arrays/objects) — used for the `parameters` list.
4
+ const MARKER = '-- @dm-sql';
5
+ const FIELD_ORDER = ['name', 'description', 'timeoutSeconds', 'credential', 'credentialId', 'parameters', 'queryId'];
6
+ const SAFE_BARE = /^[A-Za-z0-9_$./\-*]+$/;
7
+ function parseValue(raw) {
8
+ const v = raw.trim();
9
+ if (v.startsWith('[') || v.startsWith('{')) {
10
+ try {
11
+ return JSON.parse(v);
12
+ }
13
+ catch {
14
+ return v;
15
+ }
16
+ }
17
+ if (v === 'true')
18
+ return true;
19
+ if (v === 'false')
20
+ return false;
21
+ if (/^-?\d+$/.test(v))
22
+ return Number(v);
23
+ if (v.startsWith('"')) {
24
+ try {
25
+ return JSON.parse(v);
26
+ }
27
+ catch {
28
+ return v.slice(1, -1);
29
+ }
30
+ }
31
+ return v;
32
+ }
33
+ function serializeValue(v) {
34
+ if (v === null)
35
+ return 'null';
36
+ if (typeof v === 'object')
37
+ return JSON.stringify(v);
38
+ if (typeof v === 'string')
39
+ return SAFE_BARE.test(v) ? v : JSON.stringify(v);
40
+ return String(v);
41
+ }
42
+ /** Parses a `@dm-sql` file into `{ meta, sql }`. No frontmatter → all SQL. */
43
+ export function parseSqlFile(text) {
44
+ const lines = text.split('\n');
45
+ if (lines[0]?.trim() !== MARKER)
46
+ return { meta: {}, sql: text };
47
+ const meta = {};
48
+ let i = 1;
49
+ for (; i < lines.length; i++) {
50
+ const line = lines[i] ?? '';
51
+ if (!line.trimStart().startsWith('--'))
52
+ break;
53
+ const body = line.trimStart().replace(/^--\s?/, '');
54
+ const colon = body.indexOf(':');
55
+ if (colon === -1)
56
+ continue;
57
+ const key = body.slice(0, colon).trim();
58
+ const value = body.slice(colon + 1).trim();
59
+ if (key)
60
+ meta[key] = parseValue(value);
61
+ }
62
+ return { meta, sql: lines.slice(i).join('\n').replace(/^\r?\n/, '') };
63
+ }
64
+ /** Serializes `{ meta, sql }` back into a `@dm-sql` file. */
65
+ export function serializeSqlFile(meta, sql) {
66
+ const keys = [
67
+ ...FIELD_ORDER.filter((k) => k in meta),
68
+ ...Object.keys(meta).filter((k) => !FIELD_ORDER.includes(k)),
69
+ ];
70
+ const lines = [MARKER];
71
+ for (const k of keys)
72
+ lines.push(`-- ${k}: ${serializeValue(meta[k])}`);
73
+ return `${lines.join('\n')}\n${sql.replace(/^\r?\n/, '')}`;
74
+ }
75
+ //# sourceMappingURL=sqlfile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlfile.js","sourceRoot":"","sources":["../src/sqlfile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { TypegenMeta } from './meta.js';
2
+ /**
3
+ * Emits the `dm.generated.ts` module from fetched metadata.
4
+ *
5
+ * Deterministic: aliases are sorted within each category, the output carries
6
+ * no timestamps, and identical inputs always produce byte-identical output —
7
+ * the file is meant to be committed.
8
+ */
9
+ export declare function emitGeneratedModule(meta: TypegenMeta): string;
10
+ /** `parts` → `PartsRow`-style Pascal case. */
11
+ export declare function pascal(alias: string): string;
12
+ /**
13
+ * Maps a lookup-table `value_schema` field type to TypeScript
14
+ * (design §8.1): text→string, number→number, date→string (ISO 8601),
15
+ * boolean→boolean, picture→DmImageRef, lookup_table→number (FK).
16
+ */
17
+ export declare function lookupFieldType(type: string): {
18
+ ts: string;
19
+ note?: string;
20
+ };
21
+ /** Maps an ODBC parameter type to TypeScript: string|int|float|bool. */
22
+ export declare function odbcParamType(type: string): string;