ts-procedures 5.10.0 → 5.12.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.
- 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 +2 -2
- package/agent_config/claude-code/skills/{guide → ts-procedures}/SKILL.md +1 -1
- package/agent_config/claude-code/skills/{guide → ts-procedures}/api-reference.md +11 -8
- package/agent_config/claude-code/skills/{guide → ts-procedures}/patterns.md +8 -2
- package/agent_config/claude-code/skills/{review → ts-procedures-review}/SKILL.md +3 -3
- package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/SKILL.md +2 -2
- package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/templates/client.md +4 -4
- package/agent_config/copilot/copilot-instructions.md +6 -5
- package/agent_config/cursor/cursorrules +6 -5
- package/agent_config/lib/install-claude.mjs +35 -87
- package/build/codegen/e2e.test.js +21 -14
- package/build/codegen/e2e.test.js.map +1 -1
- package/build/codegen/emit-index.d.ts +7 -3
- package/build/codegen/emit-index.js +33 -20
- package/build/codegen/emit-index.js.map +1 -1
- package/build/codegen/emit-index.test.js +69 -45
- package/build/codegen/emit-index.test.js.map +1 -1
- package/build/codegen/pipeline.js +4 -5
- package/build/codegen/pipeline.js.map +1 -1
- package/build/codegen/pipeline.test.js +4 -4
- package/build/codegen/pipeline.test.js.map +1 -1
- 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/client-and-codegen.md +9 -6
- package/package.json +1 -1
- package/src/codegen/e2e.test.ts +23 -14
- package/src/codegen/emit-index.test.ts +72 -45
- package/src/codegen/emit-index.ts +43 -20
- package/src/codegen/pipeline.test.ts +4 -4
- package/src/codegen/pipeline.ts +4 -5
- /package/agent_config/claude-code/skills/{guide → ts-procedures}/anti-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
|
@@ -39,76 +39,103 @@ describe('emitIndexFile', () => {
|
|
|
39
39
|
expect(output).toContain("import type { ClientInstance } from 'ts-procedures/client'")
|
|
40
40
|
})
|
|
41
41
|
|
|
42
|
-
it('imports each
|
|
42
|
+
it('imports each scope as a namespace using the camelCase scope name', () => {
|
|
43
43
|
const output = emitIndexFile([usersGroup, billingGroup])
|
|
44
|
-
expect(output).toContain("import
|
|
45
|
-
expect(output).toContain("import
|
|
44
|
+
expect(output).toContain("import * as users from './users'")
|
|
45
|
+
expect(output).toContain("import * as billing from './billing'")
|
|
46
46
|
})
|
|
47
47
|
|
|
48
|
-
it('
|
|
48
|
+
it('does not emit `export *` re-exports', () => {
|
|
49
49
|
const output = emitIndexFile([usersGroup, billingGroup])
|
|
50
|
-
expect(output).toContain(
|
|
51
|
-
expect(output).toContain("export * from './billing'")
|
|
50
|
+
expect(output).not.toContain('export *')
|
|
52
51
|
})
|
|
53
52
|
|
|
54
|
-
it('
|
|
55
|
-
const output = emitIndexFile([
|
|
56
|
-
expect(output).toContain(
|
|
57
|
-
expect(output).toContain('users: bindUsersScope(client)')
|
|
58
|
-
expect(output).toContain('billing: bindBillingScope(client)')
|
|
53
|
+
it('uses the scopeKey for import paths and camelCase for the local alias', () => {
|
|
54
|
+
const output = emitIndexFile([adminUsersGroup])
|
|
55
|
+
expect(output).toContain("import * as adminUsers from './admin-users'")
|
|
59
56
|
})
|
|
60
57
|
|
|
61
|
-
it('
|
|
62
|
-
const output = emitIndexFile([
|
|
63
|
-
expect(output).toContain('
|
|
58
|
+
it('generates the factory using the default service name (Api)', () => {
|
|
59
|
+
const output = emitIndexFile([usersGroup, billingGroup])
|
|
60
|
+
expect(output).toContain('export function createApiBindings(client: ClientInstance)')
|
|
61
|
+
expect(output).toContain('users: users.bindUsersScope(client)')
|
|
62
|
+
expect(output).toContain('billing: billing.bindBillingScope(client)')
|
|
64
63
|
})
|
|
65
64
|
|
|
66
|
-
it('uses
|
|
65
|
+
it('uses camelCase as the binding property key', () => {
|
|
67
66
|
const output = emitIndexFile([adminUsersGroup])
|
|
68
|
-
expect(output).toContain(
|
|
69
|
-
expect(output).toContain("export * from './admin-users'")
|
|
67
|
+
expect(output).toContain('adminUsers: adminUsers.bindAdminUsersScope(client)')
|
|
70
68
|
})
|
|
71
69
|
|
|
72
|
-
it('
|
|
73
|
-
const output = emitIndexFile([usersGroup])
|
|
74
|
-
|
|
75
|
-
|
|
70
|
+
it('places imports before the namespace block before the factory', () => {
|
|
71
|
+
const output = emitIndexFile([usersGroup, billingGroup], { namespaceTypes: true })
|
|
72
|
+
const importIdx = output.indexOf("import * as users")
|
|
73
|
+
const namespaceIdx = output.indexOf('export namespace Api')
|
|
74
|
+
const factoryIdx = output.indexOf('export function createApiBindings')
|
|
75
|
+
expect(importIdx).toBeLessThan(namespaceIdx)
|
|
76
|
+
expect(namespaceIdx).toBeLessThan(factoryIdx)
|
|
76
77
|
})
|
|
77
78
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
})
|
|
79
|
+
describe('service namespace (namespaceTypes: true)', () => {
|
|
80
|
+
it('emits a service namespace named after the default Api', () => {
|
|
81
|
+
const output = emitIndexFile([usersGroup, billingGroup], { namespaceTypes: true })
|
|
82
|
+
expect(output).toContain('export namespace Api {')
|
|
83
|
+
expect(output).toContain('export import Users = users.Users')
|
|
84
|
+
expect(output).toContain('export import Billing = billing.Billing')
|
|
85
|
+
})
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
expect(output).toContain('export
|
|
87
|
+
it('emits a service namespace named after a provided serviceName', () => {
|
|
88
|
+
const output = emitIndexFile([usersGroup], { namespaceTypes: true, serviceName: 'UsersApi' })
|
|
89
|
+
expect(output).toContain('export namespace UsersApi {')
|
|
90
|
+
expect(output).toContain('export import Users = users.Users')
|
|
91
|
+
expect(output).toContain('export function createUsersApiBindings(client: ClientInstance)')
|
|
91
92
|
})
|
|
92
93
|
|
|
93
|
-
it('
|
|
94
|
-
const output = emitIndexFile([
|
|
95
|
-
expect(output).toContain('export
|
|
96
|
-
expect(output).not.toContain('createScopeBindings')
|
|
94
|
+
it('PascalCases each scope when re-exporting', () => {
|
|
95
|
+
const output = emitIndexFile([adminUsersGroup], { namespaceTypes: true })
|
|
96
|
+
expect(output).toContain('export import AdminUsers = adminUsers.AdminUsers')
|
|
97
97
|
})
|
|
98
98
|
|
|
99
|
-
it('PascalCases a kebab-case serviceName', () => {
|
|
100
|
-
const output = emitIndexFile([usersGroup], { serviceName: 'auth-service' })
|
|
99
|
+
it('PascalCases a kebab-case serviceName for both namespace and factory', () => {
|
|
100
|
+
const output = emitIndexFile([usersGroup], { namespaceTypes: true, serviceName: 'auth-service' })
|
|
101
|
+
expect(output).toContain('export namespace AuthService {')
|
|
101
102
|
expect(output).toContain('export function createAuthServiceBindings(client: ClientInstance)')
|
|
102
103
|
})
|
|
103
104
|
|
|
104
|
-
it('
|
|
105
|
-
const output = emitIndexFile([usersGroup], {
|
|
106
|
-
|
|
105
|
+
it('folds errors into the service namespace as `Errors` when hasErrors is true', () => {
|
|
106
|
+
const output = emitIndexFile([usersGroup], {
|
|
107
|
+
namespaceTypes: true,
|
|
108
|
+
hasErrors: true,
|
|
109
|
+
serviceName: 'UsersApi',
|
|
110
|
+
})
|
|
111
|
+
expect(output).toContain("import * as _errorsModule from './_errors'")
|
|
112
|
+
expect(output).toContain('export import Errors = _errorsModule.UsersApiErrors')
|
|
107
113
|
})
|
|
108
114
|
|
|
109
|
-
it('
|
|
110
|
-
const output = emitIndexFile([usersGroup
|
|
111
|
-
expect(output).toContain(
|
|
115
|
+
it('omits the errors import and re-export when hasErrors is false', () => {
|
|
116
|
+
const output = emitIndexFile([usersGroup], { namespaceTypes: true, hasErrors: false })
|
|
117
|
+
expect(output).not.toContain("from './_errors'")
|
|
118
|
+
expect(output).not.toContain('Errors')
|
|
119
|
+
})
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
describe('namespaceTypes: false', () => {
|
|
123
|
+
it('skips the service namespace block entirely', () => {
|
|
124
|
+
const output = emitIndexFile([usersGroup, billingGroup])
|
|
125
|
+
expect(output).not.toContain('export namespace')
|
|
126
|
+
expect(output).not.toContain('export import')
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
it('still imports scopes and emits the factory', () => {
|
|
130
|
+
const output = emitIndexFile([usersGroup, billingGroup])
|
|
131
|
+
expect(output).toContain("import * as users from './users'")
|
|
132
|
+
expect(output).toContain('export function createApiBindings(client: ClientInstance)')
|
|
133
|
+
expect(output).toContain('users: users.bindUsersScope(client)')
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
it('does not import errors even when hasErrors is true', () => {
|
|
137
|
+
const output = emitIndexFile([usersGroup], { hasErrors: true })
|
|
138
|
+
expect(output).not.toContain("from './_errors'")
|
|
112
139
|
})
|
|
113
140
|
})
|
|
114
141
|
|
|
@@ -2,10 +2,7 @@ import type { ScopeGroup } from './group-routes.js'
|
|
|
2
2
|
import { CODEGEN_HEADER } from './constants.js'
|
|
3
3
|
import { toPascalCase } from './naming.js'
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
function bindFunctionName(camelCase: string): string {
|
|
7
|
-
return `bind${toPascalCase(camelCase)}Scope`
|
|
8
|
-
}
|
|
5
|
+
const ERRORS_MODULE_ALIAS = '_errorsModule'
|
|
9
6
|
|
|
10
7
|
// ---------------------------------------------------------------------------
|
|
11
8
|
// emitIndexFile
|
|
@@ -14,40 +11,66 @@ function bindFunctionName(camelCase: string): string {
|
|
|
14
11
|
export interface EmitIndexOptions {
|
|
15
12
|
clientImportPath?: string
|
|
16
13
|
hasErrors?: boolean
|
|
14
|
+
namespaceTypes?: boolean
|
|
17
15
|
serviceName?: string
|
|
18
16
|
}
|
|
19
17
|
|
|
20
18
|
/**
|
|
21
|
-
* Generates a barrel index file that
|
|
22
|
-
*
|
|
23
|
-
*
|
|
19
|
+
* Generates a barrel index file that exposes every scope through a single
|
|
20
|
+
* service namespace (named after `serviceName`, defaulting to `Api`) and a
|
|
21
|
+
* `create${ServiceName}Bindings` factory.
|
|
22
|
+
*
|
|
23
|
+
* The service namespace is only emitted when `namespaceTypes` is on, since
|
|
24
|
+
* scope files only export top-level namespaces in that mode.
|
|
24
25
|
*/
|
|
25
26
|
export function emitIndexFile(groups: ScopeGroup[], options?: EmitIndexOptions): string {
|
|
26
|
-
const {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
const {
|
|
28
|
+
clientImportPath = 'ts-procedures/client',
|
|
29
|
+
hasErrors = false,
|
|
30
|
+
namespaceTypes = false,
|
|
31
|
+
serviceName = 'Api',
|
|
32
|
+
} = options ?? {}
|
|
33
|
+
|
|
34
|
+
const servicePascal = toPascalCase(serviceName)
|
|
35
|
+
const factoryName = `create${servicePascal}Bindings`
|
|
36
|
+
const errorsExportedName = `${servicePascal}Errors`
|
|
31
37
|
|
|
32
|
-
const
|
|
33
|
-
.map((g) => `
|
|
38
|
+
const scopeImports = groups
|
|
39
|
+
.map((g) => `import * as ${g.camelCase} from './${g.scopeKey}'`)
|
|
34
40
|
.join('\n')
|
|
35
41
|
|
|
36
|
-
const
|
|
42
|
+
const errorsImport = namespaceTypes && hasErrors
|
|
43
|
+
? `import * as ${ERRORS_MODULE_ALIAS} from './_errors'`
|
|
44
|
+
: ''
|
|
37
45
|
|
|
38
|
-
const
|
|
46
|
+
const importsBlock = [scopeImports, errorsImport].filter(Boolean).join('\n')
|
|
47
|
+
|
|
48
|
+
let namespaceBlock = ''
|
|
49
|
+
if (namespaceTypes) {
|
|
50
|
+
const namespaceMembers = groups.map(
|
|
51
|
+
(g) => ` export import ${toPascalCase(g.camelCase)} = ${g.camelCase}.${toPascalCase(g.camelCase)}`,
|
|
52
|
+
)
|
|
53
|
+
if (hasErrors) {
|
|
54
|
+
namespaceMembers.push(` export import Errors = ${ERRORS_MODULE_ALIAS}.${errorsExportedName}`)
|
|
55
|
+
}
|
|
56
|
+
namespaceBlock = [
|
|
57
|
+
`export namespace ${servicePascal} {`,
|
|
58
|
+
namespaceMembers.join('\n'),
|
|
59
|
+
'}',
|
|
60
|
+
'',
|
|
61
|
+
].join('\n')
|
|
62
|
+
}
|
|
39
63
|
|
|
40
64
|
const scopeBindings = groups
|
|
41
|
-
.map((g) => ` ${g.camelCase}: ${
|
|
65
|
+
.map((g) => ` ${g.camelCase}: ${g.camelCase}.bind${toPascalCase(g.camelCase)}Scope(client),`)
|
|
42
66
|
.join('\n')
|
|
43
67
|
|
|
44
68
|
return [
|
|
45
69
|
CODEGEN_HEADER,
|
|
46
70
|
`import type { ClientInstance } from '${clientImportPath}'`,
|
|
47
|
-
|
|
48
|
-
'',
|
|
49
|
-
reExports,
|
|
71
|
+
importsBlock,
|
|
50
72
|
'',
|
|
73
|
+
namespaceBlock,
|
|
51
74
|
`export function ${factoryName}(client: ClientInstance) {`,
|
|
52
75
|
' return {',
|
|
53
76
|
scopeBindings,
|
|
@@ -114,14 +114,14 @@ describe('generateClient pipeline', () => {
|
|
|
114
114
|
expect(content).toContain('CreateInvoice')
|
|
115
115
|
})
|
|
116
116
|
|
|
117
|
-
it('index.ts
|
|
117
|
+
it('index.ts imports both scope namespaces and emits the default Api factory', async () => {
|
|
118
118
|
tmpDir = makeTmpDir()
|
|
119
119
|
await generateClient({ envelope, outDir: tmpDir })
|
|
120
120
|
|
|
121
121
|
const content = readFileSync(join(tmpDir, 'index.ts'), 'utf-8')
|
|
122
|
-
expect(content).toContain("from './users'")
|
|
123
|
-
expect(content).toContain("from './billing'")
|
|
124
|
-
expect(content).toContain('
|
|
122
|
+
expect(content).toContain("import * as users from './users'")
|
|
123
|
+
expect(content).toContain("import * as billing from './billing'")
|
|
124
|
+
expect(content).toContain('createApiBindings')
|
|
125
125
|
})
|
|
126
126
|
|
|
127
127
|
it('creates outDir if it does not exist', async () => {
|
package/src/codegen/pipeline.ts
CHANGED
|
@@ -28,10 +28,9 @@ export interface GeneratedFile {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
export async function runPipeline(options: PipelineOptions): Promise<GeneratedFile[]> {
|
|
31
|
-
const { envelope, outDir, ajsc: ajscOpts, dryRun = false, namespaceTypes = false, selfContained = false
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
31
|
+
const { envelope, outDir, ajsc: ajscOpts, dryRun = false, namespaceTypes = false, selfContained = false } = options
|
|
32
|
+
const serviceName = options.serviceName ?? 'Api'
|
|
33
|
+
validateServiceName(serviceName)
|
|
35
34
|
const clientImportPath = selfContained ? './_types' : options.clientImportPath
|
|
36
35
|
if (selfContained && options.clientImportPath != null) {
|
|
37
36
|
console.warn('[ts-procedures-codegen] --self-contained overrides --client-import-path; using ./_types')
|
|
@@ -72,7 +71,7 @@ export async function runPipeline(options: PipelineOptions): Promise<GeneratedFi
|
|
|
72
71
|
files.push({ path: join(outDir, '_errors.ts'), code: errorsWithHash })
|
|
73
72
|
}
|
|
74
73
|
|
|
75
|
-
const rawIndexCode = emitIndexFile(groupArray, { clientImportPath, hasErrors, serviceName })
|
|
74
|
+
const rawIndexCode = emitIndexFile(groupArray, { clientImportPath, hasErrors, namespaceTypes, serviceName })
|
|
76
75
|
const indexLines = rawIndexCode.split('\n')
|
|
77
76
|
indexLines.splice(1, 0, hashComment)
|
|
78
77
|
const indexCode = indexLines.join('\n')
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/templates/hono-api.md
RENAMED
|
File without changes
|
/package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/templates/hono-rpc.md
RENAMED
|
File without changes
|
|
File without changes
|
/package/agent_config/claude-code/skills/{scaffold → ts-procedures-scaffold}/templates/procedure.md
RENAMED
|
File without changes
|
|
File without changes
|