ts-procedures 5.5.0 → 5.6.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/README.md +150 -0
  2. package/agent_config/claude-code/skills/guide/api-reference.md +177 -0
  3. package/agent_config/claude-code/skills/guide/patterns.md +107 -0
  4. package/agent_config/copilot/copilot-instructions.md +80 -0
  5. package/agent_config/cursor/cursorrules +80 -0
  6. package/build/client/call.d.ts +14 -0
  7. package/build/client/call.js +47 -0
  8. package/build/client/call.js.map +1 -0
  9. package/build/client/call.test.d.ts +1 -0
  10. package/build/client/call.test.js +124 -0
  11. package/build/client/call.test.js.map +1 -0
  12. package/build/client/errors.d.ts +25 -0
  13. package/build/client/errors.js +33 -0
  14. package/build/client/errors.js.map +1 -0
  15. package/build/client/errors.test.d.ts +1 -0
  16. package/build/client/errors.test.js +41 -0
  17. package/build/client/errors.test.js.map +1 -0
  18. package/build/client/fetch-adapter.d.ts +12 -0
  19. package/build/client/fetch-adapter.js +156 -0
  20. package/build/client/fetch-adapter.js.map +1 -0
  21. package/build/client/fetch-adapter.test.d.ts +1 -0
  22. package/build/client/fetch-adapter.test.js +271 -0
  23. package/build/client/fetch-adapter.test.js.map +1 -0
  24. package/build/client/hooks.d.ts +17 -0
  25. package/build/client/hooks.js +40 -0
  26. package/build/client/hooks.js.map +1 -0
  27. package/build/client/hooks.test.d.ts +1 -0
  28. package/build/client/hooks.test.js +163 -0
  29. package/build/client/hooks.test.js.map +1 -0
  30. package/build/client/index.d.ts +22 -0
  31. package/build/client/index.js +67 -0
  32. package/build/client/index.js.map +1 -0
  33. package/build/client/index.test.d.ts +1 -0
  34. package/build/client/index.test.js +231 -0
  35. package/build/client/index.test.js.map +1 -0
  36. package/build/client/request-builder.d.ts +13 -0
  37. package/build/client/request-builder.js +53 -0
  38. package/build/client/request-builder.js.map +1 -0
  39. package/build/client/request-builder.test.d.ts +1 -0
  40. package/build/client/request-builder.test.js +160 -0
  41. package/build/client/request-builder.test.js.map +1 -0
  42. package/build/client/stream.d.ts +27 -0
  43. package/build/client/stream.js +118 -0
  44. package/build/client/stream.js.map +1 -0
  45. package/build/client/stream.test.d.ts +1 -0
  46. package/build/client/stream.test.js +228 -0
  47. package/build/client/stream.test.js.map +1 -0
  48. package/build/client/types.d.ts +78 -0
  49. package/build/client/types.js +3 -0
  50. package/build/client/types.js.map +1 -0
  51. package/build/codegen/bin/cli.d.ts +17 -0
  52. package/build/codegen/bin/cli.js +149 -0
  53. package/build/codegen/bin/cli.js.map +1 -0
  54. package/build/codegen/bin/cli.test.d.ts +1 -0
  55. package/build/codegen/bin/cli.test.js +83 -0
  56. package/build/codegen/bin/cli.test.js.map +1 -0
  57. package/build/codegen/e2e.test.d.ts +1 -0
  58. package/build/codegen/e2e.test.js +321 -0
  59. package/build/codegen/e2e.test.js.map +1 -0
  60. package/build/codegen/emit-errors.d.ts +9 -0
  61. package/build/codegen/emit-errors.js +30 -0
  62. package/build/codegen/emit-errors.js.map +1 -0
  63. package/build/codegen/emit-errors.test.d.ts +1 -0
  64. package/build/codegen/emit-errors.test.js +110 -0
  65. package/build/codegen/emit-errors.test.js.map +1 -0
  66. package/build/codegen/emit-index.d.ts +6 -0
  67. package/build/codegen/emit-index.js +49 -0
  68. package/build/codegen/emit-index.js.map +1 -0
  69. package/build/codegen/emit-index.test.d.ts +1 -0
  70. package/build/codegen/emit-index.test.js +83 -0
  71. package/build/codegen/emit-index.test.js.map +1 -0
  72. package/build/codegen/emit-scope.d.ts +6 -0
  73. package/build/codegen/emit-scope.js +194 -0
  74. package/build/codegen/emit-scope.js.map +1 -0
  75. package/build/codegen/emit-scope.test.d.ts +1 -0
  76. package/build/codegen/emit-scope.test.js +276 -0
  77. package/build/codegen/emit-scope.test.js.map +1 -0
  78. package/build/codegen/emit-types.d.ts +14 -0
  79. package/build/codegen/emit-types.js +40 -0
  80. package/build/codegen/emit-types.js.map +1 -0
  81. package/build/codegen/emit-types.test.d.ts +1 -0
  82. package/build/codegen/emit-types.test.js +82 -0
  83. package/build/codegen/emit-types.test.js.map +1 -0
  84. package/build/codegen/group-routes.d.ts +23 -0
  85. package/build/codegen/group-routes.js +46 -0
  86. package/build/codegen/group-routes.js.map +1 -0
  87. package/build/codegen/group-routes.test.d.ts +1 -0
  88. package/build/codegen/group-routes.test.js +131 -0
  89. package/build/codegen/group-routes.test.js.map +1 -0
  90. package/build/codegen/index.d.ts +11 -0
  91. package/build/codegen/index.js +13 -0
  92. package/build/codegen/index.js.map +1 -0
  93. package/build/codegen/pipeline.d.ts +14 -0
  94. package/build/codegen/pipeline.js +49 -0
  95. package/build/codegen/pipeline.js.map +1 -0
  96. package/build/codegen/pipeline.test.d.ts +1 -0
  97. package/build/codegen/pipeline.test.js +151 -0
  98. package/build/codegen/pipeline.test.js.map +1 -0
  99. package/build/codegen/resolve-envelope.d.ts +7 -0
  100. package/build/codegen/resolve-envelope.js +26 -0
  101. package/build/codegen/resolve-envelope.js.map +1 -0
  102. package/build/codegen/resolve-envelope.test.d.ts +1 -0
  103. package/build/codegen/resolve-envelope.test.js +69 -0
  104. package/build/codegen/resolve-envelope.test.js.map +1 -0
  105. package/build/implementations/http/doc-registry.test.js +27 -1
  106. package/build/implementations/http/doc-registry.test.js.map +1 -1
  107. package/build/implementations/http/express-rpc/index.js +1 -0
  108. package/build/implementations/http/express-rpc/index.js.map +1 -1
  109. package/build/implementations/http/express-rpc/index.test.js +1 -1
  110. package/build/implementations/http/express-rpc/index.test.js.map +1 -1
  111. package/build/implementations/http/hono-api/index.js +2 -0
  112. package/build/implementations/http/hono-api/index.js.map +1 -1
  113. package/build/implementations/http/hono-api/index.test.js +9 -0
  114. package/build/implementations/http/hono-api/index.test.js.map +1 -1
  115. package/build/implementations/http/hono-rpc/index.js +1 -0
  116. package/build/implementations/http/hono-rpc/index.js.map +1 -1
  117. package/build/implementations/http/hono-rpc/index.test.js +1 -1
  118. package/build/implementations/http/hono-rpc/index.test.js.map +1 -1
  119. package/build/implementations/http/hono-stream/index.js +17 -1
  120. package/build/implementations/http/hono-stream/index.js.map +1 -1
  121. package/build/implementations/http/hono-stream/index.test.js +61 -0
  122. package/build/implementations/http/hono-stream/index.test.js.map +1 -1
  123. package/build/implementations/http/hono-stream/types.d.ts +4 -13
  124. package/build/implementations/types.d.ts +5 -0
  125. package/build/index.js +8 -1
  126. package/build/index.js.map +1 -1
  127. package/package.json +12 -2
@@ -0,0 +1,83 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { emitIndexFile } from './emit-index.js';
3
+ // ---------------------------------------------------------------------------
4
+ // Fixtures
5
+ // ---------------------------------------------------------------------------
6
+ const usersGroup = {
7
+ scopeKey: 'users',
8
+ camelCase: 'users',
9
+ routes: [],
10
+ };
11
+ const billingGroup = {
12
+ scopeKey: 'billing',
13
+ camelCase: 'billing',
14
+ routes: [],
15
+ };
16
+ const adminUsersGroup = {
17
+ scopeKey: 'admin-users',
18
+ camelCase: 'adminUsers',
19
+ routes: [],
20
+ };
21
+ // ---------------------------------------------------------------------------
22
+ // Tests
23
+ // ---------------------------------------------------------------------------
24
+ describe('emitIndexFile', () => {
25
+ it('includes the auto-generated header comment', () => {
26
+ const output = emitIndexFile([usersGroup]);
27
+ expect(output).toContain('// Auto-generated by ts-procedures-codegen — do not edit');
28
+ });
29
+ it('imports ClientInstance from ts-procedures/client', () => {
30
+ const output = emitIndexFile([usersGroup]);
31
+ expect(output).toContain("import type { ClientInstance } from 'ts-procedures/client'");
32
+ });
33
+ it('imports each bind function using the camelCase scope name', () => {
34
+ const output = emitIndexFile([usersGroup, billingGroup]);
35
+ expect(output).toContain("import { bindUsersScope } from './users'");
36
+ expect(output).toContain("import { bindBillingScope } from './billing'");
37
+ });
38
+ it('re-exports from each scope file', () => {
39
+ const output = emitIndexFile([usersGroup, billingGroup]);
40
+ expect(output).toContain("export * from './users'");
41
+ expect(output).toContain("export * from './billing'");
42
+ });
43
+ it('generates createScopeBindings with correct scope property names', () => {
44
+ const output = emitIndexFile([usersGroup, billingGroup]);
45
+ expect(output).toContain('export function createScopeBindings(client: ClientInstance)');
46
+ expect(output).toContain('users: bindUsersScope(client)');
47
+ expect(output).toContain('billing: bindBillingScope(client)');
48
+ });
49
+ it('uses camelCase as the property key in createScopeBindings', () => {
50
+ const output = emitIndexFile([adminUsersGroup]);
51
+ expect(output).toContain('adminUsers: bindAdminUsersScope(client)');
52
+ });
53
+ it('uses the scopeKey as the import path (not camelCase)', () => {
54
+ const output = emitIndexFile([adminUsersGroup]);
55
+ expect(output).toContain("import { bindAdminUsersScope } from './admin-users'");
56
+ expect(output).toContain("export * from './admin-users'");
57
+ });
58
+ it('handles a single scope group', () => {
59
+ const output = emitIndexFile([usersGroup]);
60
+ expect(output).toContain('bindUsersScope');
61
+ expect(output).toContain('users: bindUsersScope(client)');
62
+ });
63
+ it('places imports before re-exports before createScopeBindings', () => {
64
+ const output = emitIndexFile([usersGroup, billingGroup]);
65
+ const importIdx = output.indexOf("import { bindUsersScope }");
66
+ const reExportIdx = output.indexOf("export * from './users'");
67
+ const bindIdx = output.indexOf('export function createScopeBindings');
68
+ expect(importIdx).toBeLessThan(reExportIdx);
69
+ expect(reExportIdx).toBeLessThan(bindIdx);
70
+ });
71
+ describe('clientImportPath', () => {
72
+ it('uses custom clientImportPath in import statement', () => {
73
+ const output = emitIndexFile([usersGroup], '@my-app/client');
74
+ expect(output).toContain("import type { ClientInstance } from '@my-app/client'");
75
+ expect(output).not.toContain("from 'ts-procedures/client'");
76
+ });
77
+ it('defaults to ts-procedures/client when not specified', () => {
78
+ const output = emitIndexFile([usersGroup]);
79
+ expect(output).toContain("import type { ClientInstance } from 'ts-procedures/client'");
80
+ });
81
+ });
82
+ });
83
+ //# sourceMappingURL=emit-index.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emit-index.test.js","sourceRoot":"","sources":["../../src/codegen/emit-index.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { ScopeGroup } from './group-routes.js';
2
+ import { type AjscOptions } from './emit-types.js';
3
+ /**
4
+ * Generates a complete TypeScript scope file for a ScopeGroup.
5
+ */
6
+ export declare function emitScopeFile(group: ScopeGroup, ajscOpts?: AjscOptions, clientImportPath?: string): Promise<string>;
@@ -0,0 +1,194 @@
1
+ import { jsonSchemaToTypeString } from './emit-types.js';
2
+ // ---------------------------------------------------------------------------
3
+ // Helpers
4
+ // ---------------------------------------------------------------------------
5
+ /** Converts a string to PascalCase (splits on whitespace, hyphens, underscores). */
6
+ function toPascalCase(str) {
7
+ return str
8
+ .split(/[\s\-_]+/)
9
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
10
+ .join('');
11
+ }
12
+ /**
13
+ * Checks whether a JSON schema looks like an SSE envelope.
14
+ * SSE envelopes have properties: data, event, id (and optionally retry).
15
+ */
16
+ function isSseEnvelope(schema) {
17
+ const props = schema.properties;
18
+ if (props == null || typeof props !== 'object')
19
+ return false;
20
+ const keys = Object.keys(props);
21
+ return keys.includes('data') && keys.includes('event') && keys.includes('id');
22
+ }
23
+ /**
24
+ * Unwraps an SSE envelope schema to return the inner `data` property schema.
25
+ * If not an SSE envelope, returns the schema unchanged.
26
+ */
27
+ function unwrapSseEnvelope(schema) {
28
+ if (!isSseEnvelope(schema))
29
+ return schema;
30
+ const props = schema.properties;
31
+ const dataSchema = props['data'];
32
+ return dataSchema ?? schema;
33
+ }
34
+ async function emitRpcRoute(route, ajscOpts) {
35
+ const pascal = toPascalCase(route.name);
36
+ const typeDeclarations = [];
37
+ const paramsType = await jsonSchemaToTypeString(`${pascal}Params`, route.jsonSchema.body, ajscOpts);
38
+ const responseType = await jsonSchemaToTypeString(`${pascal}Response`, route.jsonSchema.response, ajscOpts);
39
+ if (paramsType != null)
40
+ typeDeclarations.push(paramsType);
41
+ if (responseType != null)
42
+ typeDeclarations.push(responseType);
43
+ const paramsTypeName = paramsType != null ? `${pascal}Params` : 'unknown';
44
+ const responseTypeName = responseType != null ? `${pascal}Response` : 'unknown';
45
+ const scopeStr = Array.isArray(route.scope) ? route.scope.join('-') : route.scope;
46
+ const callable = [
47
+ ` /** ${route.method.toUpperCase()} ${route.path} */`,
48
+ ` ${route.name}(params: ${paramsTypeName}, options?: ProcedureCallOptions): Promise<${responseTypeName}> {`,
49
+ ` return client.call<${responseTypeName}>({`,
50
+ ` name: '${route.name}',`,
51
+ ` scope: '${scopeStr}',`,
52
+ ` path: '${route.path}',`,
53
+ ` method: '${route.method}',`,
54
+ ` kind: 'rpc',`,
55
+ ` params,`,
56
+ ` }, options)`,
57
+ ` },`,
58
+ ].join('\n');
59
+ return { typeDeclarations, callable, hasStream: false };
60
+ }
61
+ async function emitApiRoute(route, ajscOpts) {
62
+ const pascal = toPascalCase(route.name);
63
+ const typeDeclarations = [];
64
+ const channelKeys = ['pathParams', 'query', 'body', 'headers'];
65
+ const presentChannels = [];
66
+ for (const channel of channelKeys) {
67
+ const channelSchema = route.jsonSchema[channel];
68
+ if (channelSchema != null) {
69
+ const typeName = `${pascal}${toPascalCase(channel)}`;
70
+ const typeStr = await jsonSchemaToTypeString(typeName, channelSchema, ajscOpts);
71
+ if (typeStr != null) {
72
+ typeDeclarations.push(typeStr);
73
+ presentChannels.push(channel);
74
+ }
75
+ }
76
+ }
77
+ // Compose structured params type
78
+ if (presentChannels.length > 0) {
79
+ const structureFields = presentChannels
80
+ .map((ch) => `${ch}: ${pascal}${toPascalCase(ch)}`)
81
+ .join('; ');
82
+ typeDeclarations.push(`export type ${pascal}Params = { ${structureFields} }`);
83
+ }
84
+ const responseType = await jsonSchemaToTypeString(`${pascal}Response`, route.jsonSchema.response, ajscOpts);
85
+ if (responseType != null)
86
+ typeDeclarations.push(responseType);
87
+ const paramsTypeName = presentChannels.length > 0 ? `${pascal}Params` : 'unknown';
88
+ const responseTypeName = responseType != null ? `${pascal}Response` : 'unknown';
89
+ const scopeStr = route.scope ?? 'default';
90
+ const callable = [
91
+ ` /** ${route.method.toUpperCase()} ${route.fullPath} */`,
92
+ ` ${route.name}(params: ${paramsTypeName}, options?: ProcedureCallOptions): Promise<${responseTypeName}> {`,
93
+ ` return client.call<${responseTypeName}>({`,
94
+ ` name: '${route.name}',`,
95
+ ` scope: '${scopeStr}',`,
96
+ ` path: '${route.fullPath}',`,
97
+ ` method: '${route.method}',`,
98
+ ` kind: 'api',`,
99
+ ` params,`,
100
+ ` }, options)`,
101
+ ` },`,
102
+ ].join('\n');
103
+ return { typeDeclarations, callable, hasStream: false };
104
+ }
105
+ async function emitStreamRoute(route, ajscOpts) {
106
+ const pascal = toPascalCase(route.name);
107
+ const typeDeclarations = [];
108
+ const paramsType = await jsonSchemaToTypeString(`${pascal}Params`, route.jsonSchema.params, ajscOpts);
109
+ // Unwrap SSE envelope from yieldType
110
+ let yieldSchema = route.jsonSchema.yieldType;
111
+ if (yieldSchema != null && route.streamMode === 'sse' && isSseEnvelope(yieldSchema)) {
112
+ yieldSchema = unwrapSseEnvelope(yieldSchema);
113
+ }
114
+ const yieldType = await jsonSchemaToTypeString(`${pascal}Yield`, yieldSchema, ajscOpts);
115
+ const returnType = await jsonSchemaToTypeString(`${pascal}Return`, route.jsonSchema.returnType, ajscOpts);
116
+ if (paramsType != null)
117
+ typeDeclarations.push(paramsType);
118
+ if (yieldType != null)
119
+ typeDeclarations.push(yieldType);
120
+ if (returnType != null)
121
+ typeDeclarations.push(returnType);
122
+ const paramsTypeName = paramsType != null ? `${pascal}Params` : 'unknown';
123
+ const yieldTypeName = yieldType != null ? `${pascal}Yield` : 'unknown';
124
+ const returnTypeName = returnType != null ? `${pascal}Return` : 'void';
125
+ const scopeStr = Array.isArray(route.scope) ? route.scope.join('-') : route.scope;
126
+ const callable = [
127
+ ` /** ${route.methods.map((m) => m.toUpperCase()).join('|')} ${route.path} */`,
128
+ ` ${route.name}(params: ${paramsTypeName}, options?: ProcedureCallOptions): TypedStream<${yieldTypeName}, ${returnTypeName}> {`,
129
+ ` return client.stream<${yieldTypeName}, ${returnTypeName}>({`,
130
+ ` name: '${route.name}',`,
131
+ ` scope: '${scopeStr}',`,
132
+ ` path: '${route.path}',`,
133
+ ` method: '${route.methods[0] ?? 'get'}',`,
134
+ ` kind: 'stream',`,
135
+ ` streamMode: '${route.streamMode}',`,
136
+ ` params,`,
137
+ ` }, options)`,
138
+ ` },`,
139
+ ].join('\n');
140
+ return { typeDeclarations, callable, hasStream: true };
141
+ }
142
+ // ---------------------------------------------------------------------------
143
+ // emitScopeFile
144
+ // ---------------------------------------------------------------------------
145
+ /**
146
+ * Generates a complete TypeScript scope file for a ScopeGroup.
147
+ */
148
+ export async function emitScopeFile(group, ajscOpts, clientImportPath = 'ts-procedures/client') {
149
+ const pascal = toPascalCase(group.camelCase);
150
+ const allTypeDeclarations = [];
151
+ const callables = [];
152
+ let hasStream = false;
153
+ for (const route of group.routes) {
154
+ let chunks;
155
+ if (route.kind === 'rpc') {
156
+ chunks = await emitRpcRoute(route, ajscOpts);
157
+ }
158
+ else if (route.kind === 'api') {
159
+ chunks = await emitApiRoute(route, ajscOpts);
160
+ }
161
+ else {
162
+ chunks = await emitStreamRoute(route, ajscOpts);
163
+ }
164
+ allTypeDeclarations.push(...chunks.typeDeclarations);
165
+ callables.push(chunks.callable);
166
+ if (chunks.hasStream)
167
+ hasStream = true;
168
+ }
169
+ // Build import line
170
+ const clientImports = hasStream
171
+ ? `import type { ClientInstance, ProcedureCallOptions, TypedStream } from '${clientImportPath}'`
172
+ : `import type { ClientInstance, ProcedureCallOptions } from '${clientImportPath}'`;
173
+ const typesBlock = allTypeDeclarations.length > 0
174
+ ? allTypeDeclarations.join('\n') + '\n'
175
+ : '';
176
+ const callablesBlock = callables.join('\n\n');
177
+ return [
178
+ '// Auto-generated by ts-procedures-codegen — do not edit',
179
+ clientImports,
180
+ '',
181
+ '// ── Types ────────────────────────────────────────',
182
+ '',
183
+ typesBlock,
184
+ '// ── Callables ────────────────────────────────────',
185
+ '',
186
+ `export function bind${pascal}Scope(client: ClientInstance) {`,
187
+ ' return {',
188
+ callablesBlock,
189
+ ' }',
190
+ '}',
191
+ '',
192
+ ].join('\n');
193
+ }
194
+ //# sourceMappingURL=emit-scope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emit-scope.js","sourceRoot":"","sources":["../../src/codegen/emit-scope.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,sBAAsB,EAAoB,MAAM,iBAAiB,CAAA;AAE1E,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,oFAAoF;AACpF,SAAS,YAAY,CAAC,GAAW;IAC/B,OAAO,GAAG;SACP,KAAK,CAAC,UAAU,CAAC;SACjB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAC3D,IAAI,CAAC,EAAE,CAAC,CAAA;AACb,CAAC;AAED;;;GAGG;AACH,SAAS,aAAa,CAAC,MAA+B;IACpD,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAA;IAC/B,IAAI,KAAK,IAAI,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IAC5D,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAgC,CAAC,CAAA;IAC1D,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;AAC/E,CAAC;AAED;;;GAGG;AACH,SAAS,iBAAiB,CACxB,MAA+B;IAE/B,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAA;IACzC,MAAM,KAAK,GAAG,MAAM,CAAC,UAAqD,CAAA;IAC1E,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,CAAA;IAChC,OAAO,UAAU,IAAI,MAAM,CAAA;AAC7B,CAAC;AAYD,KAAK,UAAU,YAAY,CAAC,KAAsB,EAAE,QAAsB;IACxE,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACvC,MAAM,gBAAgB,GAAa,EAAE,CAAA;IAErC,MAAM,UAAU,GAAG,MAAM,sBAAsB,CAAC,GAAG,MAAM,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;IACnG,MAAM,YAAY,GAAG,MAAM,sBAAsB,CAAC,GAAG,MAAM,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;IAE3G,IAAI,UAAU,IAAI,IAAI;QAAE,gBAAgB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IACzD,IAAI,YAAY,IAAI,IAAI;QAAE,gBAAgB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;IAE7D,MAAM,cAAc,GAAG,UAAU,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,MAAM,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAA;IACzE,MAAM,gBAAgB,GAAG,YAAY,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,MAAM,UAAU,CAAC,CAAC,CAAC,SAAS,CAAA;IAE/E,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAA;IAEjF,MAAM,QAAQ,GAAG;QACf,WAAW,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,KAAK,CAAC,IAAI,KAAK;QACxD,OAAO,KAAK,CAAC,IAAI,YAAY,cAAc,8CAA8C,gBAAgB,KAAK;QAC9G,4BAA4B,gBAAgB,KAAK;QACjD,kBAAkB,KAAK,CAAC,IAAI,IAAI;QAChC,mBAAmB,QAAQ,IAAI;QAC/B,kBAAkB,KAAK,CAAC,IAAI,IAAI;QAChC,oBAAoB,KAAK,CAAC,MAAM,IAAI;QACpC,sBAAsB;QACtB,iBAAiB;QACjB,mBAAmB;QACnB,QAAQ;KACT,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAEZ,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,CAAA;AACzD,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,KAAsB,EAAE,QAAsB;IACxE,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACvC,MAAM,gBAAgB,GAAa,EAAE,CAAA;IACrC,MAAM,WAAW,GAAG,CAAC,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,CAAU,CAAA;IACvE,MAAM,eAAe,GAAa,EAAE,CAAA;IAEpC,KAAK,MAAM,OAAO,IAAI,WAAW,EAAE,CAAC;QAClC,MAAM,aAAa,GAAG,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;QAC/C,IAAI,aAAa,IAAI,IAAI,EAAE,CAAC;YAC1B,MAAM,QAAQ,GAAG,GAAG,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,EAAE,CAAA;YACpD,MAAM,OAAO,GAAG,MAAM,sBAAsB,CAAC,QAAQ,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAA;YAC/E,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;gBACpB,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gBAC9B,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YAC/B,CAAC;QACH,CAAC;IACH,CAAC;IAED,iCAAiC;IACjC,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,MAAM,eAAe,GAAG,eAAe;aACpC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,KAAK,MAAM,GAAG,YAAY,CAAC,EAAE,CAAC,EAAE,CAAC;aAClD,IAAI,CAAC,IAAI,CAAC,CAAA;QACb,gBAAgB,CAAC,IAAI,CAAC,eAAe,MAAM,cAAc,eAAe,IAAI,CAAC,CAAA;IAC/E,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,sBAAsB,CAAC,GAAG,MAAM,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;IAC3G,IAAI,YAAY,IAAI,IAAI;QAAE,gBAAgB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;IAE7D,MAAM,cAAc,GAAG,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAA;IACjF,MAAM,gBAAgB,GAAG,YAAY,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,MAAM,UAAU,CAAC,CAAC,CAAC,SAAS,CAAA;IAE/E,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,IAAI,SAAS,CAAA;IAEzC,MAAM,QAAQ,GAAG;QACf,WAAW,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,KAAK,CAAC,QAAQ,KAAK;QAC5D,OAAO,KAAK,CAAC,IAAI,YAAY,cAAc,8CAA8C,gBAAgB,KAAK;QAC9G,4BAA4B,gBAAgB,KAAK;QACjD,kBAAkB,KAAK,CAAC,IAAI,IAAI;QAChC,mBAAmB,QAAQ,IAAI;QAC/B,kBAAkB,KAAK,CAAC,QAAQ,IAAI;QACpC,oBAAoB,KAAK,CAAC,MAAM,IAAI;QACpC,sBAAsB;QACtB,iBAAiB;QACjB,mBAAmB;QACnB,QAAQ;KACT,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAEZ,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,CAAA;AACzD,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,KAAyB,EAAE,QAAsB;IAC9E,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACvC,MAAM,gBAAgB,GAAa,EAAE,CAAA;IAErC,MAAM,UAAU,GAAG,MAAM,sBAAsB,CAAC,GAAG,MAAM,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;IAErG,qCAAqC;IACrC,IAAI,WAAW,GAAG,KAAK,CAAC,UAAU,CAAC,SAAS,CAAA;IAC5C,IAAI,WAAW,IAAI,IAAI,IAAI,KAAK,CAAC,UAAU,KAAK,KAAK,IAAI,aAAa,CAAC,WAAW,CAAC,EAAE,CAAC;QACpF,WAAW,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAA;IAC9C,CAAC;IACD,MAAM,SAAS,GAAG,MAAM,sBAAsB,CAAC,GAAG,MAAM,OAAO,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAA;IACvF,MAAM,UAAU,GAAG,MAAM,sBAAsB,CAAC,GAAG,MAAM,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAA;IAEzG,IAAI,UAAU,IAAI,IAAI;QAAE,gBAAgB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IACzD,IAAI,SAAS,IAAI,IAAI;QAAE,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IACvD,IAAI,UAAU,IAAI,IAAI;QAAE,gBAAgB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IAEzD,MAAM,cAAc,GAAG,UAAU,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,MAAM,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAA;IACzE,MAAM,aAAa,GAAG,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,MAAM,OAAO,CAAC,CAAC,CAAC,SAAS,CAAA;IACtE,MAAM,cAAc,GAAG,UAAU,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,MAAM,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAA;IAEtE,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAA;IAEjF,MAAM,QAAQ,GAAG;QACf,WAAW,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK;QACjF,OAAO,KAAK,CAAC,IAAI,YAAY,cAAc,kDAAkD,aAAa,KAAK,cAAc,KAAK;QAClI,8BAA8B,aAAa,KAAK,cAAc,KAAK;QACnE,kBAAkB,KAAK,CAAC,IAAI,IAAI;QAChC,mBAAmB,QAAQ,IAAI;QAC/B,kBAAkB,KAAK,CAAC,IAAI,IAAI;QAChC,oBAAoB,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI;QACjD,yBAAyB;QACzB,wBAAwB,KAAK,CAAC,UAAU,IAAI;QAC5C,iBAAiB;QACjB,mBAAmB;QACnB,QAAQ;KACT,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAEZ,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,CAAA;AACxD,CAAC;AAED,8EAA8E;AAC9E,gBAAgB;AAChB,8EAA8E;AAE9E;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,KAAiB,EACjB,QAAsB,EACtB,gBAAgB,GAAG,sBAAsB;IAEzC,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;IAC5C,MAAM,mBAAmB,GAAa,EAAE,CAAA;IACxC,MAAM,SAAS,GAAa,EAAE,CAAA;IAC9B,IAAI,SAAS,GAAG,KAAK,CAAA;IAErB,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjC,IAAI,MAAmB,CAAA;QAEvB,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;YACzB,MAAM,GAAG,MAAM,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;QAC9C,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;YAChC,MAAM,GAAG,MAAM,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;QAC9C,CAAC;aAAM,CAAC;YACN,MAAM,GAAG,MAAM,eAAe,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;QACjD,CAAC;QAED,mBAAmB,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAA;QACpD,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QAC/B,IAAI,MAAM,CAAC,SAAS;YAAE,SAAS,GAAG,IAAI,CAAA;IACxC,CAAC;IAED,oBAAoB;IACpB,MAAM,aAAa,GAAG,SAAS;QAC7B,CAAC,CAAC,2EAA2E,gBAAgB,GAAG;QAChG,CAAC,CAAC,8DAA8D,gBAAgB,GAAG,CAAA;IAErF,MAAM,UAAU,GACd,mBAAmB,CAAC,MAAM,GAAG,CAAC;QAC5B,CAAC,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI;QACvC,CAAC,CAAC,EAAE,CAAA;IAER,MAAM,cAAc,GAAG,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAE7C,OAAO;QACL,0DAA0D;QAC1D,aAAa;QACb,EAAE;QACF,sDAAsD;QACtD,EAAE;QACF,UAAU;QACV,sDAAsD;QACtD,EAAE;QACF,uBAAuB,MAAM,iCAAiC;QAC9D,YAAY;QACZ,cAAc;QACd,KAAK;QACL,GAAG;QACH,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACd,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,276 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { emitScopeFile } from './emit-scope.js';
3
+ // ---------------------------------------------------------------------------
4
+ // Fixtures
5
+ // ---------------------------------------------------------------------------
6
+ const rpcGroup = {
7
+ scopeKey: 'users',
8
+ camelCase: 'users',
9
+ routes: [
10
+ {
11
+ kind: 'rpc',
12
+ name: 'GetUser',
13
+ path: '/users/1',
14
+ method: 'post',
15
+ scope: 'users',
16
+ version: 1,
17
+ jsonSchema: {
18
+ body: {
19
+ type: 'object',
20
+ properties: { id: { type: 'string' } },
21
+ required: ['id'],
22
+ },
23
+ response: {
24
+ type: 'object',
25
+ properties: { name: { type: 'string' } },
26
+ required: ['name'],
27
+ },
28
+ },
29
+ },
30
+ ],
31
+ };
32
+ const apiGroup = {
33
+ scopeKey: 'posts',
34
+ camelCase: 'posts',
35
+ routes: [
36
+ {
37
+ kind: 'api',
38
+ name: 'UpdatePost',
39
+ path: '/posts/:id',
40
+ method: 'put',
41
+ fullPath: '/api/posts/:id',
42
+ scope: 'posts',
43
+ jsonSchema: {
44
+ pathParams: {
45
+ type: 'object',
46
+ properties: { id: { type: 'string' } },
47
+ required: ['id'],
48
+ },
49
+ body: {
50
+ type: 'object',
51
+ properties: { title: { type: 'string' } },
52
+ required: ['title'],
53
+ },
54
+ response: {
55
+ type: 'object',
56
+ properties: { id: { type: 'string' }, title: { type: 'string' } },
57
+ required: ['id', 'title'],
58
+ },
59
+ },
60
+ },
61
+ ],
62
+ };
63
+ const streamGroup = {
64
+ scopeKey: 'events',
65
+ camelCase: 'events',
66
+ routes: [
67
+ {
68
+ kind: 'stream',
69
+ name: 'WatchEvents',
70
+ path: '/events/stream',
71
+ methods: ['get'],
72
+ streamMode: 'sse',
73
+ scope: 'events',
74
+ version: 1,
75
+ jsonSchema: {
76
+ params: {
77
+ type: 'object',
78
+ properties: { filter: { type: 'string' } },
79
+ required: [],
80
+ },
81
+ // SSE envelope: data wraps the actual yield type
82
+ yieldType: {
83
+ type: 'object',
84
+ properties: {
85
+ data: {
86
+ type: 'object',
87
+ properties: { message: { type: 'string' } },
88
+ required: ['message'],
89
+ },
90
+ event: { type: 'string' },
91
+ id: { type: 'string' },
92
+ retry: { type: 'number' },
93
+ },
94
+ required: ['data'],
95
+ },
96
+ returnType: {
97
+ type: 'object',
98
+ properties: { total: { type: 'number' } },
99
+ required: ['total'],
100
+ },
101
+ },
102
+ },
103
+ ],
104
+ };
105
+ const streamGroupText = {
106
+ scopeKey: 'feed',
107
+ camelCase: 'feed',
108
+ routes: [
109
+ {
110
+ kind: 'stream',
111
+ name: 'GetFeed',
112
+ path: '/feed/stream',
113
+ methods: ['get'],
114
+ streamMode: 'text',
115
+ scope: 'feed',
116
+ version: 1,
117
+ jsonSchema: {
118
+ params: undefined,
119
+ yieldType: {
120
+ type: 'string',
121
+ },
122
+ returnType: undefined,
123
+ },
124
+ },
125
+ ],
126
+ };
127
+ // ---------------------------------------------------------------------------
128
+ // Tests
129
+ // ---------------------------------------------------------------------------
130
+ describe('emitScopeFile', () => {
131
+ describe('RPC scope', () => {
132
+ it('includes the auto-generated header comment', async () => {
133
+ const output = await emitScopeFile(rpcGroup);
134
+ expect(output).toContain('// Auto-generated by ts-procedures-codegen — do not edit');
135
+ });
136
+ it('imports ClientInstance and ProcedureCallOptions but not TypedStream', async () => {
137
+ const output = await emitScopeFile(rpcGroup);
138
+ expect(output).toContain("import type { ClientInstance, ProcedureCallOptions } from 'ts-procedures/client'");
139
+ expect(output).not.toContain('TypedStream');
140
+ });
141
+ it('exports param type from jsonSchema.body', async () => {
142
+ const output = await emitScopeFile(rpcGroup);
143
+ expect(output).toContain('export type GetUserParams');
144
+ });
145
+ it('exports response type from jsonSchema.response', async () => {
146
+ const output = await emitScopeFile(rpcGroup);
147
+ expect(output).toContain('export type GetUserResponse');
148
+ });
149
+ it('emits the bindUsersScope function', async () => {
150
+ const output = await emitScopeFile(rpcGroup);
151
+ expect(output).toContain('export function bindUsersScope(client: ClientInstance)');
152
+ });
153
+ it('callable uses client.call with kind: rpc', async () => {
154
+ const output = await emitScopeFile(rpcGroup);
155
+ expect(output).toContain("kind: 'rpc'");
156
+ expect(output).toContain('client.call');
157
+ });
158
+ it('callable includes JSDoc with method and path', async () => {
159
+ const output = await emitScopeFile(rpcGroup);
160
+ expect(output).toContain('POST');
161
+ expect(output).toContain('/users/1');
162
+ });
163
+ });
164
+ describe('API scope', () => {
165
+ it('generates PascalCase channel types', async () => {
166
+ const output = await emitScopeFile(apiGroup);
167
+ expect(output).toContain('export type UpdatePostPathParams');
168
+ expect(output).toContain('export type UpdatePostBody');
169
+ });
170
+ it('composes structured params type', async () => {
171
+ const output = await emitScopeFile(apiGroup);
172
+ expect(output).toContain('export type UpdatePostParams =');
173
+ expect(output).toContain('pathParams: UpdatePostPathParams');
174
+ expect(output).toContain('body: UpdatePostBody');
175
+ });
176
+ it('exports response type', async () => {
177
+ const output = await emitScopeFile(apiGroup);
178
+ expect(output).toContain('export type UpdatePostResponse');
179
+ });
180
+ it('callable uses client.call with kind: api', async () => {
181
+ const output = await emitScopeFile(apiGroup);
182
+ expect(output).toContain("kind: 'api'");
183
+ expect(output).toContain('client.call');
184
+ });
185
+ it('callable includes JSDoc with method and fullPath', async () => {
186
+ const output = await emitScopeFile(apiGroup);
187
+ expect(output).toContain('PUT');
188
+ expect(output).toContain('/api/posts/:id');
189
+ });
190
+ it('callable path field uses fullPath not path', async () => {
191
+ const output = await emitScopeFile(apiGroup);
192
+ // fullPath should appear in the path: field of the callable
193
+ expect(output).toContain("path: '/api/posts/:id'");
194
+ // The bare path without prefix should NOT appear as path: value
195
+ expect(output).not.toContain("path: '/posts/:id'");
196
+ });
197
+ });
198
+ describe('Stream scope', () => {
199
+ it('imports TypedStream when stream routes are present', async () => {
200
+ const output = await emitScopeFile(streamGroup);
201
+ expect(output).toContain('TypedStream');
202
+ expect(output).toContain("import type { ClientInstance, ProcedureCallOptions, TypedStream } from 'ts-procedures/client'");
203
+ });
204
+ it('unwraps SSE envelope for yieldType', async () => {
205
+ const output = await emitScopeFile(streamGroup);
206
+ // Should have WatchEventsYield type based on the inner data schema, not the full SSE envelope
207
+ expect(output).toContain('export type WatchEventsYield');
208
+ // The yield type should be from the data property (has 'message'), not the envelope (has event/id/retry)
209
+ const yieldTypeMatch = output.match(/export type WatchEventsYield = ([^;]+)/);
210
+ expect(yieldTypeMatch).not.toBeNull();
211
+ // Should NOT contain the SSE envelope fields like "event" or "retry" directly
212
+ // The resolved type should be the inner data object
213
+ });
214
+ it('emits params type from jsonSchema.params', async () => {
215
+ const output = await emitScopeFile(streamGroup);
216
+ expect(output).toContain('export type WatchEventsParams');
217
+ });
218
+ it('emits return type from jsonSchema.returnType', async () => {
219
+ const output = await emitScopeFile(streamGroup);
220
+ expect(output).toContain('export type WatchEventsReturn');
221
+ });
222
+ it('callable uses client.stream with kind: stream and streamMode', async () => {
223
+ const output = await emitScopeFile(streamGroup);
224
+ expect(output).toContain("kind: 'stream'");
225
+ expect(output).toContain("streamMode: 'sse'");
226
+ expect(output).toContain('client.stream');
227
+ });
228
+ it('callable returns TypedStream<Yield, Return>', async () => {
229
+ const output = await emitScopeFile(streamGroup);
230
+ expect(output).toContain('TypedStream<WatchEventsYield, WatchEventsReturn>');
231
+ });
232
+ it('does not import TypedStream for non-stream scopes', async () => {
233
+ const output = await emitScopeFile(rpcGroup);
234
+ expect(output).not.toContain('TypedStream');
235
+ });
236
+ it('handles text stream without SSE unwrapping', async () => {
237
+ const output = await emitScopeFile(streamGroupText);
238
+ // text stream - yieldType is plain string, no unwrapping
239
+ expect(output).toContain('export type GetFeedYield');
240
+ });
241
+ it('omits params type when params schema is undefined', async () => {
242
+ const output = await emitScopeFile(streamGroupText);
243
+ expect(output).not.toContain('GetFeedParams');
244
+ });
245
+ });
246
+ describe('bindScope function structure', () => {
247
+ it('wraps callables in the bind function return object', async () => {
248
+ const output = await emitScopeFile(rpcGroup);
249
+ expect(output).toMatch(/export function bindUsersScope\(client: ClientInstance\)/);
250
+ expect(output).toContain('return {');
251
+ });
252
+ it('places types section before callables section', async () => {
253
+ const output = await emitScopeFile(rpcGroup);
254
+ const typesIdx = output.indexOf('// ── Types');
255
+ const callablesIdx = output.indexOf('// ── Callables');
256
+ expect(typesIdx).toBeLessThan(callablesIdx);
257
+ });
258
+ });
259
+ describe('clientImportPath', () => {
260
+ it('uses custom clientImportPath in import statement', async () => {
261
+ const output = await emitScopeFile(rpcGroup, undefined, '@my-app/client');
262
+ expect(output).toContain("from '@my-app/client'");
263
+ expect(output).not.toContain("from 'ts-procedures/client'");
264
+ });
265
+ it('uses custom clientImportPath for stream scope imports', async () => {
266
+ const output = await emitScopeFile(streamGroup, undefined, '@my-app/client');
267
+ expect(output).toContain("from '@my-app/client'");
268
+ expect(output).toContain('TypedStream');
269
+ });
270
+ it('defaults to ts-procedures/client when not specified', async () => {
271
+ const output = await emitScopeFile(rpcGroup);
272
+ expect(output).toContain("from 'ts-procedures/client'");
273
+ });
274
+ });
275
+ });
276
+ //# sourceMappingURL=emit-scope.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emit-scope.test.js","sourceRoot":"","sources":["../../src/codegen/emit-scope.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export interface AjscOptions {
2
+ enumStyle?: 'union' | 'enum';
3
+ depluralize?: boolean;
4
+ inlineTypes?: boolean;
5
+ }
6
+ /**
7
+ * Converts a JSON Schema to a TypeScript type string using ajsc.
8
+ *
9
+ * Returns `export type ${typeName} = ${code}` where code is the inline type
10
+ * body from TypescriptConverter with inlineTypes: true.
11
+ *
12
+ * Returns undefined for undefined or null schema.
13
+ */
14
+ export declare function jsonSchemaToTypeString(typeName: string, schema: Record<string, unknown> | undefined, options?: AjscOptions): Promise<string | undefined>;