@pixel-point/toolcraft 0.0.16 → 0.0.17
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/package.json +1 -1
- package/src/generate-performance-iteration-execution.test.mjs +2 -2
- package/src/generate-test-demand-only-lifecycle.mjs +14 -3
- package/src/generate-test-dependency-sandbox.mjs +42 -5
- package/src/generate-test-doc-assertions.mjs +68 -18
- package/src/generate-test-doc-assertions.test.mjs +22 -0
- package/src/generate-test-file-assertions.mjs +43 -76
- package/src/generate-test-output-assertions.mjs +95 -0
- package/src/generate-test-package-assertions.mjs +6 -0
- package/src/generate-test-performance-boundary-assertions.mjs +45 -0
- package/src/generate-test-product-fixture.mjs +1 -0
- package/src/generate-test-product-fixture.test.mjs +18 -0
- package/src/generate-test-product-iteration.mjs +1 -0
- package/src/generate-test-product-iteration.test.mjs +1 -0
- package/src/generate-test-standalone-delivery-stages.mjs +14 -6
- package/src/generate.test.mjs +14 -0
- package/templates/runtime/contracts/component-contracts.choices.test.ts +12 -9
- package/templates/runtime/contracts/component-contracts.choices.ts +10 -9
- package/templates/runtime/contracts/component-contracts.runtime-acceptance.test.ts +17 -2
- package/templates/runtime/contracts/component-contracts.runtime-panels.test.ts +1 -1
- package/templates/runtime/contracts/component-contracts.runtime-shell.test.ts +1 -1
- package/templates/runtime/contracts/component-contracts.runtime.ts +3 -2
- package/templates/runtime/contracts/decision-contracts.test.ts +25 -4
- package/templates/runtime/contracts/decision-contracts.ts +3 -3
- package/templates/runtime/contracts/performance-verification-policy.test.ts +59 -6
- package/templates/runtime/contracts/performance-verification-policy.ts +5 -2
- package/templates/runtime/export/artifact-download.test.ts +71 -0
- package/templates/runtime/export/artifact-download.ts +80 -0
- package/templates/runtime/export/artifact-export-request.ts +23 -0
- package/templates/runtime/export/artifact-export-settings.test.ts +75 -0
- package/templates/runtime/export/artifact-export-settings.ts +96 -0
- package/templates/runtime/export/artifact-frame-renderer.test.ts +107 -0
- package/templates/runtime/export/artifact-frame-renderer.ts +96 -0
- package/templates/runtime/export/artifact-frame-state.test.ts +54 -0
- package/templates/runtime/export/artifact-frame-state.ts +44 -0
- package/templates/runtime/export/artifact-scene-frame.test.ts +84 -0
- package/templates/runtime/export/artifact-scene-frame.ts +118 -0
- package/templates/runtime/export/export-background.ts +65 -0
- package/templates/runtime/export/export-error.ts +43 -0
- package/templates/runtime/export/export.test.ts +6 -186
- package/templates/runtime/export/image-artifact-export.test.ts +111 -0
- package/templates/runtime/export/image-artifact-export.ts +145 -0
- package/templates/runtime/export/index.ts +14 -1
- package/templates/runtime/export/product-export-renderer.test.ts +77 -0
- package/templates/runtime/export/product-export-renderer.ts +63 -0
- package/templates/runtime/export/video-artifact-export.test.ts +166 -0
- package/templates/runtime/export/video-artifact-export.ts +164 -0
- package/templates/runtime/export/video-encoding-backend.ts +124 -0
- package/templates/runtime/export/video-encoding-policy.test.ts +68 -0
- package/templates/runtime/export/video-encoding-policy.ts +86 -0
- package/templates/runtime/export/video-frame-schedule.test.ts +58 -0
- package/templates/runtime/export/video-frame-schedule.ts +42 -0
- package/templates/runtime/index.ts +1 -0
- package/templates/runtime/react/app-shell/runtime-public-api-runtime.test.tsx +291 -0
- package/templates/runtime/react/app-shell/runtime-public-api-test-support.ts +21 -0
- package/templates/runtime/react/app-shell/runtime-public-api.test.tsx +4 -303
- package/templates/runtime/react/app-shell/toolcraft-app.scene-export.test.tsx +12 -27
- package/templates/runtime/react/app-shell/toolcraft-app.tsx +22 -4
- package/templates/runtime/react/app-shell/toolcraft-source-asset-context.test.tsx +16 -57
- package/templates/runtime/react/app-shell/toolcraft-source-asset-context.tsx +75 -434
- package/templates/runtime/react/app-shell/toolcraft-source-asset-owner.test.ts +194 -0
- package/templates/runtime/react/app-shell/toolcraft-source-asset-owner.ts +227 -0
- package/templates/runtime/react/app-shell/toolcraft-source-asset-provider-ownership.test.tsx +243 -0
- package/templates/runtime/react/app-shell/toolcraft-source-asset-test-support.ts +51 -0
- package/templates/runtime/react/app-shell/toolcraft-unavailable-resource-proof.test.ts +138 -0
- package/templates/runtime/react/app-shell/toolcraft-unavailable-resource-proof.ts +378 -0
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.footer-actions.test.tsx +7 -12
- package/templates/runtime/react/controls-panel/__tests__/controls-panel.scene-export-actions.test.tsx +17 -83
- package/templates/runtime/react/controls-panel/actions/controls-panel-actions.ts +42 -84
- package/templates/runtime/react/controls-panel/actions/export-action-runner.ts +62 -0
- package/templates/runtime/react/panel-host/panel-host-runtime-placement.test.tsx +30 -0
- package/templates/runtime/react/panel-host/panel-host.tsx +4 -0
- package/templates/runtime/scene/scene-bounds.ts +1 -2
- package/templates/runtime/schema/canvas-render-scale.ts +62 -0
- package/templates/runtime/schema/controls-panel-section-id.test.ts +1 -1
- package/templates/runtime/schema/controls-panel-section-roundtrip.test.ts +3 -3
- package/templates/runtime/schema/define-toolcraft.setup-background.test.ts +1 -1
- package/templates/runtime/schema/define-toolcraft.setup-render-scale-timeline.test.ts +71 -3
- package/templates/runtime/schema/define-toolcraft.ts +1 -1
- package/templates/runtime/schema/schema-resolvers.ts +0 -56
- package/templates/runtime/schema/types.ts +4 -4
- package/templates/runtime/state/canvas-background-state.ts +6 -0
- package/templates/runtime/testing/performance-render-plan-integration.test.ts +64 -0
- package/templates/runtime/testing/performance-renderer-pipeline-validation.ts +18 -1
- package/templates/starter/AGENTS.md +8 -7
- package/templates/starter/NOTICE.md +6 -0
- package/templates/starter/docs/toolcraft/README.md +2 -1
- package/templates/starter/docs/toolcraft/acceptance-testing.md +8 -6
- package/templates/starter/docs/toolcraft/agent-worklog.md +3 -3
- package/templates/starter/docs/toolcraft/assembly-workflow.md +4 -3
- package/templates/starter/docs/toolcraft/core/media-upload.md +2 -2
- package/templates/starter/docs/toolcraft/core/performance.md +14 -3
- package/templates/starter/docs/toolcraft/core/runtime-boundary.md +3 -1
- package/templates/starter/docs/toolcraft/core/setup-export.md +16 -12
- package/templates/starter/docs/toolcraft/core/timeline-animation.md +4 -4
- package/templates/starter/docs/toolcraft/performance.md +20 -6
- package/templates/starter/docs/toolcraft/renderer-technique.md +1 -1
- package/templates/starter/docs/toolcraft/schema-reference.md +2 -6
- package/templates/starter/docs/toolcraft/workflow.md +7 -2
- package/templates/starter/e2e/app-browser-control-coverage.spec.ts +33 -0
- package/templates/starter/e2e/app-browser-infinity-canvas-evidence.spec.ts +43 -1
- package/templates/starter/e2e/app-browser-render-scale-evidence.spec.ts +60 -6
- package/templates/starter/e2e/app-browser-render-scale-requirements.spec.ts +77 -1
- package/templates/starter/e2e/app-browser-runtime-provenance.spec.ts +8 -0
- package/templates/starter/e2e/app-browser-runtime-reporter.spec.ts +35 -0
- package/templates/starter/e2e/app-browser-runtime-requirements.spec.ts +4 -1
- package/templates/starter/e2e/app-browser-semantic-evidence.spec.ts +0 -1
- package/templates/starter/e2e/app-browser-shell.spec.ts +13 -5
- package/templates/starter/e2e/app-performance-path-adapters.ts +8 -1
- package/templates/starter/e2e/app-performance.spec.ts +16 -9
- package/templates/starter/e2e/browser-infinity-canvas-evidence.ts +9 -330
- package/templates/starter/e2e/browser-infinity-canvas-unavailable-image-evidence.ts +370 -0
- package/templates/starter/e2e/browser-media-export-evidence.spec.ts +77 -0
- package/templates/starter/e2e/browser-media-export-evidence.ts +208 -0
- package/templates/starter/e2e/browser-render-scale-evidence.ts +37 -29
- package/templates/starter/e2e/browser-runtime-evidence-reporter.ts +4 -1
- package/templates/starter/e2e/browser-runtime-evidence-requirements.ts +43 -9
- package/templates/starter/e2e/browser-standard-timeline-evidence.ts +106 -0
- package/templates/starter/e2e/decoded-pixel-observation.spec.ts +74 -0
- package/templates/starter/e2e/decoded-pixel-observation.ts +227 -0
- package/templates/starter/e2e/export-artifact-helpers.ts +206 -25
- package/templates/starter/e2e/image-artifact-inspection.spec.ts +41 -0
- package/templates/starter/e2e/image-artifact-inspection.ts +99 -0
- package/templates/starter/e2e/performance-canvas-helpers.ts +22 -21
- package/templates/starter/e2e/performance-canvas-quality-guard.spec.ts +312 -0
- package/templates/starter/e2e/performance-canvas-quality-guard.ts +196 -0
- package/templates/starter/e2e/performance-canvas-quality-observer.ts +351 -0
- package/templates/starter/e2e/performance-control-layout-helpers.ts +2 -2
- package/templates/starter/e2e/performance-path-adapter-contract.ts +4 -4
- package/templates/starter/e2e/performance-path-helpers.spec.ts +203 -70
- package/templates/starter/e2e/performance-path-helpers.ts +210 -91
- package/templates/starter/e2e/performance-pipeline-evidence-continuity.spec.ts +76 -0
- package/templates/starter/e2e/performance-pipeline-evidence-test-fixtures.ts +11 -2
- package/templates/starter/e2e/performance-pipeline-invariants.ts +47 -4
- package/templates/starter/e2e/performance-render-scale-runner.spec.ts +140 -38
- package/templates/starter/e2e/video-artifact-inspection.spec.ts +64 -0
- package/templates/starter/e2e/video-artifact-inspection.ts +281 -0
- package/templates/starter/gitignore +1 -0
- package/templates/starter/package.json +1 -0
- package/templates/starter/scripts/check-toolcraft-docs.mjs +17 -0
- package/templates/starter/scripts/toolcraft-delivery-plan-authority.test.mjs +60 -0
- package/templates/starter/scripts/toolcraft-delivery-plan-errors.test.mjs +7 -2
- package/templates/starter/scripts/toolcraft-delivery-plan.mjs +7 -3
- package/templates/starter/scripts/toolcraft-product-boundary-ast.mjs +24 -2
- package/templates/starter/scripts/toolcraft-product-boundary.mjs +12 -0
- package/templates/starter/scripts/toolcraft-product-boundary.test.mjs +46 -0
- package/templates/starter/scripts/toolcraft-product-evidence-boundary.test.mjs +85 -20
- package/templates/starter/scripts/toolcraft-product-evidence-import-policy.mjs +43 -0
- package/templates/starter/scripts/toolcraft-product-export-boundary.mjs +168 -0
- package/templates/starter/scripts/toolcraft-typescript-analysis.d.mts +73 -0
- package/templates/starter/scripts/toolcraft-unavailable-resource-evidence-facade-test-helpers.mjs +318 -0
- package/templates/starter/scripts/toolcraft-unavailable-resource-evidence-facade.test.mjs +155 -206
- package/templates/starter/scripts/toolcraft-verification-inventory.mjs +1 -0
- package/templates/starter/scripts/toolcraft-verification-receipt.test.mjs +51 -0
- package/templates/starter/scripts/toolcraft-vite-env-activation.test.mjs +128 -59
- package/templates/starter/src/app/acceptance/export-artifact-coverage.ts +113 -0
- package/templates/starter/src/app/acceptance/output-background-rules.ts +1 -1
- package/templates/starter/src/app/acceptance/output-export.ts +13 -2
- package/templates/starter/src/app/acceptance/types.ts +7 -0
- package/templates/starter/src/app/acceptance/validate-coverage.ts +2 -1
- package/templates/starter/src/app/starter-acceptance.export-artifact.test.ts +131 -0
- package/templates/starter/src/app/starter-acceptance.keyframes.test.ts +14 -4
- package/templates/starter/src/app/starter-acceptance.output-export-rules.test.ts +42 -1
- package/templates/starter/src/app/starter-acceptance.ts +2 -0
- package/templates/starter/src/app/starter-performance-test-utils.ts +103 -0
- package/templates/starter/src/app/starter-performance.gates.test.ts +231 -278
- package/templates/starter/src/app/starter-performance.lifecycle.test.ts +261 -0
- package/templates/starter/src/app/test-evidence/browser-runtime-contract.ts +2 -0
- package/templates/starter/src/routes/index.tsx +1 -0
- package/templates/runtime/export/export.ts +0 -166
|
@@ -239,6 +239,66 @@ test("creates a changed authorized iteration with exact affected proof", () => {
|
|
|
239
239
|
assert.equal(getToolcraftDeliveryDiagnosticTier(plan), 3);
|
|
240
240
|
});
|
|
241
241
|
|
|
242
|
+
test("creates an authorized iteration for a passless viewport path", () => {
|
|
243
|
+
const passlessPathId =
|
|
244
|
+
"performance-path:%5B%22interactive-continuous%22%2C%22viewport-drag%22%2C%5B%5D%2C%5B%5D%2C%5B%5D%5D";
|
|
245
|
+
const testName = `browser perf: toolcraft path ${passlessPathId}`;
|
|
246
|
+
const source = {
|
|
247
|
+
heading: "Delivery 2 - Slow viewport drag",
|
|
248
|
+
pathIds: [passlessPathId],
|
|
249
|
+
request: "The canvas is slow while panning.",
|
|
250
|
+
requestEvidence: "The canvas is slow while panning.",
|
|
251
|
+
};
|
|
252
|
+
const planningInputs = inputs({
|
|
253
|
+
requestAuthority: {
|
|
254
|
+
hash: createToolcraftPerformanceRequestAuthorityHash(source),
|
|
255
|
+
...source,
|
|
256
|
+
},
|
|
257
|
+
});
|
|
258
|
+
planningInputs.catalog = {
|
|
259
|
+
...catalog,
|
|
260
|
+
performance: [{ passIds: [], pathId: passlessPathId, testName }],
|
|
261
|
+
};
|
|
262
|
+
planningInputs.changeSet.impact.performanceCandidates = {
|
|
263
|
+
passIds: [],
|
|
264
|
+
pathIds: [passlessPathId],
|
|
265
|
+
testNames: [testName],
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
const plan = createToolcraftDeliveryPlan(planningInputs);
|
|
269
|
+
|
|
270
|
+
assert.equal(plan.kind, "performance-iteration");
|
|
271
|
+
assert.deepEqual(
|
|
272
|
+
plan.steps.find(({ kind }) => kind === "browser-performance"),
|
|
273
|
+
{
|
|
274
|
+
kind: "browser-performance",
|
|
275
|
+
passIds: [],
|
|
276
|
+
pathIds: [passlessPathId],
|
|
277
|
+
testNames: [testName],
|
|
278
|
+
},
|
|
279
|
+
);
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
test("keeps performance-adapter-only changes functional without inferred measurement", () => {
|
|
283
|
+
const planningInputs = inputs();
|
|
284
|
+
planningInputs.changeSet.impact = {
|
|
285
|
+
acceptanceIds: [],
|
|
286
|
+
browserTestNames: [],
|
|
287
|
+
buildRequired: false,
|
|
288
|
+
performanceCandidates: {
|
|
289
|
+
passIds: ["preview-composite"],
|
|
290
|
+
pathIds: [pathId],
|
|
291
|
+
testNames: [performanceTestName],
|
|
292
|
+
},
|
|
293
|
+
productTestFiles: [],
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
const plan = createToolcraftDeliveryPlan(planningInputs);
|
|
297
|
+
|
|
298
|
+
assert.equal(plan.kind, "functional");
|
|
299
|
+
assert.deepEqual(plan.steps, [{ kind: "code-health" }]);
|
|
300
|
+
});
|
|
301
|
+
|
|
242
302
|
test("rejects malformed basis and functional performance proof", () => {
|
|
243
303
|
const valid = createToolcraftDeliveryPlan(inputs());
|
|
244
304
|
for (const basis of [
|
|
@@ -203,14 +203,19 @@ test("rejects malformed catalogs and inconsistent exact impact relations", () =>
|
|
|
203
203
|
}
|
|
204
204
|
});
|
|
205
205
|
|
|
206
|
-
test("
|
|
206
|
+
test("impact cannot omit both functional and performance proof", () => {
|
|
207
207
|
const value = inputs();
|
|
208
208
|
value.changeSet.impact.acceptanceIds = [];
|
|
209
209
|
value.changeSet.impact.browserTestNames = [];
|
|
210
210
|
value.changeSet.impact.productTestFiles = [];
|
|
211
|
+
value.changeSet.impact.performanceCandidates = {
|
|
212
|
+
passIds: [],
|
|
213
|
+
pathIds: [],
|
|
214
|
+
testNames: [],
|
|
215
|
+
};
|
|
211
216
|
assert.throws(
|
|
212
217
|
() => createToolcraftDeliveryPlan(value),
|
|
213
|
-
/functional proof/iu,
|
|
218
|
+
/functional or performance proof/iu,
|
|
214
219
|
);
|
|
215
220
|
});
|
|
216
221
|
|
|
@@ -124,8 +124,9 @@ function impactError(impact, catalog, allTests) {
|
|
|
124
124
|
impact.acceptanceIds.includes(row.acceptanceId));
|
|
125
125
|
const performance = catalog.performance.filter((row) =>
|
|
126
126
|
impact.performanceCandidates.pathIds.includes(row.pathId));
|
|
127
|
-
if (!impact.browserTestNames.length && !impact.productTestFiles.length
|
|
128
|
-
|
|
127
|
+
if (!impact.browserTestNames.length && !impact.productTestFiles.length &&
|
|
128
|
+
!impact.performanceCandidates.pathIds.length)
|
|
129
|
+
return "Verification impact does not select functional or performance proof.";
|
|
129
130
|
if (acceptance.length !== impact.acceptanceIds.length ||
|
|
130
131
|
!same(acceptance.map((row) => row.testName).sort(compare), impact.browserTestNames) ||
|
|
131
132
|
performance.length !== impact.performanceCandidates.pathIds.length ||
|
|
@@ -227,7 +228,10 @@ function stepError(step) {
|
|
|
227
228
|
if (step.kind === "dependencies" && !managers.has(step.packageManager))
|
|
228
229
|
return "Dependency proof has an invalid package manager.";
|
|
229
230
|
const badTarget = ["files", "testNames", "pathIds", "passIds"].find((key) =>
|
|
230
|
-
Object.hasOwn(step, key) && !targets(step[key], {
|
|
231
|
+
Object.hasOwn(step, key) && !targets(step[key], {
|
|
232
|
+
empty: step.kind === "browser-performance" && key === "passIds",
|
|
233
|
+
paths: key === "files",
|
|
234
|
+
}));
|
|
231
235
|
if (badTarget)
|
|
232
236
|
return `Delivery proof ${badTarget} must be nonempty, sorted, and unique.`;
|
|
233
237
|
}
|
|
@@ -6,6 +6,11 @@ import {
|
|
|
6
6
|
builtInControlExportNames,
|
|
7
7
|
runtimeSurfaceComponentNames,
|
|
8
8
|
} from "./toolcraft-integrity-policy.mjs";
|
|
9
|
+
import {
|
|
10
|
+
createToolcraftProductExportInspector,
|
|
11
|
+
getToolcraftProductExportModuleKind,
|
|
12
|
+
isForbiddenToolcraftRuntimeExport,
|
|
13
|
+
} from "./toolcraft-product-export-boundary.mjs";
|
|
9
14
|
import { inspectToolcraftProductStyleNode } from "./toolcraft-product-style-boundary.mjs";
|
|
10
15
|
|
|
11
16
|
const runtimeSurfaceNames = new Set(runtimeSurfaceComponentNames);
|
|
@@ -42,6 +47,11 @@ function getSensitiveModuleKind(sourceFilePath, moduleSpecifier, rootDir) {
|
|
|
42
47
|
normalizedSpecifier,
|
|
43
48
|
rootDir,
|
|
44
49
|
);
|
|
50
|
+
const exportModuleKind = getToolcraftProductExportModuleKind(
|
|
51
|
+
normalizedSpecifier,
|
|
52
|
+
resolvedSpecifier,
|
|
53
|
+
);
|
|
54
|
+
if (exportModuleKind) return exportModuleKind;
|
|
45
55
|
|
|
46
56
|
if (
|
|
47
57
|
/^@repo\/toolcraft-runtime\/react\/model-rendering(?:\/|$)/u.test(
|
|
@@ -94,6 +104,7 @@ function getSensitiveModuleKind(sourceFilePath, moduleSpecifier, rootDir) {
|
|
|
94
104
|
}
|
|
95
105
|
|
|
96
106
|
function isForbiddenNamedExport(moduleKind, importedName) {
|
|
107
|
+
if (isForbiddenToolcraftRuntimeExport(moduleKind, importedName)) return true;
|
|
97
108
|
if (
|
|
98
109
|
moduleKind === "runtime-model-import" ||
|
|
99
110
|
moduleKind === "runtime-model-presentation"
|
|
@@ -117,7 +128,9 @@ function createViolation({
|
|
|
117
128
|
}) {
|
|
118
129
|
const subject = importedName ? ` ${importedName}` : "";
|
|
119
130
|
const message =
|
|
120
|
-
kind === "runtime-
|
|
131
|
+
kind === "runtime-export-ownership"
|
|
132
|
+
? `Product source must not own artifact encoding, recording, or download mechanics${subject} from ${moduleSpecifier}. Declare exportRenderer and let runtime export actions encode and download the artifact.`
|
|
133
|
+
: kind === "runtime-surface"
|
|
121
134
|
? `Product source must not import or re-export host-owned runtime surface${subject} from ${moduleSpecifier}. Use ToolcraftAppComposition, schema, canvasContent, controlRenderers, onPanelAction, and runtime commands.`
|
|
122
135
|
: kind === "runtime-model-presentation-ownership"
|
|
123
136
|
? `Product source must not import raw model render hosts or standard model canvas internals${subject} from ${moduleSpecifier}. Declare modelPresentation and use useToolcraftModelPresentationConsumer for visible custom model output.`
|
|
@@ -141,6 +154,11 @@ export function inspectToolcraftProductSource({
|
|
|
141
154
|
sourceFile,
|
|
142
155
|
}) {
|
|
143
156
|
const violations = [];
|
|
157
|
+
const inspectExportMechanics = createToolcraftProductExportInspector({
|
|
158
|
+
getNodeLocation,
|
|
159
|
+
repoPath,
|
|
160
|
+
sourceFile,
|
|
161
|
+
});
|
|
144
162
|
|
|
145
163
|
function report(node, moduleSpecifier, moduleKind, importedName) {
|
|
146
164
|
if (importedName && !isForbiddenNamedExport(moduleKind, importedName)) {
|
|
@@ -151,7 +169,10 @@ export function inspectToolcraftProductSource({
|
|
|
151
169
|
getNodeLocation,
|
|
152
170
|
importedName,
|
|
153
171
|
kind:
|
|
154
|
-
moduleKind === "runtime-
|
|
172
|
+
moduleKind === "runtime-export-api" ||
|
|
173
|
+
moduleKind === "runtime-export-mechanics"
|
|
174
|
+
? "runtime-export-ownership"
|
|
175
|
+
: moduleKind === "runtime-model-presentation"
|
|
155
176
|
? "runtime-model-presentation-ownership"
|
|
156
177
|
: moduleKind === "runtime-react"
|
|
157
178
|
? runtimeModelPresentationInternalNames.has(importedName)
|
|
@@ -180,6 +201,7 @@ export function inspectToolcraftProductSource({
|
|
|
180
201
|
resolveStaticString,
|
|
181
202
|
sourceFile,
|
|
182
203
|
}),
|
|
204
|
+
...inspectExportMechanics(node),
|
|
183
205
|
);
|
|
184
206
|
|
|
185
207
|
if (
|
|
@@ -4,6 +4,7 @@ import fs from "node:fs";
|
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
|
|
7
|
+
import { createToolcraftPrivateEvidenceImportViolation } from "./toolcraft-product-evidence-import-policy.mjs";
|
|
7
8
|
import { isToolcraftTypeScriptCompilerAvailable } from "./toolcraft-typescript-source-evidence.mjs";
|
|
8
9
|
|
|
9
10
|
function compareCodeUnits(left, right) {
|
|
@@ -94,6 +95,15 @@ export async function evaluateToolcraftProductBoundary({
|
|
|
94
95
|
importerEvidence.push(evidence);
|
|
95
96
|
importsByImporter.set(evidence.importerRepoPath, importerEvidence);
|
|
96
97
|
}
|
|
98
|
+
const appendPrivateEvidenceImportViolations = (entry) => {
|
|
99
|
+
for (const moduleImport of importsByImporter.get(entry.repoPath) ?? []) {
|
|
100
|
+
const violation = createToolcraftPrivateEvidenceImportViolation({
|
|
101
|
+
importerRepoPath: entry.repoPath,
|
|
102
|
+
moduleImport,
|
|
103
|
+
});
|
|
104
|
+
if (violation) violations.push(violation);
|
|
105
|
+
}
|
|
106
|
+
};
|
|
97
107
|
|
|
98
108
|
for (const entry of productEntries) {
|
|
99
109
|
const sourceRecord = localDependencyGraph.sourceRecords.get(entry.repoPath);
|
|
@@ -113,6 +123,7 @@ export async function evaluateToolcraftProductBoundary({
|
|
|
113
123
|
...boundaryEvidence.reservedEvidenceViolations,
|
|
114
124
|
...boundaryEvidence.playwrightAuthorityViolations,
|
|
115
125
|
);
|
|
126
|
+
appendPrivateEvidenceImportViolations(entry);
|
|
116
127
|
for (const evidence of importsByImporter.get(entry.repoPath) ?? []) {
|
|
117
128
|
if (evidence.resolution === "outside-inventory") {
|
|
118
129
|
violations.push({
|
|
@@ -165,6 +176,7 @@ export async function evaluateToolcraftProductBoundary({
|
|
|
165
176
|
...boundaryEvidence.playwrightAuthorityViolations,
|
|
166
177
|
...boundaryEvidence.moduleLoadingViolations,
|
|
167
178
|
);
|
|
179
|
+
appendPrivateEvidenceImportViolations(entry);
|
|
168
180
|
}
|
|
169
181
|
|
|
170
182
|
return {
|
|
@@ -143,6 +143,52 @@ test("keeps model import, topology, and repair infrastructure runtime-owned", as
|
|
|
143
143
|
);
|
|
144
144
|
});
|
|
145
145
|
|
|
146
|
+
test("keeps artifact encoding and download mechanics runtime-owned", async (context) => {
|
|
147
|
+
const rootDir = await createFixture(context, {
|
|
148
|
+
"src/features/export-mechanics.ts": `
|
|
149
|
+
import { createToolcraftPngExportCanvas } from "@/toolcraft/runtime";
|
|
150
|
+
import { Output } from "mediabunny";
|
|
151
|
+
export function exportArtifact(canvas: HTMLCanvasElement) {
|
|
152
|
+
const recorder = new MediaRecorder(canvas.captureStream());
|
|
153
|
+
const encoder = new VideoEncoder({ error() {}, output() {} });
|
|
154
|
+
canvas.toBlob(() => undefined);
|
|
155
|
+
canvas.toDataURL();
|
|
156
|
+
URL.createObjectURL(new Blob());
|
|
157
|
+
void createToolcraftPngExportCanvas;
|
|
158
|
+
void Output;
|
|
159
|
+
void recorder;
|
|
160
|
+
void encoder;
|
|
161
|
+
}
|
|
162
|
+
`,
|
|
163
|
+
"src/features/safe-renderer.ts": `
|
|
164
|
+
export const renderFrame = ({ context }) => context.fillRect(0, 0, 1, 1);
|
|
165
|
+
`,
|
|
166
|
+
"src/features/shadowed-globals.ts": `
|
|
167
|
+
export function localNames(MediaRecorder, VideoEncoder, URL) {
|
|
168
|
+
void new MediaRecorder();
|
|
169
|
+
void new VideoEncoder();
|
|
170
|
+
URL.createObjectURL();
|
|
171
|
+
}
|
|
172
|
+
`,
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
const result = await evaluateToolcraftProductBoundary({ rootDir });
|
|
176
|
+
|
|
177
|
+
assert.equal(result.violations.length, 8);
|
|
178
|
+
assert.equal(
|
|
179
|
+
result.violations.every(
|
|
180
|
+
(violation) => violation.kind === "runtime-export-ownership",
|
|
181
|
+
),
|
|
182
|
+
true,
|
|
183
|
+
);
|
|
184
|
+
assert.equal(
|
|
185
|
+
result.violations.some((violation) =>
|
|
186
|
+
violation.repoPath.endsWith("shadowed-globals.ts"),
|
|
187
|
+
),
|
|
188
|
+
false,
|
|
189
|
+
);
|
|
190
|
+
});
|
|
191
|
+
|
|
146
192
|
test("ignores tests but checks a product bridge imported by production", async (context) => {
|
|
147
193
|
const rootDir = await createFixture(context, {
|
|
148
194
|
"src/features/bridge.ts": `
|
|
@@ -12,6 +12,44 @@ const starterRoot = path.resolve(
|
|
|
12
12
|
path.dirname(fileURLToPath(import.meta.url)),
|
|
13
13
|
"..",
|
|
14
14
|
);
|
|
15
|
+
const unavailableImageEvidenceFacadePath =
|
|
16
|
+
"e2e/browser-infinity-canvas-evidence.ts";
|
|
17
|
+
const unavailableImageEvidencePrivatePath =
|
|
18
|
+
"e2e/browser-infinity-canvas-unavailable-image-evidence.ts";
|
|
19
|
+
|
|
20
|
+
async function evaluateUnavailableImageEvidenceImport(context, specifier) {
|
|
21
|
+
const rootDir = await createFixture(context, {
|
|
22
|
+
"e2e/app-canvas.spec.ts": `
|
|
23
|
+
import { createToolcraftUnavailableImageResourceFixture } from "${specifier}";
|
|
24
|
+
void createToolcraftUnavailableImageResourceFixture;
|
|
25
|
+
`,
|
|
26
|
+
[unavailableImageEvidenceFacadePath]: `
|
|
27
|
+
export {
|
|
28
|
+
createToolcraftUnavailableImageResourceFixture,
|
|
29
|
+
} from "./browser-infinity-canvas-unavailable-image-evidence";
|
|
30
|
+
`,
|
|
31
|
+
[unavailableImageEvidencePrivatePath]: `
|
|
32
|
+
export function createToolcraftUnavailableImageResourceFixture() {}
|
|
33
|
+
`,
|
|
34
|
+
"tsconfig.json": JSON.stringify({
|
|
35
|
+
compilerOptions: {
|
|
36
|
+
baseUrl: ".",
|
|
37
|
+
paths: {
|
|
38
|
+
"@private-proof": [`./${unavailableImageEvidencePrivatePath}`],
|
|
39
|
+
"@public-proof": [`./${unavailableImageEvidenceFacadePath}`],
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
}),
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
return evaluateToolcraftProductBoundary({
|
|
46
|
+
protectedFilePaths: [
|
|
47
|
+
unavailableImageEvidenceFacadePath,
|
|
48
|
+
unavailableImageEvidencePrivatePath,
|
|
49
|
+
],
|
|
50
|
+
rootDir,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
15
53
|
|
|
16
54
|
test("protects every starter helper that writes reserved runtime evidence", async () => {
|
|
17
55
|
const e2eRoot = path.join(starterRoot, "e2e");
|
|
@@ -201,27 +239,54 @@ test("allows product layer specs to use the public proof facade without reserved
|
|
|
201
239
|
assert.deepEqual(result.violations, []);
|
|
202
240
|
});
|
|
203
241
|
|
|
204
|
-
test("
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
242
|
+
test("rejects relative and configured-alias imports of private unavailable-image evidence", async (context) => {
|
|
243
|
+
const results = await Promise.all(
|
|
244
|
+
[
|
|
245
|
+
"./browser-infinity-canvas-unavailable-image-evidence",
|
|
246
|
+
"@private-proof",
|
|
247
|
+
].map((specifier) =>
|
|
248
|
+
evaluateUnavailableImageEvidenceImport(context, specifier),
|
|
249
|
+
),
|
|
250
|
+
);
|
|
251
|
+
assert.deepEqual(
|
|
252
|
+
results.map((result) =>
|
|
253
|
+
result.violations.map((violation) => violation.kind),
|
|
254
|
+
),
|
|
255
|
+
[
|
|
256
|
+
["reserved-runtime-evidence"],
|
|
257
|
+
["reserved-runtime-evidence"],
|
|
258
|
+
],
|
|
259
|
+
);
|
|
260
|
+
for (const result of results) {
|
|
261
|
+
assert.match(result.violations[0].message, /browser-infinity-canvas-evidence/u);
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
test("allows relative and configured-alias imports of the public unavailable-image facade", async (context) => {
|
|
266
|
+
for (const specifier of [
|
|
267
|
+
"./browser-infinity-canvas-evidence",
|
|
268
|
+
"@public-proof",
|
|
269
|
+
]) {
|
|
270
|
+
const result = await evaluateUnavailableImageEvidenceImport(
|
|
271
|
+
context,
|
|
272
|
+
specifier,
|
|
273
|
+
);
|
|
274
|
+
assert.deepEqual(result.violations, []);
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
test("normalizes private unavailable-image evidence import paths before enforcing policy", async (context) => {
|
|
279
|
+
const result = await evaluateUnavailableImageEvidenceImport(
|
|
280
|
+
context,
|
|
281
|
+
"./nested/../browser-infinity-canvas-unavailable-image-evidence",
|
|
282
|
+
);
|
|
283
|
+
assert.deepEqual(
|
|
284
|
+
result.violations.map((violation) => violation.kind),
|
|
285
|
+
["reserved-runtime-evidence"],
|
|
286
|
+
);
|
|
287
|
+
});
|
|
224
288
|
|
|
289
|
+
test("rejects product access to the reserved unavailable-resource bridge", async (context) => {
|
|
225
290
|
const rejectedRoot = await createFixture(context, {
|
|
226
291
|
"e2e/app-canvas.spec.ts": `
|
|
227
292
|
const fixtureEvent =
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const PRIVATE_EVIDENCE_MESSAGE =
|
|
2
|
+
"Product-owned source must use the protected public evidence facade instead of importing its private implementation module.";
|
|
3
|
+
|
|
4
|
+
export const toolcraftProductEvidenceModulePolicies = Object.freeze([
|
|
5
|
+
Object.freeze({
|
|
6
|
+
capability: "unavailable-image-resource-evidence",
|
|
7
|
+
privateModuleRepoPath:
|
|
8
|
+
"e2e/browser-infinity-canvas-unavailable-image-evidence.ts",
|
|
9
|
+
publicFacadeRepoPath: "e2e/browser-infinity-canvas-evidence.ts",
|
|
10
|
+
}),
|
|
11
|
+
]);
|
|
12
|
+
|
|
13
|
+
const privateEvidencePolicyByRepoPath = new Map(
|
|
14
|
+
toolcraftProductEvidenceModulePolicies.map((policy) => [
|
|
15
|
+
policy.privateModuleRepoPath,
|
|
16
|
+
policy,
|
|
17
|
+
]),
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
function normalizeRepoPath(repoPath) {
|
|
21
|
+
return String(repoPath).replaceAll("\\", "/").replace(/^\.\//u, "");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function createToolcraftPrivateEvidenceImportViolation({
|
|
25
|
+
importerRepoPath,
|
|
26
|
+
moduleImport,
|
|
27
|
+
}) {
|
|
28
|
+
if (moduleImport.resolution !== "resolved") return null;
|
|
29
|
+
const policy = privateEvidencePolicyByRepoPath.get(
|
|
30
|
+
normalizeRepoPath(moduleImport.resolvedRepoPath),
|
|
31
|
+
);
|
|
32
|
+
if (!policy) return null;
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
column: moduleImport.column,
|
|
36
|
+
kind: "reserved-runtime-evidence",
|
|
37
|
+
line: moduleImport.line,
|
|
38
|
+
message:
|
|
39
|
+
`${PRIVATE_EVIDENCE_MESSAGE} Import ${policy.publicFacadeRepoPath} ` +
|
|
40
|
+
`for ${policy.capability}.`,
|
|
41
|
+
repoPath: importerRepoPath,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
|
|
3
|
+
const forbiddenRuntimeExportNames = new Set([
|
|
4
|
+
"createToolcraftPngExportCanvas",
|
|
5
|
+
]);
|
|
6
|
+
const forbiddenGlobalExportConstructors = new Set([
|
|
7
|
+
"MediaRecorder",
|
|
8
|
+
"VideoEncoder",
|
|
9
|
+
]);
|
|
10
|
+
const forbiddenCanvasExportMethods = new Set([
|
|
11
|
+
"captureStream",
|
|
12
|
+
"toBlob",
|
|
13
|
+
"toDataURL",
|
|
14
|
+
]);
|
|
15
|
+
|
|
16
|
+
export function getToolcraftProductExportModuleKind(
|
|
17
|
+
normalizedSpecifier,
|
|
18
|
+
resolvedSpecifier,
|
|
19
|
+
) {
|
|
20
|
+
if (/^mediabunny(?:\/|$)/u.test(normalizedSpecifier)) {
|
|
21
|
+
return "runtime-export-mechanics";
|
|
22
|
+
}
|
|
23
|
+
if (
|
|
24
|
+
normalizedSpecifier === "@repo/toolcraft-runtime" ||
|
|
25
|
+
/^[#@]\/toolcraft\/runtime\/?$/u.test(normalizedSpecifier) ||
|
|
26
|
+
/\/src\/toolcraft\/runtime$/u.test(resolvedSpecifier ?? "")
|
|
27
|
+
) {
|
|
28
|
+
return "runtime-export-api";
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function isForbiddenToolcraftRuntimeExport(
|
|
34
|
+
moduleKind,
|
|
35
|
+
importedName,
|
|
36
|
+
) {
|
|
37
|
+
return (
|
|
38
|
+
moduleKind === "runtime-export-mechanics" ||
|
|
39
|
+
(moduleKind === "runtime-export-api" &&
|
|
40
|
+
forbiddenRuntimeExportNames.has(importedName))
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function getDeclarationScope(node, sourceFile) {
|
|
45
|
+
let current = node.parent;
|
|
46
|
+
while (current) {
|
|
47
|
+
if (
|
|
48
|
+
ts.isSourceFile(current) ||
|
|
49
|
+
ts.isFunctionLike(current) ||
|
|
50
|
+
ts.isBlock(current) ||
|
|
51
|
+
ts.isCatchClause(current)
|
|
52
|
+
) {
|
|
53
|
+
return current;
|
|
54
|
+
}
|
|
55
|
+
current = current.parent;
|
|
56
|
+
}
|
|
57
|
+
return sourceFile;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function collectLexicalDeclarations(sourceFile) {
|
|
61
|
+
const declarations = [];
|
|
62
|
+
|
|
63
|
+
function collectBindingNames(name, scope) {
|
|
64
|
+
if (ts.isIdentifier(name)) {
|
|
65
|
+
declarations.push({ name: name.text, scope });
|
|
66
|
+
} else if (
|
|
67
|
+
ts.isObjectBindingPattern(name) ||
|
|
68
|
+
ts.isArrayBindingPattern(name)
|
|
69
|
+
) {
|
|
70
|
+
for (const element of name.elements) {
|
|
71
|
+
if (ts.isBindingElement(element)) collectBindingNames(element.name, scope);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function visit(node) {
|
|
77
|
+
if (ts.isImportClause(node) && node.name) {
|
|
78
|
+
collectBindingNames(node.name, sourceFile);
|
|
79
|
+
} else if (ts.isImportSpecifier(node) || ts.isNamespaceImport(node)) {
|
|
80
|
+
collectBindingNames(node.name, sourceFile);
|
|
81
|
+
} else if (ts.isVariableDeclaration(node)) {
|
|
82
|
+
collectBindingNames(node.name, getDeclarationScope(node, sourceFile));
|
|
83
|
+
} else if (ts.isParameter(node)) {
|
|
84
|
+
collectBindingNames(node.name, node.parent);
|
|
85
|
+
} else if (
|
|
86
|
+
(ts.isFunctionDeclaration(node) || ts.isClassDeclaration(node)) &&
|
|
87
|
+
node.name
|
|
88
|
+
) {
|
|
89
|
+
collectBindingNames(node.name, getDeclarationScope(node, sourceFile));
|
|
90
|
+
}
|
|
91
|
+
ts.forEachChild(node, visit);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
visit(sourceFile);
|
|
95
|
+
return declarations;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function createToolcraftProductExportInspector({
|
|
99
|
+
getNodeLocation,
|
|
100
|
+
repoPath,
|
|
101
|
+
sourceFile,
|
|
102
|
+
}) {
|
|
103
|
+
const lexicalDeclarations = collectLexicalDeclarations(sourceFile);
|
|
104
|
+
|
|
105
|
+
function isLexicallyDeclared(identifier) {
|
|
106
|
+
const ancestorScopes = new Set();
|
|
107
|
+
let current = identifier.parent;
|
|
108
|
+
while (current) {
|
|
109
|
+
if (
|
|
110
|
+
ts.isSourceFile(current) ||
|
|
111
|
+
ts.isFunctionLike(current) ||
|
|
112
|
+
ts.isBlock(current) ||
|
|
113
|
+
ts.isCatchClause(current)
|
|
114
|
+
) {
|
|
115
|
+
ancestorScopes.add(current);
|
|
116
|
+
}
|
|
117
|
+
current = current.parent;
|
|
118
|
+
}
|
|
119
|
+
return lexicalDeclarations.some(
|
|
120
|
+
(declaration) =>
|
|
121
|
+
declaration.name === identifier.text &&
|
|
122
|
+
ancestorScopes.has(declaration.scope),
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function violation(node, subject) {
|
|
127
|
+
return {
|
|
128
|
+
...getNodeLocation(sourceFile, node),
|
|
129
|
+
kind: "runtime-export-ownership",
|
|
130
|
+
message: `Product source must not own ${subject}. Declare exportRenderer and let runtime export actions encode and download the artifact.`,
|
|
131
|
+
repoPath,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return (node) => {
|
|
136
|
+
if (
|
|
137
|
+
ts.isNewExpression(node) &&
|
|
138
|
+
ts.isIdentifier(node.expression) &&
|
|
139
|
+
forbiddenGlobalExportConstructors.has(node.expression.text) &&
|
|
140
|
+
!isLexicallyDeclared(node.expression)
|
|
141
|
+
) {
|
|
142
|
+
return [
|
|
143
|
+
violation(
|
|
144
|
+
node,
|
|
145
|
+
`${node.expression.text} encoder or recorder construction`,
|
|
146
|
+
),
|
|
147
|
+
];
|
|
148
|
+
}
|
|
149
|
+
if (
|
|
150
|
+
ts.isCallExpression(node) &&
|
|
151
|
+
ts.isPropertyAccessExpression(node.expression)
|
|
152
|
+
) {
|
|
153
|
+
const propertyName = node.expression.name.text;
|
|
154
|
+
if (forbiddenCanvasExportMethods.has(propertyName)) {
|
|
155
|
+
return [violation(node, `canvas.${propertyName}() export mechanics`)];
|
|
156
|
+
}
|
|
157
|
+
if (
|
|
158
|
+
propertyName === "createObjectURL" &&
|
|
159
|
+
ts.isIdentifier(node.expression.expression) &&
|
|
160
|
+
node.expression.expression.text === "URL" &&
|
|
161
|
+
!isLexicallyDeclared(node.expression.expression)
|
|
162
|
+
) {
|
|
163
|
+
return [violation(node, "URL.createObjectURL() artifact delivery")];
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return [];
|
|
167
|
+
};
|
|
168
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type ts from "typescript";
|
|
2
|
+
|
|
3
|
+
export type ToolcraftTypeScriptImportedBinding = Readonly<{
|
|
4
|
+
importedName: string;
|
|
5
|
+
localName: string;
|
|
6
|
+
specifier: string;
|
|
7
|
+
}>;
|
|
8
|
+
|
|
9
|
+
export type ToolcraftTypeScriptImportedCallTarget = Readonly<{
|
|
10
|
+
callerCallableId: string | null;
|
|
11
|
+
callerExportNames: readonly string[];
|
|
12
|
+
importedName: string;
|
|
13
|
+
localName: string;
|
|
14
|
+
memberPath: string;
|
|
15
|
+
operation: string;
|
|
16
|
+
specifier: string;
|
|
17
|
+
}>;
|
|
18
|
+
|
|
19
|
+
export type ToolcraftTypeScriptModuleBindings = Readonly<{
|
|
20
|
+
callables: unknown;
|
|
21
|
+
exportedCallableBindings: readonly Readonly<{
|
|
22
|
+
callableId: string;
|
|
23
|
+
exportedName: string;
|
|
24
|
+
}>[];
|
|
25
|
+
exportedRuntimeBindings: readonly string[];
|
|
26
|
+
importedBindingSymbols: readonly Readonly<{
|
|
27
|
+
binding: ToolcraftTypeScriptImportedBinding;
|
|
28
|
+
symbol: ts.Symbol;
|
|
29
|
+
}>[];
|
|
30
|
+
importedRuntimeBindings: readonly ToolcraftTypeScriptImportedBinding[];
|
|
31
|
+
}>;
|
|
32
|
+
|
|
33
|
+
export function createToolcraftTypeScriptChecker(
|
|
34
|
+
sourceFile: ts.SourceFile,
|
|
35
|
+
typescript: typeof ts,
|
|
36
|
+
): ts.TypeChecker;
|
|
37
|
+
|
|
38
|
+
export function collectToolcraftTypeScriptModuleBindings(
|
|
39
|
+
sourceFile: ts.SourceFile,
|
|
40
|
+
typescript: typeof ts,
|
|
41
|
+
checker?: ts.TypeChecker,
|
|
42
|
+
callables?: unknown,
|
|
43
|
+
): ToolcraftTypeScriptModuleBindings;
|
|
44
|
+
|
|
45
|
+
export function collectToolcraftTypeScriptCallTargets(input: Readonly<{
|
|
46
|
+
bindings: ToolcraftTypeScriptModuleBindings;
|
|
47
|
+
checker: ts.TypeChecker;
|
|
48
|
+
sourceFile: ts.SourceFile;
|
|
49
|
+
ts: typeof ts;
|
|
50
|
+
}>): Readonly<{
|
|
51
|
+
importedCallTargets: readonly ToolcraftTypeScriptImportedCallTarget[];
|
|
52
|
+
localCallTargets: readonly Readonly<{
|
|
53
|
+
calleeCallableId: string;
|
|
54
|
+
callerCallableId: string;
|
|
55
|
+
}>[];
|
|
56
|
+
}>;
|
|
57
|
+
|
|
58
|
+
export function getToolcraftTypeScriptImportedCallTarget(input: Readonly<{
|
|
59
|
+
bindings: ToolcraftTypeScriptModuleBindings;
|
|
60
|
+
checker: ts.TypeChecker;
|
|
61
|
+
expression: ts.Expression;
|
|
62
|
+
ts: typeof ts;
|
|
63
|
+
}>):
|
|
64
|
+
| Omit<
|
|
65
|
+
ToolcraftTypeScriptImportedCallTarget,
|
|
66
|
+
"callerCallableId" | "callerExportNames"
|
|
67
|
+
>
|
|
68
|
+
| undefined;
|
|
69
|
+
|
|
70
|
+
export function unwrapToolcraftTypeScriptExpression(
|
|
71
|
+
node: ts.Expression,
|
|
72
|
+
typescript: typeof ts,
|
|
73
|
+
): ts.Expression;
|