ts-procedures 5.9.1 → 5.10.2
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/agent_config/bin/postinstall.mjs +3 -3
- package/agent_config/bin/setup.mjs +22 -11
- package/agent_config/claude-code/agents/ts-procedures-architect.md +46 -101
- package/agent_config/claude-code/skills/{guide → ts-procedures}/SKILL.md +50 -35
- package/agent_config/claude-code/skills/{guide → ts-procedures}/anti-patterns.md +6 -5
- package/agent_config/claude-code/skills/{guide → ts-procedures}/api-reference.md +60 -49
- package/agent_config/claude-code/skills/ts-procedures-review/SKILL.md +48 -0
- package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/SKILL.md +19 -24
- package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/client.md +115 -0
- package/agent_config/lib/install-claude.mjs +35 -87
- package/build/src/client/call.d.ts +14 -0
- package/build/src/client/call.js +47 -0
- package/build/src/client/call.js.map +1 -0
- package/build/src/client/call.test.d.ts +1 -0
- package/build/src/client/call.test.js +124 -0
- package/build/src/client/call.test.js.map +1 -0
- package/build/src/client/errors.d.ts +25 -0
- package/build/src/client/errors.js +33 -0
- package/build/src/client/errors.js.map +1 -0
- package/build/src/client/errors.test.d.ts +1 -0
- package/build/src/client/errors.test.js +41 -0
- package/build/src/client/errors.test.js.map +1 -0
- package/build/src/client/fetch-adapter.d.ts +12 -0
- package/build/src/client/fetch-adapter.js +156 -0
- package/build/src/client/fetch-adapter.js.map +1 -0
- package/build/src/client/fetch-adapter.test.d.ts +1 -0
- package/build/src/client/fetch-adapter.test.js +271 -0
- package/build/src/client/fetch-adapter.test.js.map +1 -0
- package/build/src/client/hooks.d.ts +17 -0
- package/build/src/client/hooks.js +40 -0
- package/build/src/client/hooks.js.map +1 -0
- package/build/src/client/hooks.test.d.ts +1 -0
- package/build/src/client/hooks.test.js +163 -0
- package/build/src/client/hooks.test.js.map +1 -0
- package/build/src/client/index.d.ts +22 -0
- package/build/src/client/index.js +67 -0
- package/build/src/client/index.js.map +1 -0
- package/build/src/client/index.test.d.ts +1 -0
- package/build/src/client/index.test.js +231 -0
- package/build/src/client/index.test.js.map +1 -0
- package/build/src/client/request-builder.d.ts +13 -0
- package/build/src/client/request-builder.js +53 -0
- package/build/src/client/request-builder.js.map +1 -0
- package/build/src/client/request-builder.test.d.ts +1 -0
- package/build/src/client/request-builder.test.js +160 -0
- package/build/src/client/request-builder.test.js.map +1 -0
- package/build/src/client/stream.d.ts +27 -0
- package/build/src/client/stream.js +118 -0
- package/build/src/client/stream.js.map +1 -0
- package/build/src/client/stream.test.d.ts +1 -0
- package/build/src/client/stream.test.js +228 -0
- package/build/src/client/stream.test.js.map +1 -0
- package/build/src/client/types.d.ts +78 -0
- package/build/src/client/types.js +3 -0
- package/build/src/client/types.js.map +1 -0
- package/build/src/codegen/bin/cli.d.ts +45 -0
- package/build/src/codegen/bin/cli.js +246 -0
- package/build/src/codegen/bin/cli.js.map +1 -0
- package/build/src/codegen/bin/cli.test.d.ts +1 -0
- package/build/src/codegen/bin/cli.test.js +220 -0
- package/build/src/codegen/bin/cli.test.js.map +1 -0
- package/build/src/codegen/constants.d.ts +1 -0
- package/build/src/codegen/constants.js +2 -0
- package/build/src/codegen/constants.js.map +1 -0
- package/build/src/codegen/e2e.test.d.ts +1 -0
- package/build/src/codegen/e2e.test.js +464 -0
- package/build/src/codegen/e2e.test.js.map +1 -0
- package/build/src/codegen/emit-client-runtime.d.ts +9 -0
- package/build/src/codegen/emit-client-runtime.js +99 -0
- package/build/src/codegen/emit-client-runtime.js.map +1 -0
- package/build/src/codegen/emit-client-runtime.test.d.ts +1 -0
- package/build/src/codegen/emit-client-runtime.test.js +78 -0
- package/build/src/codegen/emit-client-runtime.test.js.map +1 -0
- package/build/src/codegen/emit-client-types.d.ts +8 -0
- package/build/src/codegen/emit-client-types.js +25 -0
- package/build/src/codegen/emit-client-types.js.map +1 -0
- package/build/src/codegen/emit-client-types.test.d.ts +1 -0
- package/build/src/codegen/emit-client-types.test.js +33 -0
- package/build/src/codegen/emit-client-types.test.js.map +1 -0
- package/build/src/codegen/emit-errors.d.ts +19 -0
- package/build/src/codegen/emit-errors.js +59 -0
- package/build/src/codegen/emit-errors.js.map +1 -0
- package/build/src/codegen/emit-errors.test.d.ts +1 -0
- package/build/src/codegen/emit-errors.test.js +175 -0
- package/build/src/codegen/emit-errors.test.js.map +1 -0
- package/build/src/codegen/emit-index.d.ts +12 -0
- package/build/src/codegen/emit-index.js +41 -0
- package/build/src/codegen/emit-index.js.map +1 -0
- package/build/src/codegen/emit-index.test.d.ts +1 -0
- package/build/src/codegen/emit-index.test.js +106 -0
- package/build/src/codegen/emit-index.test.js.map +1 -0
- package/build/src/codegen/emit-scope.d.ts +15 -0
- package/build/src/codegen/emit-scope.js +299 -0
- package/build/src/codegen/emit-scope.js.map +1 -0
- package/build/src/codegen/emit-scope.test.d.ts +1 -0
- package/build/src/codegen/emit-scope.test.js +559 -0
- package/build/src/codegen/emit-scope.test.js.map +1 -0
- package/build/src/codegen/emit-types.d.ts +43 -0
- package/build/src/codegen/emit-types.js +111 -0
- package/build/src/codegen/emit-types.js.map +1 -0
- package/build/src/codegen/emit-types.test.d.ts +1 -0
- package/build/src/codegen/emit-types.test.js +184 -0
- package/build/src/codegen/emit-types.test.js.map +1 -0
- package/build/src/codegen/group-routes.d.ts +23 -0
- package/build/src/codegen/group-routes.js +46 -0
- package/build/src/codegen/group-routes.js.map +1 -0
- package/build/src/codegen/group-routes.test.d.ts +1 -0
- package/build/src/codegen/group-routes.test.js +131 -0
- package/build/src/codegen/group-routes.test.js.map +1 -0
- package/build/src/codegen/index.d.ts +15 -0
- package/build/src/codegen/index.js +16 -0
- package/build/src/codegen/index.js.map +1 -0
- package/build/src/codegen/naming.d.ts +7 -0
- package/build/src/codegen/naming.js +21 -0
- package/build/src/codegen/naming.js.map +1 -0
- package/build/src/codegen/naming.test.d.ts +1 -0
- package/build/src/codegen/naming.test.js +40 -0
- package/build/src/codegen/naming.test.js.map +1 -0
- package/build/src/codegen/pipeline.d.ts +17 -0
- package/build/src/codegen/pipeline.js +78 -0
- package/build/src/codegen/pipeline.js.map +1 -0
- package/build/src/codegen/pipeline.test.d.ts +1 -0
- package/build/src/codegen/pipeline.test.js +269 -0
- package/build/src/codegen/pipeline.test.js.map +1 -0
- package/build/src/codegen/resolve-envelope.d.ts +7 -0
- package/build/src/codegen/resolve-envelope.js +46 -0
- package/build/src/codegen/resolve-envelope.js.map +1 -0
- package/build/src/codegen/resolve-envelope.test.d.ts +1 -0
- package/build/src/codegen/resolve-envelope.test.js +69 -0
- package/build/src/codegen/resolve-envelope.test.js.map +1 -0
- package/build/src/errors.d.ts +33 -0
- package/build/src/errors.js +91 -0
- package/build/src/errors.js.map +1 -0
- package/build/src/errors.test.d.ts +1 -0
- package/build/src/errors.test.js +122 -0
- package/build/src/errors.test.js.map +1 -0
- package/build/src/exports.d.ts +7 -0
- package/build/src/exports.js +8 -0
- package/build/src/exports.js.map +1 -0
- package/build/src/implementations/http/doc-registry.d.ts +12 -0
- package/build/src/implementations/http/doc-registry.js +114 -0
- package/build/src/implementations/http/doc-registry.js.map +1 -0
- package/build/src/implementations/http/doc-registry.test.d.ts +1 -0
- package/build/src/implementations/http/doc-registry.test.js +347 -0
- package/build/src/implementations/http/doc-registry.test.js.map +1 -0
- package/build/src/implementations/http/express-rpc/index.d.ts +94 -0
- package/build/src/implementations/http/express-rpc/index.js +185 -0
- package/build/src/implementations/http/express-rpc/index.js.map +1 -0
- package/build/src/implementations/http/express-rpc/index.test.d.ts +1 -0
- package/build/src/implementations/http/express-rpc/index.test.js +684 -0
- package/build/src/implementations/http/express-rpc/index.test.js.map +1 -0
- package/build/src/implementations/http/express-rpc/types.d.ts +11 -0
- package/build/src/implementations/http/express-rpc/types.js +2 -0
- package/build/src/implementations/http/express-rpc/types.js.map +1 -0
- package/build/src/implementations/http/hono-api/index.d.ts +102 -0
- package/build/src/implementations/http/hono-api/index.js +341 -0
- package/build/src/implementations/http/hono-api/index.js.map +1 -0
- package/build/src/implementations/http/hono-api/index.test.d.ts +1 -0
- package/build/src/implementations/http/hono-api/index.test.js +992 -0
- package/build/src/implementations/http/hono-api/index.test.js.map +1 -0
- package/build/src/implementations/http/hono-api/types.d.ts +13 -0
- package/build/src/implementations/http/hono-api/types.js +2 -0
- package/build/src/implementations/http/hono-api/types.js.map +1 -0
- package/build/src/implementations/http/hono-rpc/index.d.ts +92 -0
- package/build/src/implementations/http/hono-rpc/index.js +161 -0
- package/build/src/implementations/http/hono-rpc/index.js.map +1 -0
- package/build/src/implementations/http/hono-rpc/index.test.d.ts +1 -0
- package/build/src/implementations/http/hono-rpc/index.test.js +803 -0
- package/build/src/implementations/http/hono-rpc/index.test.js.map +1 -0
- package/build/src/implementations/http/hono-rpc/types.d.ts +11 -0
- package/build/src/implementations/http/hono-rpc/types.js +2 -0
- package/build/src/implementations/http/hono-rpc/types.js.map +1 -0
- package/build/src/implementations/http/hono-stream/index.d.ts +120 -0
- package/build/src/implementations/http/hono-stream/index.js +309 -0
- package/build/src/implementations/http/hono-stream/index.js.map +1 -0
- package/build/src/implementations/http/hono-stream/index.test.d.ts +1 -0
- package/build/src/implementations/http/hono-stream/index.test.js +1356 -0
- package/build/src/implementations/http/hono-stream/index.test.js.map +1 -0
- package/build/src/implementations/http/hono-stream/types.d.ts +15 -0
- package/build/src/implementations/http/hono-stream/types.js +2 -0
- package/build/src/implementations/http/hono-stream/types.js.map +1 -0
- package/build/src/implementations/types.d.ts +142 -0
- package/build/src/implementations/types.js +2 -0
- package/build/src/implementations/types.js.map +1 -0
- package/build/src/index.d.ts +165 -0
- package/build/src/index.js +253 -0
- package/build/src/index.js.map +1 -0
- package/build/src/index.test.d.ts +1 -0
- package/build/src/index.test.js +890 -0
- package/build/src/index.test.js.map +1 -0
- package/build/src/schema/compute-schema.d.ts +35 -0
- package/build/src/schema/compute-schema.js +41 -0
- package/build/src/schema/compute-schema.js.map +1 -0
- package/build/src/schema/compute-schema.test.d.ts +1 -0
- package/build/src/schema/compute-schema.test.js +107 -0
- package/build/src/schema/compute-schema.test.js.map +1 -0
- package/build/src/schema/extract-json-schema.d.ts +2 -0
- package/build/src/schema/extract-json-schema.js +12 -0
- package/build/src/schema/extract-json-schema.js.map +1 -0
- package/build/src/schema/extract-json-schema.test.d.ts +1 -0
- package/build/src/schema/extract-json-schema.test.js +23 -0
- package/build/src/schema/extract-json-schema.test.js.map +1 -0
- package/build/src/schema/parser.d.ts +28 -0
- package/build/src/schema/parser.js +170 -0
- package/build/src/schema/parser.js.map +1 -0
- package/build/src/schema/parser.test.d.ts +1 -0
- package/build/src/schema/parser.test.js +120 -0
- package/build/src/schema/parser.test.js.map +1 -0
- package/build/src/schema/resolve-schema-lib.d.ts +12 -0
- package/build/src/schema/resolve-schema-lib.js +11 -0
- package/build/src/schema/resolve-schema-lib.js.map +1 -0
- package/build/src/schema/resolve-schema-lib.test.d.ts +1 -0
- package/build/src/schema/resolve-schema-lib.test.js +17 -0
- package/build/src/schema/resolve-schema-lib.test.js.map +1 -0
- package/build/src/schema/types.d.ts +8 -0
- package/build/src/schema/types.js +2 -0
- package/build/src/schema/types.js.map +1 -0
- package/build/src/stack-utils.d.ts +25 -0
- package/build/src/stack-utils.js +95 -0
- package/build/src/stack-utils.js.map +1 -0
- package/build/src/stack-utils.test.d.ts +1 -0
- package/build/src/stack-utils.test.js +80 -0
- package/build/src/stack-utils.test.js.map +1 -0
- package/docs/ai-agent-setup.md +7 -6
- package/docs/core.md +5 -9
- package/docs/streaming.md +9 -9
- package/package.json +2 -13
- package/src/client/call.test.ts +162 -0
- package/src/client/errors.test.ts +43 -0
- package/src/client/fetch-adapter.test.ts +340 -0
- package/src/client/hooks.test.ts +191 -0
- package/src/client/index.test.ts +290 -0
- package/src/client/request-builder.test.ts +184 -0
- package/src/client/stream.test.ts +331 -0
- package/src/codegen/bin/cli.test.ts +260 -0
- package/src/codegen/bin/cli.ts +282 -0
- package/src/codegen/constants.ts +1 -0
- package/src/codegen/e2e.test.ts +565 -0
- package/src/codegen/emit-client-runtime.test.ts +93 -0
- package/src/codegen/emit-client-runtime.ts +114 -0
- package/src/codegen/emit-client-types.test.ts +39 -0
- package/src/codegen/emit-client-types.ts +27 -0
- package/src/codegen/emit-errors.test.ts +202 -0
- package/src/codegen/emit-errors.ts +80 -0
- package/src/codegen/emit-index.test.ts +127 -0
- package/src/codegen/emit-index.ts +58 -0
- package/src/codegen/emit-scope.test.ts +624 -0
- package/src/codegen/emit-scope.ts +389 -0
- package/src/codegen/emit-types.test.ts +205 -0
- package/src/codegen/emit-types.ts +158 -0
- package/src/codegen/group-routes.test.ts +159 -0
- package/src/codegen/group-routes.ts +61 -0
- package/src/codegen/index.ts +30 -0
- package/src/codegen/naming.test.ts +50 -0
- package/src/codegen/naming.ts +25 -0
- package/src/codegen/pipeline.test.ts +316 -0
- package/src/codegen/pipeline.ts +108 -0
- package/src/codegen/resolve-envelope.test.ts +76 -0
- package/src/codegen/resolve-envelope.ts +61 -0
- package/src/errors.test.ts +163 -0
- package/src/errors.ts +107 -0
- package/src/exports.ts +7 -0
- package/src/implementations/http/doc-registry.test.ts +415 -0
- package/src/implementations/http/doc-registry.ts +143 -0
- package/src/implementations/http/express-rpc/README.md +6 -6
- package/src/implementations/http/express-rpc/index.test.ts +957 -0
- package/src/implementations/http/express-rpc/index.ts +266 -0
- package/src/implementations/http/express-rpc/types.ts +16 -0
- package/src/implementations/http/hono-api/index.test.ts +1341 -0
- package/src/implementations/http/hono-api/index.ts +463 -0
- package/src/implementations/http/hono-api/types.ts +16 -0
- package/src/implementations/http/hono-rpc/README.md +6 -6
- package/src/implementations/http/hono-rpc/index.test.ts +1075 -0
- package/src/implementations/http/hono-rpc/index.ts +238 -0
- package/src/implementations/http/hono-rpc/types.ts +16 -0
- package/src/implementations/http/hono-stream/README.md +12 -12
- package/src/implementations/http/hono-stream/index.test.ts +1768 -0
- package/src/implementations/http/hono-stream/index.ts +456 -0
- package/src/implementations/http/hono-stream/types.ts +20 -0
- package/src/implementations/types.ts +174 -0
- package/src/index.test.ts +1185 -0
- package/src/index.ts +522 -0
- package/src/schema/compute-schema.test.ts +128 -0
- package/src/schema/compute-schema.ts +88 -0
- package/src/schema/extract-json-schema.test.ts +25 -0
- package/src/schema/extract-json-schema.ts +15 -0
- package/src/schema/parser.test.ts +182 -0
- package/src/schema/parser.ts +215 -0
- package/src/schema/resolve-schema-lib.test.ts +19 -0
- package/src/schema/resolve-schema-lib.ts +29 -0
- package/src/schema/types.ts +20 -0
- package/src/stack-utils.test.ts +94 -0
- package/src/stack-utils.ts +129 -0
- package/agent_config/claude-code/skills/review/SKILL.md +0 -53
- package/docs/superpowers/plans/2026-03-30-client-codegen.md +0 -2833
- package/docs/superpowers/specs/2026-03-30-client-codegen-design.md +0 -632
- /package/agent_config/claude-code/skills/{guide → ts-procedures}/patterns.md +0 -0
- /package/agent_config/claude-code/skills/{review → ts-procedures-review}/checklist.md +0 -0
- /package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/templates/express-rpc.md +0 -0
- /package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/templates/hono-api.md +0 -0
- /package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/templates/hono-rpc.md +0 -0
- /package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/templates/hono-stream.md +0 -0
- /package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/templates/procedure.md +0 -0
- /package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/templates/stream-procedure.md +0 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { toPascalCase, validateServiceName } from './naming.js';
|
|
3
|
+
describe('toPascalCase', () => {
|
|
4
|
+
it('converts a single word', () => {
|
|
5
|
+
expect(toPascalCase('auth')).toBe('Auth');
|
|
6
|
+
});
|
|
7
|
+
it('converts hyphen-separated words', () => {
|
|
8
|
+
expect(toPascalCase('auth-service')).toBe('AuthService');
|
|
9
|
+
});
|
|
10
|
+
it('converts underscore-separated words', () => {
|
|
11
|
+
expect(toPascalCase('users_api')).toBe('UsersApi');
|
|
12
|
+
});
|
|
13
|
+
it('converts space-separated words', () => {
|
|
14
|
+
expect(toPascalCase('my service')).toBe('MyService');
|
|
15
|
+
});
|
|
16
|
+
it('preserves already-PascalCased input', () => {
|
|
17
|
+
expect(toPascalCase('UsersApi')).toBe('UsersApi');
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
describe('validateServiceName', () => {
|
|
21
|
+
it('accepts a valid PascalCase name', () => {
|
|
22
|
+
expect(() => validateServiceName('Auth')).not.toThrow();
|
|
23
|
+
});
|
|
24
|
+
it('accepts a hyphen-separated name', () => {
|
|
25
|
+
expect(() => validateServiceName('auth-service')).not.toThrow();
|
|
26
|
+
});
|
|
27
|
+
it('accepts an underscore-separated name', () => {
|
|
28
|
+
expect(() => validateServiceName('users_api')).not.toThrow();
|
|
29
|
+
});
|
|
30
|
+
it('throws for an empty string', () => {
|
|
31
|
+
expect(() => validateServiceName('')).toThrow('empty');
|
|
32
|
+
});
|
|
33
|
+
it('throws for a string of only separators', () => {
|
|
34
|
+
expect(() => validateServiceName('---')).toThrow('empty');
|
|
35
|
+
});
|
|
36
|
+
it('throws when the result starts with a digit', () => {
|
|
37
|
+
expect(() => validateServiceName('123service')).toThrow('starts with a digit');
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
//# sourceMappingURL=naming.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"naming.test.js","sourceRoot":"","sources":["../../../src/codegen/naming.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAE/D,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAC3C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;IAC1D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IACpD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,MAAM,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;IACtD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IACnD,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,CAAC,GAAG,EAAE,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAA;IACzD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,CAAC,GAAG,EAAE,CAAC,mBAAmB,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAA;IACjE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,GAAG,EAAE,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAA;IAC9D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,GAAG,EAAE,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IACxD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,CAAC,GAAG,EAAE,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IAC3D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,CAAC,GAAG,EAAE,CAAC,mBAAmB,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAA;IAChF,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { DocEnvelope } from '../implementations/types.js';
|
|
2
|
+
import type { AjscOptions } from './emit-types.js';
|
|
3
|
+
export interface PipelineOptions {
|
|
4
|
+
envelope: DocEnvelope;
|
|
5
|
+
outDir: string;
|
|
6
|
+
ajsc?: AjscOptions;
|
|
7
|
+
clientImportPath?: string;
|
|
8
|
+
dryRun?: boolean;
|
|
9
|
+
namespaceTypes?: boolean;
|
|
10
|
+
selfContained?: boolean;
|
|
11
|
+
serviceName?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface GeneratedFile {
|
|
14
|
+
path: string;
|
|
15
|
+
code: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function runPipeline(options: PipelineOptions): Promise<GeneratedFile[]>;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { createHash } from 'node:crypto';
|
|
4
|
+
import { groupRoutesByScope } from './group-routes.js';
|
|
5
|
+
import { emitScopeFile } from './emit-scope.js';
|
|
6
|
+
import { emitIndexFile } from './emit-index.js';
|
|
7
|
+
import { emitErrorsFile } from './emit-errors.js';
|
|
8
|
+
import { emitClientTypesFile } from './emit-client-types.js';
|
|
9
|
+
import { emitClientRuntimeFile } from './emit-client-runtime.js';
|
|
10
|
+
import { validateServiceName } from './naming.js';
|
|
11
|
+
export async function runPipeline(options) {
|
|
12
|
+
const { envelope, outDir, ajsc: ajscOpts, dryRun = false, namespaceTypes = false, selfContained = false, serviceName } = options;
|
|
13
|
+
if (serviceName != null) {
|
|
14
|
+
validateServiceName(serviceName);
|
|
15
|
+
}
|
|
16
|
+
const clientImportPath = selfContained ? './_types' : options.clientImportPath;
|
|
17
|
+
if (selfContained && options.clientImportPath != null) {
|
|
18
|
+
console.warn('[ts-procedures-codegen] --self-contained overrides --client-import-path; using ./_types');
|
|
19
|
+
}
|
|
20
|
+
const hash = createHash('md5').update(JSON.stringify(envelope)).digest('hex');
|
|
21
|
+
const hashComment = `// Source hash: ${hash}`;
|
|
22
|
+
const groups = groupRoutesByScope(envelope.routes);
|
|
23
|
+
const groupArray = Array.from(groups.values());
|
|
24
|
+
if (selfContained) {
|
|
25
|
+
for (const group of groupArray) {
|
|
26
|
+
if (group.scopeKey === '_types' || group.scopeKey === '_client') {
|
|
27
|
+
throw new Error(`[ts-procedures-codegen] Scope "${group.scopeKey}" conflicts with self-contained mode reserved filename "${group.scopeKey}.ts". Rename the scope to avoid collision.`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const files = [];
|
|
32
|
+
for (const group of groupArray) {
|
|
33
|
+
const rawCode = await emitScopeFile(group, { ajsc: ajscOpts, clientImportPath, namespaceTypes });
|
|
34
|
+
const lines = rawCode.split('\n');
|
|
35
|
+
lines.splice(1, 0, hashComment);
|
|
36
|
+
const code = lines.join('\n');
|
|
37
|
+
files.push({ path: join(outDir, `${group.scopeKey}.ts`), code });
|
|
38
|
+
}
|
|
39
|
+
const errorsCode = await emitErrorsFile(envelope.errors, { ajsc: ajscOpts, clientImportPath, namespaceTypes, serviceName });
|
|
40
|
+
const hasErrors = errorsCode != null;
|
|
41
|
+
if (errorsCode != null) {
|
|
42
|
+
const errorsLines = errorsCode.split('\n');
|
|
43
|
+
errorsLines.splice(1, 0, hashComment);
|
|
44
|
+
const errorsWithHash = errorsLines.join('\n');
|
|
45
|
+
files.push({ path: join(outDir, '_errors.ts'), code: errorsWithHash });
|
|
46
|
+
}
|
|
47
|
+
const rawIndexCode = emitIndexFile(groupArray, { clientImportPath, hasErrors, serviceName });
|
|
48
|
+
const indexLines = rawIndexCode.split('\n');
|
|
49
|
+
indexLines.splice(1, 0, hashComment);
|
|
50
|
+
const indexCode = indexLines.join('\n');
|
|
51
|
+
files.push({ path: join(outDir, 'index.ts'), code: indexCode });
|
|
52
|
+
if (selfContained) {
|
|
53
|
+
const rawTypesCode = await emitClientTypesFile();
|
|
54
|
+
const typesLines = rawTypesCode.split('\n');
|
|
55
|
+
typesLines.splice(1, 0, hashComment);
|
|
56
|
+
const typesCode = typesLines.join('\n');
|
|
57
|
+
files.push({ path: join(outDir, '_types.ts'), code: typesCode });
|
|
58
|
+
const rawClientCode = await emitClientRuntimeFile();
|
|
59
|
+
const clientLines = rawClientCode.split('\n');
|
|
60
|
+
clientLines.splice(1, 0, hashComment);
|
|
61
|
+
const clientCode = clientLines.join('\n');
|
|
62
|
+
files.push({ path: join(outDir, '_client.ts'), code: clientCode });
|
|
63
|
+
}
|
|
64
|
+
if (dryRun) {
|
|
65
|
+
for (const file of files) {
|
|
66
|
+
const bytes = Buffer.byteLength(file.code, 'utf-8');
|
|
67
|
+
console.log(`[dry-run] Would write: ${file.path} (${bytes} bytes)`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
await mkdir(outDir, { recursive: true });
|
|
72
|
+
for (const file of files) {
|
|
73
|
+
await writeFile(file.path, file.code, 'utf-8');
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return files;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=pipeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../../src/codegen/pipeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import { describe, it, expect, afterEach, vi } from 'vitest';
|
|
2
|
+
import { generateClient } from './index.js';
|
|
3
|
+
import { runPipeline } from './pipeline.js';
|
|
4
|
+
import { mkdirSync, rmSync, readFileSync, existsSync } from 'node:fs';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import { tmpdir } from 'node:os';
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
// Fixtures
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
const envelope = {
|
|
11
|
+
basePath: '/api',
|
|
12
|
+
headers: [],
|
|
13
|
+
errors: [],
|
|
14
|
+
routes: [
|
|
15
|
+
{
|
|
16
|
+
kind: 'rpc',
|
|
17
|
+
name: 'GetUser',
|
|
18
|
+
path: '/users/1',
|
|
19
|
+
method: 'post',
|
|
20
|
+
scope: 'users',
|
|
21
|
+
version: 1,
|
|
22
|
+
jsonSchema: {
|
|
23
|
+
body: {
|
|
24
|
+
type: 'object',
|
|
25
|
+
properties: { id: { type: 'string' } },
|
|
26
|
+
required: ['id'],
|
|
27
|
+
},
|
|
28
|
+
response: {
|
|
29
|
+
type: 'object',
|
|
30
|
+
properties: { name: { type: 'string' } },
|
|
31
|
+
required: ['name'],
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
kind: 'rpc',
|
|
37
|
+
name: 'CreateInvoice',
|
|
38
|
+
path: '/billing/1',
|
|
39
|
+
method: 'post',
|
|
40
|
+
scope: 'billing',
|
|
41
|
+
version: 1,
|
|
42
|
+
jsonSchema: {
|
|
43
|
+
body: {
|
|
44
|
+
type: 'object',
|
|
45
|
+
properties: { amount: { type: 'number' } },
|
|
46
|
+
required: ['amount'],
|
|
47
|
+
},
|
|
48
|
+
response: {
|
|
49
|
+
type: 'object',
|
|
50
|
+
properties: { invoiceId: { type: 'string' } },
|
|
51
|
+
required: ['invoiceId'],
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
};
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
// Helpers
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
function makeTmpDir() {
|
|
61
|
+
const dir = join(tmpdir(), `ts-proc-pipeline-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
62
|
+
mkdirSync(dir, { recursive: true });
|
|
63
|
+
return dir;
|
|
64
|
+
}
|
|
65
|
+
// ---------------------------------------------------------------------------
|
|
66
|
+
// Tests
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
describe('generateClient pipeline', () => {
|
|
69
|
+
let tmpDir;
|
|
70
|
+
afterEach(() => {
|
|
71
|
+
if (tmpDir && existsSync(tmpDir)) {
|
|
72
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
it('creates scope file for each unique scope (users.ts, billing.ts)', async () => {
|
|
76
|
+
tmpDir = makeTmpDir();
|
|
77
|
+
await generateClient({ envelope, outDir: tmpDir });
|
|
78
|
+
expect(existsSync(join(tmpDir, 'users.ts'))).toBe(true);
|
|
79
|
+
expect(existsSync(join(tmpDir, 'billing.ts'))).toBe(true);
|
|
80
|
+
});
|
|
81
|
+
it('creates index.ts', async () => {
|
|
82
|
+
tmpDir = makeTmpDir();
|
|
83
|
+
await generateClient({ envelope, outDir: tmpDir });
|
|
84
|
+
expect(existsSync(join(tmpDir, 'index.ts'))).toBe(true);
|
|
85
|
+
});
|
|
86
|
+
it('users.ts contains bindUsersScope function', async () => {
|
|
87
|
+
tmpDir = makeTmpDir();
|
|
88
|
+
await generateClient({ envelope, outDir: tmpDir });
|
|
89
|
+
const content = readFileSync(join(tmpDir, 'users.ts'), 'utf-8');
|
|
90
|
+
expect(content).toContain('bindUsersScope');
|
|
91
|
+
expect(content).toContain('GetUser');
|
|
92
|
+
});
|
|
93
|
+
it('billing.ts contains bindBillingScope function', async () => {
|
|
94
|
+
tmpDir = makeTmpDir();
|
|
95
|
+
await generateClient({ envelope, outDir: tmpDir });
|
|
96
|
+
const content = readFileSync(join(tmpDir, 'billing.ts'), 'utf-8');
|
|
97
|
+
expect(content).toContain('bindBillingScope');
|
|
98
|
+
expect(content).toContain('CreateInvoice');
|
|
99
|
+
});
|
|
100
|
+
it('index.ts exports from both scope files and has createScopeBindings', async () => {
|
|
101
|
+
tmpDir = makeTmpDir();
|
|
102
|
+
await generateClient({ envelope, outDir: tmpDir });
|
|
103
|
+
const content = readFileSync(join(tmpDir, 'index.ts'), 'utf-8');
|
|
104
|
+
expect(content).toContain("from './users'");
|
|
105
|
+
expect(content).toContain("from './billing'");
|
|
106
|
+
expect(content).toContain('createScopeBindings');
|
|
107
|
+
});
|
|
108
|
+
it('creates outDir if it does not exist', async () => {
|
|
109
|
+
tmpDir = makeTmpDir();
|
|
110
|
+
const nested = join(tmpDir, 'nested', 'output');
|
|
111
|
+
await generateClient({ envelope, outDir: nested });
|
|
112
|
+
expect(existsSync(join(nested, 'index.ts'))).toBe(true);
|
|
113
|
+
});
|
|
114
|
+
it('all generated files have the auto-generated header comment', async () => {
|
|
115
|
+
tmpDir = makeTmpDir();
|
|
116
|
+
await generateClient({ envelope, outDir: tmpDir });
|
|
117
|
+
for (const file of ['users.ts', 'billing.ts', 'index.ts']) {
|
|
118
|
+
const content = readFileSync(join(tmpDir, file), 'utf-8');
|
|
119
|
+
expect(content).toContain('// Auto-generated by ts-procedures-codegen — do not edit');
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
it('generated files include source hash comment', async () => {
|
|
123
|
+
tmpDir = makeTmpDir();
|
|
124
|
+
await generateClient({ envelope, outDir: tmpDir });
|
|
125
|
+
for (const file of ['users.ts', 'billing.ts', 'index.ts']) {
|
|
126
|
+
const content = readFileSync(join(tmpDir, file), 'utf-8');
|
|
127
|
+
const lines = content.split('\n');
|
|
128
|
+
expect(lines[1]).toMatch(/^\/\/ Source hash: [a-f0-9]{32}$/);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
it('dry-run mode does not create files on disk', async () => {
|
|
132
|
+
tmpDir = makeTmpDir();
|
|
133
|
+
const dryDir = join(tmpDir, 'dry-output');
|
|
134
|
+
await runPipeline({ envelope, outDir: dryDir, dryRun: true });
|
|
135
|
+
expect(existsSync(dryDir)).toBe(false);
|
|
136
|
+
});
|
|
137
|
+
it('dry-run mode returns generated file entries', async () => {
|
|
138
|
+
tmpDir = makeTmpDir();
|
|
139
|
+
const dryDir = join(tmpDir, 'dry-output');
|
|
140
|
+
const files = await runPipeline({ envelope, outDir: dryDir, dryRun: true });
|
|
141
|
+
expect(files.length).toBe(3); // users.ts, billing.ts, index.ts
|
|
142
|
+
const paths = files.map((f) => f.path);
|
|
143
|
+
expect(paths).toContain(join(dryDir, 'users.ts'));
|
|
144
|
+
expect(paths).toContain(join(dryDir, 'billing.ts'));
|
|
145
|
+
expect(paths).toContain(join(dryDir, 'index.ts'));
|
|
146
|
+
for (const file of files) {
|
|
147
|
+
expect(file.code).toContain('// Auto-generated by ts-procedures-codegen — do not edit');
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
it('selfContained: true produces _types.ts and _client.ts', async () => {
|
|
151
|
+
tmpDir = makeTmpDir();
|
|
152
|
+
const files = await runPipeline({ envelope, outDir: tmpDir, selfContained: true });
|
|
153
|
+
const paths = files.map((f) => f.path);
|
|
154
|
+
expect(paths).toContain(join(tmpDir, '_types.ts'));
|
|
155
|
+
expect(paths).toContain(join(tmpDir, '_client.ts'));
|
|
156
|
+
// Verify both files have auto-generated header and source hash
|
|
157
|
+
const typesFile = files.find((f) => f.path.endsWith('_types.ts'));
|
|
158
|
+
const clientFile = files.find((f) => f.path.endsWith('_client.ts'));
|
|
159
|
+
expect(typesFile.code).toContain('// Auto-generated by ts-procedures-codegen — do not edit');
|
|
160
|
+
expect(clientFile.code).toContain('// Auto-generated by ts-procedures-codegen — do not edit');
|
|
161
|
+
const typesLines = typesFile.code.split('\n');
|
|
162
|
+
expect(typesLines[1]).toMatch(/^\/\/ Source hash: [a-f0-9]{32}$/);
|
|
163
|
+
const clientLines = clientFile.code.split('\n');
|
|
164
|
+
expect(clientLines[1]).toMatch(/^\/\/ Source hash: [a-f0-9]{32}$/);
|
|
165
|
+
});
|
|
166
|
+
it('selfContained: true makes scope files import from ./_types', async () => {
|
|
167
|
+
tmpDir = makeTmpDir();
|
|
168
|
+
const files = await runPipeline({ envelope, outDir: tmpDir, selfContained: true });
|
|
169
|
+
const scopeFiles = files.filter((f) => !f.path.endsWith('index.ts') && !f.path.startsWith(join(tmpDir, '_')));
|
|
170
|
+
expect(scopeFiles.length).toBeGreaterThan(0);
|
|
171
|
+
for (const file of scopeFiles) {
|
|
172
|
+
expect(file.code).toContain("from './_types'");
|
|
173
|
+
expect(file.code).not.toContain("from 'ts-procedures/client'");
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
it('selfContained + clientImportPath emits a console.warn', async () => {
|
|
177
|
+
tmpDir = makeTmpDir();
|
|
178
|
+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => { });
|
|
179
|
+
try {
|
|
180
|
+
await runPipeline({ envelope, outDir: tmpDir, selfContained: true, clientImportPath: './my-client' });
|
|
181
|
+
expect(warnSpy).toHaveBeenCalledWith('[ts-procedures-codegen] --self-contained overrides --client-import-path; using ./_types');
|
|
182
|
+
}
|
|
183
|
+
finally {
|
|
184
|
+
warnSpy.mockRestore();
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
it('serviceName + namespaceTypes produces prefixed error namespace in _errors.ts', async () => {
|
|
188
|
+
tmpDir = makeTmpDir();
|
|
189
|
+
const envelopeWithErrors = {
|
|
190
|
+
...envelope,
|
|
191
|
+
errors: [
|
|
192
|
+
{
|
|
193
|
+
name: 'ProcedureError',
|
|
194
|
+
statusCode: 500,
|
|
195
|
+
description: 'Handler error',
|
|
196
|
+
schema: {
|
|
197
|
+
type: 'object',
|
|
198
|
+
properties: { name: { type: 'string' }, message: { type: 'string' } },
|
|
199
|
+
required: ['name', 'message'],
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
],
|
|
203
|
+
};
|
|
204
|
+
await generateClient({ envelope: envelopeWithErrors, outDir: tmpDir, serviceName: 'Auth', namespaceTypes: true });
|
|
205
|
+
const errorsContent = readFileSync(join(tmpDir, '_errors.ts'), 'utf-8');
|
|
206
|
+
expect(errorsContent).toContain('export namespace AuthErrors {');
|
|
207
|
+
expect(errorsContent).not.toContain('export namespace Errors {');
|
|
208
|
+
expect(errorsContent).toContain('AuthProcedureErrorUnion');
|
|
209
|
+
});
|
|
210
|
+
it('serviceName prefixes ProcedureErrorUnion in flat mode _errors.ts', async () => {
|
|
211
|
+
tmpDir = makeTmpDir();
|
|
212
|
+
const envelopeWithErrors = {
|
|
213
|
+
...envelope,
|
|
214
|
+
errors: [
|
|
215
|
+
{
|
|
216
|
+
name: 'ProcedureError',
|
|
217
|
+
statusCode: 500,
|
|
218
|
+
description: 'Handler error',
|
|
219
|
+
schema: {
|
|
220
|
+
type: 'object',
|
|
221
|
+
properties: { name: { type: 'string' }, message: { type: 'string' } },
|
|
222
|
+
required: ['name', 'message'],
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
],
|
|
226
|
+
};
|
|
227
|
+
await generateClient({ envelope: envelopeWithErrors, outDir: tmpDir, serviceName: 'Auth' });
|
|
228
|
+
const errorsContent = readFileSync(join(tmpDir, '_errors.ts'), 'utf-8');
|
|
229
|
+
expect(errorsContent).toContain('export type AuthProcedureErrorUnion =');
|
|
230
|
+
expect(errorsContent).not.toContain('export type ProcedureErrorUnion =');
|
|
231
|
+
});
|
|
232
|
+
it('rejects invalid serviceName', async () => {
|
|
233
|
+
tmpDir = makeTmpDir();
|
|
234
|
+
await expect(generateClient({ envelope, outDir: tmpDir, serviceName: '---' })).rejects.toThrow('empty');
|
|
235
|
+
});
|
|
236
|
+
it('rejects serviceName starting with a digit', async () => {
|
|
237
|
+
tmpDir = makeTmpDir();
|
|
238
|
+
await expect(generateClient({ envelope, outDir: tmpDir, serviceName: '123svc' })).rejects.toThrow('starts with a digit');
|
|
239
|
+
});
|
|
240
|
+
it('serviceName generates custom factory function name in index.ts', async () => {
|
|
241
|
+
tmpDir = makeTmpDir();
|
|
242
|
+
await generateClient({ envelope, outDir: tmpDir, serviceName: 'Auth' });
|
|
243
|
+
const content = readFileSync(join(tmpDir, 'index.ts'), 'utf-8');
|
|
244
|
+
expect(content).toContain('createAuthBindings');
|
|
245
|
+
expect(content).not.toContain('createScopeBindings');
|
|
246
|
+
});
|
|
247
|
+
it('throws when a scope key collides with _types in selfContained mode', async () => {
|
|
248
|
+
tmpDir = makeTmpDir();
|
|
249
|
+
const collisionEnvelope = {
|
|
250
|
+
...envelope,
|
|
251
|
+
routes: [
|
|
252
|
+
{
|
|
253
|
+
kind: 'rpc',
|
|
254
|
+
name: 'GetUser',
|
|
255
|
+
path: '/users/1',
|
|
256
|
+
method: 'post',
|
|
257
|
+
scope: '_types',
|
|
258
|
+
version: 1,
|
|
259
|
+
jsonSchema: {
|
|
260
|
+
body: { type: 'object', properties: { id: { type: 'string' } }, required: ['id'] },
|
|
261
|
+
response: { type: 'object', properties: { name: { type: 'string' } }, required: ['name'] },
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
],
|
|
265
|
+
};
|
|
266
|
+
await expect(runPipeline({ envelope: collisionEnvelope, outDir: tmpDir, selfContained: true })).rejects.toThrow('[ts-procedures-codegen] Scope "_types" conflicts with self-contained mode reserved filename "_types.ts". Rename the scope to avoid collision.');
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
//# sourceMappingURL=pipeline.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.test.js","sourceRoot":"","sources":["../../../src/codegen/pipeline.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
export async function resolveEnvelope(input) {
|
|
3
|
+
let envelope;
|
|
4
|
+
if (input.envelope !== undefined) {
|
|
5
|
+
envelope = input.envelope;
|
|
6
|
+
}
|
|
7
|
+
else if (input.file !== undefined) {
|
|
8
|
+
const raw = await readFile(input.file, 'utf8');
|
|
9
|
+
envelope = JSON.parse(raw);
|
|
10
|
+
}
|
|
11
|
+
else if (input.url !== undefined) {
|
|
12
|
+
let response;
|
|
13
|
+
try {
|
|
14
|
+
response = await fetch(input.url);
|
|
15
|
+
}
|
|
16
|
+
catch (err) {
|
|
17
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
18
|
+
throw new Error(`[ts-procedures-codegen] Failed to connect to ${input.url}: ${msg}`);
|
|
19
|
+
}
|
|
20
|
+
if (!response.ok) {
|
|
21
|
+
throw new Error(`[ts-procedures-codegen] ${input.url} returned HTTP ${response.status} ${response.statusText}`);
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
envelope = (await response.json());
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
throw new Error(`[ts-procedures-codegen] ${input.url} returned non-JSON response. Expected a DocEnvelope JSON object.`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
throw new Error('resolveEnvelope: no input source provided. Pass one of: envelope, file, or url.');
|
|
32
|
+
}
|
|
33
|
+
if (!envelope || typeof envelope !== 'object') {
|
|
34
|
+
throw new Error(`[ts-procedures-codegen] Invalid DocEnvelope: expected an object with a "routes" array, got ${typeof envelope}`);
|
|
35
|
+
}
|
|
36
|
+
if (!Array.isArray(envelope.routes)) {
|
|
37
|
+
const keys = Object.keys(envelope).join(', ');
|
|
38
|
+
throw new Error(`[ts-procedures-codegen] DocEnvelope is missing "routes" array. Found keys: [${keys}]. ` +
|
|
39
|
+
`Make sure your server uses DocRegistry.toJSON() to produce the envelope.`);
|
|
40
|
+
}
|
|
41
|
+
if (envelope.routes.length === 0) {
|
|
42
|
+
throw new Error('[ts-procedures-codegen] DocEnvelope has an empty "routes" array. Register at least one procedure before generating.');
|
|
43
|
+
}
|
|
44
|
+
return envelope;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=resolve-envelope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-envelope.js","sourceRoot":"","sources":["../../../src/codegen/resolve-envelope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAS3C,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,KAAmB;IACvD,IAAI,QAAqB,CAAA;IAEzB,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACjC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAA;IAC3B,CAAC;SAAM,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QACpC,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QAC9C,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAgB,CAAA;IAC3C,CAAC;SAAM,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QACnC,IAAI,QAAkB,CAAA;QACtB,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QACnC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAC5D,MAAM,IAAI,KAAK,CAAC,gDAAgD,KAAK,CAAC,GAAG,KAAK,GAAG,EAAE,CAAC,CAAA;QACtF,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,2BAA2B,KAAK,CAAC,GAAG,kBAAkB,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAA;QACjH,CAAC;QACD,IAAI,CAAC;YACH,QAAQ,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAgB,CAAA;QACnD,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,2BAA2B,KAAK,CAAC,GAAG,kEAAkE,CAAC,CAAA;QACzH,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,KAAK,CACb,iFAAiF,CAClF,CAAA;IACH,CAAC;IAED,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CACb,8FAA8F,OAAO,QAAQ,EAAE,CAChH,CAAA;IACH,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC7C,MAAM,IAAI,KAAK,CACb,+EAA+E,IAAI,KAAK;YACxF,0EAA0E,CAC3E,CAAA;IACH,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CACb,qHAAqH,CACtH,CAAA;IACH,CAAC;IAED,OAAO,QAAQ,CAAA;AACjB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { writeFile, mkdtemp, rm } from 'node:fs/promises';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { resolveEnvelope } from './resolve-envelope.js';
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
// Fixtures
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
const minimalEnvelope = {
|
|
10
|
+
basePath: '/api',
|
|
11
|
+
headers: [],
|
|
12
|
+
errors: [],
|
|
13
|
+
routes: [
|
|
14
|
+
{
|
|
15
|
+
kind: 'rpc',
|
|
16
|
+
name: 'Ping',
|
|
17
|
+
path: '/ping/1',
|
|
18
|
+
method: 'post',
|
|
19
|
+
scope: 'ping',
|
|
20
|
+
version: 1,
|
|
21
|
+
jsonSchema: {},
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
};
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
// Tests
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
describe('resolveEnvelope', () => {
|
|
29
|
+
it('accepts a DocEnvelope object directly', async () => {
|
|
30
|
+
const result = await resolveEnvelope({ envelope: minimalEnvelope });
|
|
31
|
+
expect(result).toEqual(minimalEnvelope);
|
|
32
|
+
});
|
|
33
|
+
it('reads a DocEnvelope from a JSON file', async () => {
|
|
34
|
+
const dir = await mkdtemp(join(tmpdir(), 'ts-proc-test-'));
|
|
35
|
+
const filePath = join(dir, 'envelope.json');
|
|
36
|
+
try {
|
|
37
|
+
await writeFile(filePath, JSON.stringify(minimalEnvelope), 'utf8');
|
|
38
|
+
const result = await resolveEnvelope({ file: filePath });
|
|
39
|
+
expect(result).toEqual(minimalEnvelope);
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
await rm(dir, { recursive: true, force: true });
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
it('throws when routes array is empty (envelope input)', async () => {
|
|
46
|
+
const empty = { basePath: '', headers: [], errors: [], routes: [] };
|
|
47
|
+
await expect(resolveEnvelope({ envelope: empty })).rejects.toThrow(/routes/);
|
|
48
|
+
});
|
|
49
|
+
it('throws when routes array is empty (file input)', async () => {
|
|
50
|
+
const dir = await mkdtemp(join(tmpdir(), 'ts-proc-test-'));
|
|
51
|
+
const filePath = join(dir, 'empty.json');
|
|
52
|
+
const empty = { basePath: '', headers: [], errors: [], routes: [] };
|
|
53
|
+
try {
|
|
54
|
+
await writeFile(filePath, JSON.stringify(empty), 'utf8');
|
|
55
|
+
await expect(resolveEnvelope({ file: filePath })).rejects.toThrow(/routes/);
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
await rm(dir, { recursive: true, force: true });
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
it('throws when no input source is provided', async () => {
|
|
62
|
+
await expect(resolveEnvelope({})).rejects.toThrow(/input/);
|
|
63
|
+
});
|
|
64
|
+
// URL test skipped — requires network mock
|
|
65
|
+
it.skip('fetches a DocEnvelope from a URL', async () => {
|
|
66
|
+
// Would require mocking fetch
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
//# sourceMappingURL=resolve-envelope.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-envelope.test.js","sourceRoot":"","sources":["../../../src/codegen/resolve-envelope.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAA;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAGvD,8EAA8E;AAC9E,WAAW;AACX,8EAA8E;AAE9E,MAAM,eAAe,GAAgB;IACnC,QAAQ,EAAE,MAAM;IAChB,OAAO,EAAE,EAAE;IACX,MAAM,EAAE,EAAE;IACV,MAAM,EAAE;QACN;YACE,IAAI,EAAE,KAAK;YACX,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,SAAS;YACf,MAAM,EAAE,MAAM;YACd,KAAK,EAAE,MAAM;YACb,OAAO,EAAE,CAAC;YACV,UAAU,EAAE,EAAE;SACf;KACF;CACF,CAAA;AAED,8EAA8E;AAC9E,QAAQ;AACR,8EAA8E;AAE9E,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;QACrD,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC,CAAA;QACnE,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC,CAAA;IACzC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;QACpD,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAA;QAC1D,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAA;QAC3C,IAAI,CAAC;YACH,MAAM,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC,CAAA;YAClE,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAA;YACxD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC,CAAA;QACzC,CAAC;gBAAS,CAAC;YACT,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;QACjD,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,KAAK,GAAgB,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAA;QAChF,MAAM,MAAM,CAAC,eAAe,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC9E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAC9D,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAA;QAC1D,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAA;QACxC,MAAM,KAAK,GAAgB,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAA;QAChF,IAAI,CAAC;YACH,MAAM,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,CAAA;YACxD,MAAM,MAAM,CAAC,eAAe,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QAC7E,CAAC;gBAAS,CAAC;YACT,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;QACjD,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QACvD,MAAM,MAAM,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IAC5D,CAAC,CAAC,CAAA;IAEF,2CAA2C;IAC3C,EAAE,CAAC,IAAI,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;QACrD,8BAA8B;IAChC,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { TSchemaValidationError } from './schema/parser.js';
|
|
2
|
+
import { DefinitionInfo, DefinitionLocation } from './stack-utils.js';
|
|
3
|
+
export declare class ProcedureError extends Error {
|
|
4
|
+
readonly procedureName: string;
|
|
5
|
+
readonly message: string;
|
|
6
|
+
readonly meta?: object | undefined;
|
|
7
|
+
cause?: unknown;
|
|
8
|
+
readonly definedAt?: DefinitionLocation;
|
|
9
|
+
readonly definitionStack?: string;
|
|
10
|
+
constructor(procedureName: string, message: string, meta?: object | undefined, definitionInfo?: DefinitionInfo);
|
|
11
|
+
/**
|
|
12
|
+
* Returns a formatted string showing where the procedure was defined.
|
|
13
|
+
*/
|
|
14
|
+
getDefinitionLocation(): string | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Enhances the error stack with definition location information.
|
|
17
|
+
*/
|
|
18
|
+
private enhanceStack;
|
|
19
|
+
}
|
|
20
|
+
export declare class ProcedureValidationError extends ProcedureError {
|
|
21
|
+
readonly procedureName: string;
|
|
22
|
+
readonly errors?: TSchemaValidationError[] | undefined;
|
|
23
|
+
constructor(procedureName: string, message: string, errors?: TSchemaValidationError[] | undefined, definitionInfo?: DefinitionInfo);
|
|
24
|
+
}
|
|
25
|
+
export declare class ProcedureRegistrationError extends ProcedureError {
|
|
26
|
+
readonly procedureName: string;
|
|
27
|
+
constructor(procedureName: string, message: string, definitionInfo?: DefinitionInfo);
|
|
28
|
+
}
|
|
29
|
+
export declare class ProcedureYieldValidationError extends ProcedureError {
|
|
30
|
+
readonly procedureName: string;
|
|
31
|
+
readonly errors?: TSchemaValidationError[] | undefined;
|
|
32
|
+
constructor(procedureName: string, message: string, errors?: TSchemaValidationError[] | undefined, definitionInfo?: DefinitionInfo);
|
|
33
|
+
}
|