@swimmesberger/elarion-jsonrpc-client-generator 0.2.3-preview.68.1 → 0.2.3-preview.69.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 (3) hide show
  1. package/README.md +6 -0
  2. package/dist/cli.js +60 -5
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -7,6 +7,12 @@ npm install --save-dev @swimmesberger/elarion-jsonrpc-client-generator
7
7
  npx elarion-jsonrpc-client-generator --schema rpc-schema.json --out src/generated
8
8
  ```
9
9
 
10
+ Add `--watch` for a tight dev loop — the generator regenerates whenever `rpc-schema.json` changes (and survives the partial/invalid states a build tool leaves the file in mid-write). Pair it with a server that re-exports the schema on save (e.g. `dotnet watch`) so an edit to a handler flows straight to the typed client:
11
+
12
+ ```bash
13
+ npx elarion-jsonrpc-client-generator --schema rpc-schema.json --out src/generated --watch
14
+ ```
15
+
10
16
  The generated files are:
11
17
 
12
18
  | File | Purpose |
package/dist/cli.js CHANGED
@@ -1,7 +1,11 @@
1
1
  #!/usr/bin/env node
2
- import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import { mkdirSync, readFileSync, watchFile, writeFileSync } from 'node:fs';
3
3
  import { basename, resolve } from 'node:path';
4
4
  import { generateRpcClientFiles } from './generate.js';
5
+ // Poll interval for --watch. Polling (rather than fs.watch) is deliberate: the schema is (re)written by a
6
+ // build tool, often via a temp-file + rename, which event-based watchers miss or double-fire; polling the
7
+ // exact path is robust to that and to delete/recreate, at the cost of up-to-one-interval latency.
8
+ const WATCH_INTERVAL_MS = 300;
5
9
  const SUPPORTED_FRAMEWORKS = ['tanstack-start'];
6
10
  function parseArgs(argv) {
7
11
  const options = {
@@ -15,6 +19,10 @@ function parseArgs(argv) {
15
19
  printHelp();
16
20
  process.exit(0);
17
21
  }
22
+ if (arg === '--watch') {
23
+ options.watch = true;
24
+ continue;
25
+ }
18
26
  if (!next) {
19
27
  throw new Error(`Missing value for ${arg}`);
20
28
  }
@@ -85,14 +93,34 @@ Options:
85
93
  Supported: tanstack-start (needs the @tanstack/react-start peer dependency)
86
94
  --framework-adapter <file> Framework adapter filename (default: start-adapter.ts)
87
95
  --source-label <text> Source label written into generated file headers
96
+ --watch Regenerate whenever the schema file changes (Ctrl+C to stop)
88
97
  `);
89
98
  }
90
- function main() {
91
- const options = parseArgs(process.argv.slice(2));
99
+ // Reads the schema and writes the generated files once. Returns false (without throwing) on a missing or
100
+ // malformed schema so --watch can keep running across the transient states a build tool leaves the file in
101
+ // mid-write, and so a one-shot run exits non-zero with a clean message instead of a stack trace.
102
+ function generateOnce(options) {
92
103
  const schemaPath = resolve(process.cwd(), options.schemaPath);
93
104
  const outDir = resolve(process.cwd(), options.outDir);
94
- const raw = readFileSync(schemaPath, 'utf-8');
95
- const schema = JSON.parse(raw);
105
+ let raw;
106
+ try {
107
+ raw = readFileSync(schemaPath, 'utf-8');
108
+ }
109
+ catch (error) {
110
+ const code = error.code;
111
+ console.error(code === 'ENOENT'
112
+ ? `[jsonrpc-client-generator] Schema not found at ${schemaPath}`
113
+ : `[jsonrpc-client-generator] Cannot read ${schemaPath}: ${errorMessage(error)}`);
114
+ return false;
115
+ }
116
+ let schema;
117
+ try {
118
+ schema = JSON.parse(raw);
119
+ }
120
+ catch (error) {
121
+ console.error(`[jsonrpc-client-generator] Invalid JSON in ${schemaPath}: ${errorMessage(error)}`);
122
+ return false;
123
+ }
96
124
  const generated = generateRpcClientFiles(schema, {
97
125
  sourceLabel: options.sourceLabel ?? basename(schemaPath),
98
126
  typesFileName: options.typesFileName,
@@ -117,5 +145,32 @@ function main() {
117
145
  }
118
146
  const extraNote = extraNotes.length > 0 ? ` (+ ${extraNotes.join(', ')})` : '';
119
147
  console.log(`[jsonrpc-client-generator] Generated ${generated.methodCount} RPC method types and schemas${extraNote} -> ${outDir}`);
148
+ return true;
149
+ }
150
+ function errorMessage(error) {
151
+ return error instanceof Error ? error.message : String(error);
152
+ }
153
+ function main() {
154
+ const options = parseArgs(process.argv.slice(2));
155
+ const ok = generateOnce(options);
156
+ if (!options.watch) {
157
+ if (!ok) {
158
+ process.exitCode = 1;
159
+ }
160
+ return;
161
+ }
162
+ const schemaPath = resolve(process.cwd(), options.schemaPath);
163
+ console.log(`[jsonrpc-client-generator] Watching ${schemaPath} for changes (Ctrl+C to stop)…`);
164
+ watchFile(schemaPath, { interval: WATCH_INTERVAL_MS }, (curr, prev) => {
165
+ // mtimeMs === 0 means the file does not currently exist (not yet written, or just deleted); wait for the
166
+ // next write rather than regenerating from a stale/absent file.
167
+ if (curr.mtimeMs === 0) {
168
+ return;
169
+ }
170
+ if (curr.mtimeMs === prev.mtimeMs && curr.size === prev.size) {
171
+ return;
172
+ }
173
+ generateOnce(options);
174
+ });
120
175
  }
121
176
  main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swimmesberger/elarion-jsonrpc-client-generator",
3
- "version": "0.2.3-preview.68.1",
3
+ "version": "0.2.3-preview.69.1",
4
4
  "description": "Generate TypeScript RPC contracts, Zod schemas, and a fetch client from Elarion JSON-RPC schema exports.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",