@aws-blocks/core 0.4.0 → 0.5.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/README.md +12 -0
- package/dist/cdk/blocks-backend.d.ts +4 -1
- package/dist/cdk/blocks-backend.d.ts.map +1 -1
- package/dist/cdk/blocks-backend.js +56 -10
- package/dist/cdk/blocks-backend.test.js +71 -1
- package/dist/cdk/blocks-defaults.d.ts +11 -0
- package/dist/cdk/blocks-defaults.d.ts.map +1 -1
- package/dist/cdk/blocks-stack.test.js +23 -3
- package/dist/cdk/compute/compute.d.ts +80 -2
- package/dist/cdk/compute/compute.d.ts.map +1 -1
- package/dist/cdk/compute/compute.js +57 -3
- package/dist/cdk/config-registry.test.js +12 -0
- package/dist/cdk/dashboard-registry.d.ts +41 -0
- package/dist/cdk/dashboard-registry.d.ts.map +1 -0
- package/dist/cdk/dashboard-registry.js +61 -0
- package/dist/cdk/index.d.ts +67 -11
- package/dist/cdk/index.d.ts.map +1 -1
- package/dist/cdk/index.js +100 -18
- package/dist/cdk/internal.d.ts +3 -1
- package/dist/cdk/internal.d.ts.map +1 -1
- package/dist/cdk/internal.js +4 -1
- package/dist/cdk/tracer-registry.d.ts +31 -0
- package/dist/cdk/tracer-registry.d.ts.map +1 -0
- package/dist/cdk/tracer-registry.js +49 -0
- package/dist/cdk/vpc-requirements-registry.d.ts +33 -0
- package/dist/cdk/vpc-requirements-registry.d.ts.map +1 -0
- package/dist/cdk/vpc-requirements-registry.js +46 -0
- package/dist/cdk/vpc-types.d.ts +151 -0
- package/dist/cdk/vpc-types.d.ts.map +1 -0
- package/dist/cdk/vpc-types.js +3 -0
- package/dist/cdk/vpc.d.ts +59 -0
- package/dist/cdk/vpc.d.ts.map +1 -0
- package/dist/cdk/vpc.js +298 -0
- package/dist/cdk/vpc.test.d.ts +2 -0
- package/dist/cdk/vpc.test.d.ts.map +1 -0
- package/dist/cdk/vpc.test.js +285 -0
- package/dist/errors.d.ts +5 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +5 -0
- package/dist/hosting.d.ts.map +1 -1
- package/dist/hosting.js +2 -0
- package/dist/hosting.test.js +39 -1
- package/dist/index.cdk.d.ts +2 -1
- package/dist/index.cdk.d.ts.map +1 -1
- package/dist/index.cdk.js +1 -1
- package/dist/lambda-handler.js +9 -2
- package/dist/lambda-handler.test.js +61 -1
- package/dist/raw-route.d.ts +15 -1
- package/dist/raw-route.d.ts.map +1 -1
- package/dist/raw-route.js +96 -12
- package/dist/raw-route.test.js +332 -1
- package/dist/scripts/dev-server.d.ts.map +1 -1
- package/dist/scripts/dev-server.js +11 -0
- package/dist/scripts/extract-ts-types.d.ts.map +1 -1
- package/dist/scripts/extract-ts-types.js +107 -23
- package/dist/scripts/extract-ts-types.test.js +225 -26
- package/dist/scripts/generate-spec.d.ts.map +1 -1
- package/dist/scripts/generate-spec.js +14 -5
- package/dist/scripts/generate-spec.test.js +93 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +8 -1
- package/src/cdk/blocks-backend.test.ts +144 -60
- package/src/cdk/blocks-backend.ts +298 -239
- package/src/cdk/blocks-defaults.ts +12 -0
- package/src/cdk/blocks-stack.test.ts +32 -13
- package/src/cdk/compute/compute.ts +105 -3
- package/src/cdk/config-registry.test.ts +14 -0
- package/src/cdk/dashboard-registry.ts +68 -0
- package/src/cdk/index.ts +426 -298
- package/src/cdk/internal.ts +6 -2
- package/src/cdk/tracer-registry.ts +54 -0
- package/src/cdk/vpc-requirements-registry.ts +63 -0
- package/src/cdk/vpc-types.ts +158 -0
- package/src/cdk/vpc.test.ts +348 -0
- package/src/cdk/vpc.ts +336 -0
- package/src/errors.ts +5 -0
- package/src/hosting.test.ts +59 -1
- package/src/hosting.ts +3 -0
- package/src/index.cdk.ts +7 -0
- package/src/lambda-handler.test.ts +79 -1
- package/src/lambda-handler.ts +11 -2
- package/src/raw-route.test.ts +427 -1
- package/src/raw-route.ts +125 -12
- package/src/scripts/dev-server.ts +12 -1
- package/src/scripts/extract-ts-types.test.ts +228 -26
- package/src/scripts/extract-ts-types.ts +104 -20
- package/src/scripts/generate-spec.test.ts +101 -0
- package/src/scripts/generate-spec.ts +15 -5
- package/src/version.ts +1 -1
|
@@ -16,6 +16,7 @@ import { join, dirname } from 'path';
|
|
|
16
16
|
import { tmpdir } from 'os';
|
|
17
17
|
import { fileURLToPath, pathToFileURL } from 'url';
|
|
18
18
|
import { generateSpec } from './generate-spec.js';
|
|
19
|
+
import { ApiNamespace } from '../api.js';
|
|
19
20
|
|
|
20
21
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
21
22
|
// `import.meta.url` lives in dist/scripts/, so `..` is dist/ and the built
|
|
@@ -97,3 +98,103 @@ describe('generateSpec — @blocksSkipCodegen', () => {
|
|
|
97
98
|
}
|
|
98
99
|
});
|
|
99
100
|
});
|
|
101
|
+
|
|
102
|
+
describe('generateSpec — namespaces sharing a method name (regression: #445)', () => {
|
|
103
|
+
it('emits each namespace its OWN schema for a same-named method', async () => {
|
|
104
|
+
const dir = join(tmpdir(), `blocks-spec-test-${Date.now()}-collision`);
|
|
105
|
+
mkdirSync(dir, { recursive: true });
|
|
106
|
+
writeTsconfig(dir);
|
|
107
|
+
|
|
108
|
+
// Typed foundation for the TS type extractor. `create` has DIFFERENT params
|
|
109
|
+
// in each namespace; binding names (widgets/subscriptions) match the runtime
|
|
110
|
+
// module's export names below.
|
|
111
|
+
writeFileSync(join(dir, 'index.ts'), `
|
|
112
|
+
interface ApiNamespaceConstructor { new <T>(scope: any, name: string, handler: (ctx: any) => T): T; }
|
|
113
|
+
const ApiNamespace: ApiNamespaceConstructor = class {} as any;
|
|
114
|
+
|
|
115
|
+
export const widgets = new ApiNamespace(null, 'widgets', () => ({
|
|
116
|
+
async create(label: string): Promise<{ widgetId: string }> { return { widgetId: 'w' }; },
|
|
117
|
+
}));
|
|
118
|
+
export const subscriptions = new ApiNamespace(null, 'subscriptions', () => ({
|
|
119
|
+
async create(topicCount: number): Promise<{ subId: number }> { return { subId: 1 }; },
|
|
120
|
+
}));
|
|
121
|
+
`);
|
|
122
|
+
|
|
123
|
+
// Runtime module for namespace discovery (types come from the .ts above via
|
|
124
|
+
// the extractor). Use the real ApiNamespace so the marker symbol matches.
|
|
125
|
+
const widgets = new ApiNamespace(null as any, 'widgets', () => ({ async create(_label: string) { return { widgetId: 'w' }; } }));
|
|
126
|
+
const subscriptions = new ApiNamespace(null as any, 'subscriptions', () => ({ async create(_topicCount: number) { return { subId: 1 }; } }));
|
|
127
|
+
const loader = async () => ({ widgets, subscriptions }) as Record<string, unknown>;
|
|
128
|
+
|
|
129
|
+
try {
|
|
130
|
+
const doc = await generateSpec(join(dir, 'index.ts'), loader);
|
|
131
|
+
const byName = new Map(doc.methods.map((m) => [m.name, m]));
|
|
132
|
+
|
|
133
|
+
const w = byName.get('widgets.create');
|
|
134
|
+
const s = byName.get('subscriptions.create');
|
|
135
|
+
assert.ok(w && s, 'both namespace-qualified methods should be present');
|
|
136
|
+
|
|
137
|
+
// Each keeps its OWN param — no cross-assignment.
|
|
138
|
+
assert.strictEqual(w!.params[0]?.name, 'label');
|
|
139
|
+
assert.strictEqual((w!.params[0] as any)?.schema?.type, 'string');
|
|
140
|
+
assert.strictEqual(s!.params[0]?.name, 'topicCount');
|
|
141
|
+
assert.strictEqual((s!.params[0] as any)?.schema?.type, 'number');
|
|
142
|
+
} finally {
|
|
143
|
+
rmSync(dir, { recursive: true, force: true });
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
describe('generateSpec — namespace returned by a factory, then destructured (regression: #444)', () => {
|
|
149
|
+
it('emits real schemas (not unknown) for a factory/destructured namespace', async () => {
|
|
150
|
+
const dir = join(tmpdir(), `blocks-spec-test-${Date.now()}-factory`);
|
|
151
|
+
mkdirSync(dir, { recursive: true });
|
|
152
|
+
writeTsconfig(dir);
|
|
153
|
+
|
|
154
|
+
// Typed foundation: one directly-exported namespace and one built inside a
|
|
155
|
+
// factory, returned as a property, destructured, and re-exported. Both use
|
|
156
|
+
// `create` with DIFFERENT params so a regression would cross-assign or emit
|
|
157
|
+
// unknown.
|
|
158
|
+
writeFileSync(join(dir, 'index.ts'), `
|
|
159
|
+
interface ApiNamespaceConstructor { new <T>(scope: any, name: string, handler: (ctx: any) => T): T; }
|
|
160
|
+
const ApiNamespace: ApiNamespaceConstructor = class {} as any;
|
|
161
|
+
class Scope { constructor(id: string) {} }
|
|
162
|
+
|
|
163
|
+
class Factory {
|
|
164
|
+
constructor(private readonly scope: Scope) {}
|
|
165
|
+
build() {
|
|
166
|
+
return {
|
|
167
|
+
subscriptions: new ApiNamespace(this.scope, 'subscriptions', () => ({
|
|
168
|
+
async create(topicCount: number): Promise<{ subId: number }> { return { subId: 1 }; },
|
|
169
|
+
})),
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const scope = new Scope('app');
|
|
175
|
+
export const widgets = new ApiNamespace(scope, 'widgets', () => ({
|
|
176
|
+
async create(label: string): Promise<{ widgetId: string }> { return { widgetId: 'w' }; },
|
|
177
|
+
}));
|
|
178
|
+
const { subscriptions } = new Factory(scope).build();
|
|
179
|
+
export { subscriptions };
|
|
180
|
+
`);
|
|
181
|
+
|
|
182
|
+
const widgets = new ApiNamespace(null as any, 'widgets', () => ({ async create(_label: string) { return { widgetId: 'w' }; } }));
|
|
183
|
+
const subscriptions = new ApiNamespace(null as any, 'subscriptions', () => ({ async create(_topicCount: number) { return { subId: 1 }; } }));
|
|
184
|
+
const loader = async () => ({ widgets, subscriptions }) as Record<string, unknown>;
|
|
185
|
+
|
|
186
|
+
try {
|
|
187
|
+
const doc = await generateSpec(join(dir, 'index.ts'), loader);
|
|
188
|
+
const byName = new Map(doc.methods.map((m) => [m.name, m]));
|
|
189
|
+
const w = byName.get('widgets.create');
|
|
190
|
+
const s = byName.get('subscriptions.create');
|
|
191
|
+
assert.ok(w && s, 'both qualified methods present');
|
|
192
|
+
// The factory-returned namespace keeps its own param, not `unknown` and
|
|
193
|
+
// not the direct namespace's `string`.
|
|
194
|
+
assert.strictEqual((s!.params[0] as any)?.schema?.type, 'number');
|
|
195
|
+
assert.strictEqual((w!.params[0] as any)?.schema?.type, 'string');
|
|
196
|
+
} finally {
|
|
197
|
+
rmSync(dir, { recursive: true, force: true });
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
});
|
|
@@ -324,6 +324,16 @@ export async function generateSpec(
|
|
|
324
324
|
for (const [methodName, methodFn] of Object.entries(methodMap)) {
|
|
325
325
|
if (typeof methodFn !== 'function') continue;
|
|
326
326
|
|
|
327
|
+
const qualifiedName = `${routingName}.${methodName}`;
|
|
328
|
+
// Prefer the namespace-qualified TS types; fall back to the bare method
|
|
329
|
+
// name for entries the extractor couldn't attribute to a namespace.
|
|
330
|
+
// Qualified keys stop two namespaces that share a method name (e.g.
|
|
331
|
+
// widgets.create / subscriptions.create) from cross-assigning schemas.
|
|
332
|
+
// Residual edge: namespaces the extractor can't attribute (default export,
|
|
333
|
+
// factory-wrapped, or an `export { x as y }` rename) still land on bare
|
|
334
|
+
// keys and could overwrite each other here — same class as #445, but rare.
|
|
335
|
+
const tsInfo = tsTypes.get(qualifiedName) ?? tsTypes.get(methodName);
|
|
336
|
+
|
|
327
337
|
// `@blocksSkipCodegen` is a JSDoc tag the customer puts on a method
|
|
328
338
|
// they want callable from the generated TS client (Proxy-based,
|
|
329
339
|
// doesn't enumerate) but absent from the OpenRPC spec — so native
|
|
@@ -334,9 +344,11 @@ export async function generateSpec(
|
|
|
334
344
|
// type-resolution errors and silently empty its Map — we always
|
|
335
345
|
// want the JSDoc tag to be honored, so the AST-only scan acts as
|
|
336
346
|
// a safety net.
|
|
337
|
-
|
|
347
|
+
// The skip set is namespace-qualified too (with a bare fallback), so a
|
|
348
|
+
// `@blocksSkipCodegen` tag on one namespace's method doesn't drop another
|
|
349
|
+
// namespace's same-named method.
|
|
350
|
+
if (tsInfo?.skipCodegen || skipCodegenNames.has(qualifiedName) || skipCodegenNames.has(methodName)) continue;
|
|
338
351
|
|
|
339
|
-
const qualifiedName = `${routingName}.${methodName}`;
|
|
340
352
|
const resultName = capitalize(methodName) + 'Result';
|
|
341
353
|
const paramNames = extractParamNames(methodFn);
|
|
342
354
|
const fnSource = methodFn.toString();
|
|
@@ -380,7 +392,6 @@ export async function generateSpec(
|
|
|
380
392
|
}));
|
|
381
393
|
} else {
|
|
382
394
|
// No Zod schema — fall back to TypeScript AST types
|
|
383
|
-
const tsInfo = tsTypes.get(methodName);
|
|
384
395
|
if (tsInfo) {
|
|
385
396
|
params = tsInfo.params.map((p) => ({
|
|
386
397
|
name: p.name,
|
|
@@ -397,8 +408,7 @@ export async function generateSpec(
|
|
|
397
408
|
}
|
|
398
409
|
}
|
|
399
410
|
|
|
400
|
-
// Return type: Zod doesn't cover this yet, so use TS types
|
|
401
|
-
const tsInfo = tsTypes.get(methodName);
|
|
411
|
+
// Return type: Zod doesn't cover this yet, so use TS types (tsInfo resolved above)
|
|
402
412
|
const rawResultSchema = tsInfo?.returnType && tsInfo.returnType.type !== 'unknown'
|
|
403
413
|
? tsInfo.returnType
|
|
404
414
|
: { type: 'unknown' };
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Auto-generated by scripts/generate-version.mjs — do not edit manually
|
|
2
|
-
export const CORE_VERSION = '0.
|
|
2
|
+
export const CORE_VERSION = '0.5.0';
|