orpc-fn 0.5.0 → 0.5.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.
- package/README.md +1 -1
- package/dist/cli.js +37 -48
- package/dist/cli.js.map +1 -1
- package/package.json +4 -6
- package/src/cli.ts +47 -57
package/README.md
CHANGED
|
@@ -243,7 +243,7 @@ Sanitized tool-name collisions between distinct procedures throw; identical alia
|
|
|
243
243
|
|
|
244
244
|
## `orpc-fn/cli`
|
|
245
245
|
|
|
246
|
-
|
|
246
|
+
Uses `hanzio/cli`, which orpc-fn depends on (`hanzio` ^3.1.0). Your `defineCli` must come from the same `hanzio` copy, so keep your own `hanzio` on a matching major.
|
|
247
247
|
|
|
248
248
|
```ts
|
|
249
249
|
import { defineCli } from 'hanzio/cli'
|
package/dist/cli.js
CHANGED
|
@@ -1,56 +1,45 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// biome-ignore-all lint/suspicious/noConsole: a CLI reports on the console
|
|
3
2
|
import { readFile, writeFile } from 'node:fs/promises';
|
|
4
3
|
import { resolve } from 'node:path';
|
|
5
4
|
import { pathToFileURL } from 'node:url';
|
|
6
|
-
import {
|
|
5
|
+
import { CliError, defineCli, defineCommand } from 'hanzio/cli';
|
|
6
|
+
import { z } from 'zod';
|
|
7
7
|
import { createStreamManifestAsync, renderStreamManifest } from './router.js';
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
8
|
+
const streamManifest = defineCommand({
|
|
9
|
+
description: "Write the paths of a router's streaming routes for createRpcLink({ streamPaths }), only when they change. Importing the router runs its module code: load .ts routers with bun, tsx or node >= 22.18.",
|
|
10
|
+
input: z.object({
|
|
11
|
+
module: z
|
|
12
|
+
.string()
|
|
13
|
+
.describe('Router module, with #export for a named export')
|
|
14
|
+
.meta({ positional: true }),
|
|
15
|
+
out: z.string().describe('Manifest to write: file.ts or file.json'),
|
|
16
|
+
name: z
|
|
17
|
+
.string()
|
|
18
|
+
.optional()
|
|
19
|
+
.describe('Exported constant name in a .ts file'),
|
|
20
|
+
check: z.boolean().describe('Exit 1 when the file is missing or stale')
|
|
21
|
+
}),
|
|
22
|
+
run: async (input) => {
|
|
23
|
+
const [modulePath = '', exportName = 'default'] = input.module.split('#');
|
|
24
|
+
const loaded = await import(pathToFileURL(resolve(modulePath)).href);
|
|
25
|
+
const router = loaded[exportName];
|
|
26
|
+
if (!router || typeof router !== 'object')
|
|
27
|
+
throw new CliError(`orpc-fn: ${modulePath} has no router export "${exportName}"`, { exitCode: 2 });
|
|
28
|
+
const out = resolve(input.out);
|
|
29
|
+
const source = renderStreamManifest(await createStreamManifestAsync(router), { format: out.endsWith('.json') ? 'json' : 'ts', name: input.name });
|
|
30
|
+
const current = await readFile(out, 'utf8').catch(() => undefined);
|
|
31
|
+
if (current === source)
|
|
32
|
+
return;
|
|
33
|
+
if (input.check)
|
|
34
|
+
throw new CliError(`orpc-fn: ${input.out} is stale; rerun without --check to update it`);
|
|
35
|
+
await writeFile(out, source);
|
|
36
|
+
return `orpc-fn: wrote ${input.out}`;
|
|
30
37
|
}
|
|
31
|
-
const [modulePath = '', exportName = 'default'] = target.split('#');
|
|
32
|
-
const loaded = await import(pathToFileURL(resolve(modulePath)).href);
|
|
33
|
-
const router = loaded[exportName];
|
|
34
|
-
if (!router || typeof router !== 'object') {
|
|
35
|
-
console.error(`orpc-fn: ${modulePath} has no router export "${exportName}"`);
|
|
36
|
-
return 2;
|
|
37
|
-
}
|
|
38
|
-
const out = resolve(values.out);
|
|
39
|
-
const source = renderStreamManifest(await createStreamManifestAsync(router), { format: out.endsWith('.json') ? 'json' : 'ts', name: values.name });
|
|
40
|
-
const current = await readFile(out, 'utf8').catch(() => undefined);
|
|
41
|
-
if (current === source)
|
|
42
|
-
return 0;
|
|
43
|
-
if (values.check) {
|
|
44
|
-
console.error(`orpc-fn: ${values.out} is stale; rerun without --check to update it`);
|
|
45
|
-
return 1;
|
|
46
|
-
}
|
|
47
|
-
await writeFile(out, source);
|
|
48
|
-
console.log(`orpc-fn: wrote ${values.out}`);
|
|
49
|
-
return 0;
|
|
50
|
-
}
|
|
51
|
-
// Exit explicitly: the imported router may hold open database or broker handles.
|
|
52
|
-
run(process.argv.slice(2)).then((code) => process.exit(code), (error) => {
|
|
53
|
-
console.error(error);
|
|
54
|
-
process.exit(1);
|
|
55
38
|
});
|
|
39
|
+
const cli = defineCli({
|
|
40
|
+
name: 'orpc-fn',
|
|
41
|
+
commands: { 'stream-manifest': streamManifest }
|
|
42
|
+
});
|
|
43
|
+
// Exit explicitly: the imported router may hold open database or broker handles.
|
|
44
|
+
process.exit(await cli.run());
|
|
56
45
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAExC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC/D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,yBAAyB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAE7E,MAAM,cAAc,GAAG,aAAa,CAAC;IACpC,WAAW,EACV,uMAAuM;IACxM,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,MAAM,EAAE,CAAC;aACP,MAAM,EAAE;aACR,QAAQ,CAAC,gDAAgD,CAAC;aAC1D,IAAI,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;QAC5B,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yCAAyC,CAAC;QACnE,IAAI,EAAE,CAAC;aACL,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,sCAAsC,CAAC;QAClD,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC;KACvE,CAAC;IACF,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QACpB,MAAM,CAAC,UAAU,GAAG,EAAE,EAAE,UAAU,GAAG,SAAS,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QACzE,MAAM,MAAM,GAA4B,MAAM,MAAM,CACnD,aAAa,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CACvC,CAAA;QACD,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,CAAA;QACjC,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;YACxC,MAAM,IAAI,QAAQ,CACjB,YAAY,UAAU,0BAA0B,UAAU,GAAG,EAC7D,EAAE,QAAQ,EAAE,CAAC,EAAE,CACf,CAAA;QACF,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAC9B,MAAM,MAAM,GAAG,oBAAoB,CAClC,MAAM,yBAAyB,CAAC,MAAmB,CAAC,EACpD,EAAE,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CACnE,CAAA;QACD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAA;QAClE,IAAI,OAAO,KAAK,MAAM;YAAE,OAAM;QAC9B,IAAI,KAAK,CAAC,KAAK;YACd,MAAM,IAAI,QAAQ,CACjB,YAAY,KAAK,CAAC,GAAG,+CAA+C,CACpE,CAAA;QACF,MAAM,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;QAC5B,OAAO,kBAAkB,KAAK,CAAC,GAAG,EAAE,CAAA;IACrC,CAAC;CACD,CAAC,CAAA;AAEF,MAAM,GAAG,GAAG,SAAS,CAAC;IACrB,IAAI,EAAE,SAAS;IACf,QAAQ,EAAE,EAAE,iBAAiB,EAAE,cAAc,EAAE;CAC/C,CAAC,CAAA;AAEF,iFAAiF;AACjF,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,EAAE,CAAC,CAAA","sourcesContent":["#!/usr/bin/env node\nimport { readFile, writeFile } from 'node:fs/promises'\nimport { resolve } from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport type { AnyRouter } from '@orpc/server'\nimport { CliError, defineCli, defineCommand } from 'hanzio/cli'\nimport { z } from 'zod'\nimport { createStreamManifestAsync, renderStreamManifest } from './router.js'\n\nconst streamManifest = defineCommand({\n\tdescription:\n\t\t\"Write the paths of a router's streaming routes for createRpcLink({ streamPaths }), only when they change. Importing the router runs its module code: load .ts routers with bun, tsx or node >= 22.18.\",\n\tinput: z.object({\n\t\tmodule: z\n\t\t\t.string()\n\t\t\t.describe('Router module, with #export for a named export')\n\t\t\t.meta({ positional: true }),\n\t\tout: z.string().describe('Manifest to write: file.ts or file.json'),\n\t\tname: z\n\t\t\t.string()\n\t\t\t.optional()\n\t\t\t.describe('Exported constant name in a .ts file'),\n\t\tcheck: z.boolean().describe('Exit 1 when the file is missing or stale')\n\t}),\n\trun: async (input) => {\n\t\tconst [modulePath = '', exportName = 'default'] = input.module.split('#')\n\t\tconst loaded: Record<string, unknown> = await import(\n\t\t\tpathToFileURL(resolve(modulePath)).href\n\t\t)\n\t\tconst router = loaded[exportName]\n\t\tif (!router || typeof router !== 'object')\n\t\t\tthrow new CliError(\n\t\t\t\t`orpc-fn: ${modulePath} has no router export \"${exportName}\"`,\n\t\t\t\t{ exitCode: 2 }\n\t\t\t)\n\t\tconst out = resolve(input.out)\n\t\tconst source = renderStreamManifest(\n\t\t\tawait createStreamManifestAsync(router as AnyRouter),\n\t\t\t{ format: out.endsWith('.json') ? 'json' : 'ts', name: input.name }\n\t\t)\n\t\tconst current = await readFile(out, 'utf8').catch(() => undefined)\n\t\tif (current === source) return\n\t\tif (input.check)\n\t\t\tthrow new CliError(\n\t\t\t\t`orpc-fn: ${input.out} is stale; rerun without --check to update it`\n\t\t\t)\n\t\tawait writeFile(out, source)\n\t\treturn `orpc-fn: wrote ${input.out}`\n\t}\n})\n\nconst cli = defineCli({\n\tname: 'orpc-fn',\n\tcommands: { 'stream-manifest': streamManifest }\n})\n\n// Exit explicitly: the imported router may hold open database or broker handles.\nprocess.exit(await cli.run())\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orpc-fn",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "Define a backend function once: a typed oRPC procedure with tracing, logging, guards, injected handler extras, nested calls and live queries over Redis.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -127,6 +127,9 @@
|
|
|
127
127
|
"test:types-performance": "bun scripts/check-types-performance.ts",
|
|
128
128
|
"test:client-bundle": "bun scripts/check-client-bundle.ts"
|
|
129
129
|
},
|
|
130
|
+
"dependencies": {
|
|
131
|
+
"hanzio": "^3.1.0"
|
|
132
|
+
},
|
|
130
133
|
"peerDependencies": {
|
|
131
134
|
"@mastra/core": "^1.51.0",
|
|
132
135
|
"@opentelemetry/api": "^1.9.0",
|
|
@@ -136,7 +139,6 @@
|
|
|
136
139
|
"@orpc/openapi": "^1.14.0",
|
|
137
140
|
"@orpc/server": "^1.14.0",
|
|
138
141
|
"@orpc/zod": "^1.14.0",
|
|
139
|
-
"hanzio": "^3.1.0",
|
|
140
142
|
"hono": "^4.0.0",
|
|
141
143
|
"ioredis": "^5.0.0",
|
|
142
144
|
"zod": "^4.0.0",
|
|
@@ -163,9 +165,6 @@
|
|
|
163
165
|
"@orpc/zod": {
|
|
164
166
|
"optional": true
|
|
165
167
|
},
|
|
166
|
-
"hanzio": {
|
|
167
|
-
"optional": true
|
|
168
|
-
},
|
|
169
168
|
"hono": {
|
|
170
169
|
"optional": true
|
|
171
170
|
},
|
|
@@ -212,7 +211,6 @@
|
|
|
212
211
|
"@types/node": "^22.0.0",
|
|
213
212
|
"@types/react": "19",
|
|
214
213
|
"@types/react-test-renderer": "19",
|
|
215
|
-
"hanzio": "^3.1.0",
|
|
216
214
|
"hono": "^4.12.31",
|
|
217
215
|
"ioredis": "5.8.2",
|
|
218
216
|
"publint": "^0.3.12",
|
package/src/cli.ts
CHANGED
|
@@ -1,68 +1,58 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// biome-ignore-all lint/suspicious/noConsole: a CLI reports on the console
|
|
3
2
|
import { readFile, writeFile } from 'node:fs/promises'
|
|
4
3
|
import { resolve } from 'node:path'
|
|
5
4
|
import { pathToFileURL } from 'node:url'
|
|
6
|
-
import { parseArgs } from 'node:util'
|
|
7
5
|
import type { AnyRouter } from '@orpc/server'
|
|
6
|
+
import { CliError, defineCli, defineCommand } from 'hanzio/cli'
|
|
7
|
+
import { z } from 'zod'
|
|
8
8
|
import { createStreamManifestAsync, renderStreamManifest } from './router.js'
|
|
9
9
|
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const [command, target] = positionals
|
|
30
|
-
if (values.help || command !== 'stream-manifest' || !target || !values.out) {
|
|
31
|
-
console.error(usage)
|
|
32
|
-
return values.help ? 0 : 2
|
|
33
|
-
}
|
|
34
|
-
const [modulePath = '', exportName = 'default'] = target.split('#')
|
|
35
|
-
const loaded: Record<string, unknown> = await import(
|
|
36
|
-
pathToFileURL(resolve(modulePath)).href
|
|
37
|
-
)
|
|
38
|
-
const router = loaded[exportName]
|
|
39
|
-
if (!router || typeof router !== 'object') {
|
|
40
|
-
console.error(`orpc-fn: ${modulePath} has no router export "${exportName}"`)
|
|
41
|
-
return 2
|
|
42
|
-
}
|
|
43
|
-
const out = resolve(values.out)
|
|
44
|
-
const source = renderStreamManifest(
|
|
45
|
-
await createStreamManifestAsync(router as AnyRouter),
|
|
46
|
-
{ format: out.endsWith('.json') ? 'json' : 'ts', name: values.name }
|
|
47
|
-
)
|
|
48
|
-
const current = await readFile(out, 'utf8').catch(() => undefined)
|
|
49
|
-
if (current === source) return 0
|
|
50
|
-
if (values.check) {
|
|
51
|
-
console.error(
|
|
52
|
-
`orpc-fn: ${values.out} is stale; rerun without --check to update it`
|
|
10
|
+
const streamManifest = defineCommand({
|
|
11
|
+
description:
|
|
12
|
+
"Write the paths of a router's streaming routes for createRpcLink({ streamPaths }), only when they change. Importing the router runs its module code: load .ts routers with bun, tsx or node >= 22.18.",
|
|
13
|
+
input: z.object({
|
|
14
|
+
module: z
|
|
15
|
+
.string()
|
|
16
|
+
.describe('Router module, with #export for a named export')
|
|
17
|
+
.meta({ positional: true }),
|
|
18
|
+
out: z.string().describe('Manifest to write: file.ts or file.json'),
|
|
19
|
+
name: z
|
|
20
|
+
.string()
|
|
21
|
+
.optional()
|
|
22
|
+
.describe('Exported constant name in a .ts file'),
|
|
23
|
+
check: z.boolean().describe('Exit 1 when the file is missing or stale')
|
|
24
|
+
}),
|
|
25
|
+
run: async (input) => {
|
|
26
|
+
const [modulePath = '', exportName = 'default'] = input.module.split('#')
|
|
27
|
+
const loaded: Record<string, unknown> = await import(
|
|
28
|
+
pathToFileURL(resolve(modulePath)).href
|
|
53
29
|
)
|
|
54
|
-
|
|
30
|
+
const router = loaded[exportName]
|
|
31
|
+
if (!router || typeof router !== 'object')
|
|
32
|
+
throw new CliError(
|
|
33
|
+
`orpc-fn: ${modulePath} has no router export "${exportName}"`,
|
|
34
|
+
{ exitCode: 2 }
|
|
35
|
+
)
|
|
36
|
+
const out = resolve(input.out)
|
|
37
|
+
const source = renderStreamManifest(
|
|
38
|
+
await createStreamManifestAsync(router as AnyRouter),
|
|
39
|
+
{ format: out.endsWith('.json') ? 'json' : 'ts', name: input.name }
|
|
40
|
+
)
|
|
41
|
+
const current = await readFile(out, 'utf8').catch(() => undefined)
|
|
42
|
+
if (current === source) return
|
|
43
|
+
if (input.check)
|
|
44
|
+
throw new CliError(
|
|
45
|
+
`orpc-fn: ${input.out} is stale; rerun without --check to update it`
|
|
46
|
+
)
|
|
47
|
+
await writeFile(out, source)
|
|
48
|
+
return `orpc-fn: wrote ${input.out}`
|
|
55
49
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
const cli = defineCli({
|
|
53
|
+
name: 'orpc-fn',
|
|
54
|
+
commands: { 'stream-manifest': streamManifest }
|
|
55
|
+
})
|
|
60
56
|
|
|
61
57
|
// Exit explicitly: the imported router may hold open database or broker handles.
|
|
62
|
-
|
|
63
|
-
(code) => process.exit(code),
|
|
64
|
-
(error) => {
|
|
65
|
-
console.error(error)
|
|
66
|
-
process.exit(1)
|
|
67
|
-
}
|
|
68
|
-
)
|
|
58
|
+
process.exit(await cli.run())
|