@tinkerlandai/indiana-iam 0.2.0 → 0.4.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 +127 -5
- package/assets/document-controller.js +18 -1
- package/assets/document-runtime.js +189 -1
- package/assets/viewer.js +74 -7
- package/package.json +6 -13
- package/src/analyze.mjs +897 -123
- package/src/anchors.mjs +5 -0
- package/src/build-options.d.ts +6 -1
- package/src/build-runtime.mjs +4 -1
- package/src/build-styles.mjs +49 -6
- package/src/build.mjs +13 -7
- package/src/cli.mjs +10 -4
- package/src/component-registry.mjs +229 -0
- package/src/dependencies.mjs +2 -2
- package/src/dom-payload-browser.mjs +28 -0
- package/src/dom-payload-json.mjs +12 -0
- package/src/dom-payload.mjs +50 -0
- package/src/framework-routes.mjs +44 -89
- package/src/generate.mjs +20 -7
- package/src/graph-sources.mjs +54 -0
- package/src/index.d.ts +13 -1
- package/src/index.mjs +1 -1
- package/src/integrity.mjs +4 -2
- package/src/library-entry.mjs +5 -0
- package/src/lucide-source.mjs +18 -0
- package/src/next-loader.cjs +7 -1
- package/src/next.cjs +5 -0
- package/src/next.mjs +4 -3
- package/src/node-hashes.mjs +13 -9
- package/src/render-index.mjs +6 -4
- package/src/route-lazy.mjs +80 -0
- package/src/route-tree.mjs +15 -3
- package/src/routing.mjs +1 -1
- package/src/schema-definition.mjs +8 -1
- package/src/source-attributes.mjs +24 -0
- package/src/source-charts.mjs +38 -0
- package/src/source-collections.mjs +241 -0
- package/src/source-entry.mjs +50 -0
- package/src/source-environment.mjs +26 -0
- package/src/source-media.mjs +21 -0
- package/src/source-query-evidence.mjs +64 -0
- package/src/source-redirects.mjs +388 -0
- package/src/source-resolution.mjs +268 -0
- package/src/static-primitives.mjs +48 -0
- package/src/static-query.mjs +39 -11
- package/src/tab-scenes.mjs +214 -0
- package/src/tanstack-routes.mjs +143 -0
- package/src/transform.mjs +2 -2
- package/src/ui-preview.mjs +225 -0
- package/src/ui-state-machine.mjs +76 -0
- package/src/ui-structure.mjs +645 -0
- package/src/upload.mjs +28 -6
- package/src/validate.mjs +19 -4
- package/src/vite.d.ts +4 -1
- package/src/vite.mjs +25 -10
package/src/validate.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { documentDom, assertDomBudget } from "./dom-payload.mjs";
|
|
1
2
|
import { loadTrustedRuntimes } from "./runtime-asset.mjs";
|
|
2
3
|
export { parseManifest } from "./json.mjs";
|
|
3
4
|
import { dependency } from "./dependencies.mjs";
|
|
@@ -31,6 +32,14 @@ export async function validate(manifest) {
|
|
|
31
32
|
const verifiedSelectors = new Map();
|
|
32
33
|
canonical(manifest);
|
|
33
34
|
assertManifestShape(manifest);
|
|
35
|
+
assertDomBudget(manifest.documents);
|
|
36
|
+
if (manifest.documents.some(doc => doc.domPayload)) assertManifestShape({
|
|
37
|
+
...manifest,
|
|
38
|
+
documents: manifest.documents.map(doc => {
|
|
39
|
+
const { domPayload, ...body } = doc;
|
|
40
|
+
return { ...body, ...documentDom(doc) };
|
|
41
|
+
}),
|
|
42
|
+
});
|
|
34
43
|
const map = (values, key) => {
|
|
35
44
|
const result = new Map(values.map((v) => [v[key], v]));
|
|
36
45
|
if (result.size !== values.length) throw new Error("Duplicate " + key);
|
|
@@ -57,7 +66,7 @@ export async function validate(manifest) {
|
|
|
57
66
|
if (!components.has(element.componentKey))
|
|
58
67
|
throw new Error("Missing element component");
|
|
59
68
|
}
|
|
60
|
-
if (["react-router", "react-spa"].includes(manifest.routing.framework)) {
|
|
69
|
+
if (["react-router", "react-spa", "tanstack-router"].includes(manifest.routing.framework)) {
|
|
61
70
|
if (manifest.routing.basePath || manifest.routing.trailingSlash || manifest.routing.routeSources?.length !== pages.size)
|
|
62
71
|
throw Error("React route provenance is incomplete");
|
|
63
72
|
for (const row of manifest.routing.routeSources) {
|
|
@@ -121,10 +130,11 @@ export async function validate(manifest) {
|
|
|
121
130
|
throw new Error("Document hash mismatch");
|
|
122
131
|
const fullNodes=documentNodes(doc);
|
|
123
132
|
if (doc.sourceMappingsHash !== sourceMappingsHash(fullNodes, elements)) throw new Error('Source mapping hash mismatch');
|
|
124
|
-
|
|
133
|
+
const decoded = documentDom(doc);
|
|
134
|
+
expandedDocuments.push({...doc,html:decoded.html,nodes:fullNodes});
|
|
125
135
|
const nodes = map(fullNodes, "nodeId");
|
|
126
136
|
const dom = new JSDOM(
|
|
127
|
-
"<!doctype html><html><body>" +
|
|
137
|
+
"<!doctype html><html><body>" + decoded.html + "</body></html>",
|
|
128
138
|
);
|
|
129
139
|
try {
|
|
130
140
|
const document = dom.window.document;
|
|
@@ -161,6 +171,11 @@ export async function validate(manifest) {
|
|
|
161
171
|
)
|
|
162
172
|
throw new Error("DOM tag/locator mismatch");
|
|
163
173
|
for (const attr of node.attributes) {
|
|
174
|
+
if(node.tagName.toLowerCase()==='use'&&['href','xlink:href'].includes(attr.name)){
|
|
175
|
+
if(attr.name!=='href'||!/^#iam-glyph-[a-f0-9]{24}$/.test(attr.value))throw Error('Unsafe SVG glyph reference');
|
|
176
|
+
const glyphs=[...document.querySelectorAll('[id]')].filter(el=>el.id===attr.value.slice(1));
|
|
177
|
+
if(glyphs.length!==1||glyphs[0].tagName.toLowerCase()!=='g'||glyphs[0].parentElement?.tagName.toLowerCase()!=='defs'||[...glyphs[0].querySelectorAll('*')].some(el=>!['path','circle','rect','line','polyline','polygon','ellipse','g'].includes(el.tagName.toLowerCase())))throw Error('Invalid SVG glyph definition');
|
|
178
|
+
}
|
|
164
179
|
if (
|
|
165
180
|
/^on/i.test(attr.name) ||
|
|
166
181
|
["srcdoc", "formaction", "action"].includes(attr.name)
|
|
@@ -277,7 +292,7 @@ export async function validate(manifest) {
|
|
|
277
292
|
components: components.size,
|
|
278
293
|
elements: elements.size,
|
|
279
294
|
documents: docs.size,
|
|
280
|
-
concreteNodes:
|
|
295
|
+
concreteNodes: expandedDocuments.reduce((n, d) => n + d.nodes.length, 0),
|
|
281
296
|
runtimeObserved: manifest.coverage.runtimeObserved,
|
|
282
297
|
routeTree,
|
|
283
298
|
};
|
package/src/vite.d.ts
CHANGED
|
@@ -6,7 +6,10 @@ export declare function indianaIam(options?: IndianaIamBuildOptions): {
|
|
|
6
6
|
name: "indiana-iam";
|
|
7
7
|
apply: "build";
|
|
8
8
|
enforce: "pre";
|
|
9
|
-
transform
|
|
9
|
+
transform: {
|
|
10
|
+
order: "pre";
|
|
11
|
+
handler(code: string, id: string): IamSourceTransform | null;
|
|
12
|
+
};
|
|
10
13
|
config(config: {
|
|
11
14
|
root?: string;
|
|
12
15
|
build?: { ssr?: unknown };
|
package/src/vite.mjs
CHANGED
|
@@ -13,12 +13,13 @@ import { releasePath } from "./release-metadata.mjs";
|
|
|
13
13
|
* IAM as the current version. Server builds are skipped.
|
|
14
14
|
*/
|
|
15
15
|
export function indianaIam(options = {}) {
|
|
16
|
-
const { enabled = true, name, automaticAnchors = true, strict = false, rootFont, omitSvgResources, logger = console, apiKey, baseUrl, upload, fetch } = options;
|
|
16
|
+
const { enabled = true, name, entry, automaticAnchors = true, strict = false, rootFont, omitSvgResources, logger = console, apiKey, baseUrl, upload, client, fetch } = options;
|
|
17
17
|
let releaseId = null,
|
|
18
18
|
root,
|
|
19
19
|
outDir,
|
|
20
20
|
base,
|
|
21
|
-
server = false
|
|
21
|
+
server = false,
|
|
22
|
+
buildFailed = false;
|
|
22
23
|
return {
|
|
23
24
|
name: "indiana-iam",
|
|
24
25
|
apply: "build",
|
|
@@ -26,7 +27,7 @@ export function indianaIam(options = {}) {
|
|
|
26
27
|
async config(config) {
|
|
27
28
|
if (!enabled || config.build?.ssr) return;
|
|
28
29
|
root = await fs.realpath(path.resolve(config.root ?? process.cwd()));
|
|
29
|
-
const prepared = await prepareBuildRelease({ root, name, automaticAnchors, strict, logger });
|
|
30
|
+
const prepared = await prepareBuildRelease({ root, name, entry, automaticAnchors, strict, logger });
|
|
30
31
|
if (!prepared) return;
|
|
31
32
|
releaseId = prepared.releaseId;
|
|
32
33
|
return { define: { "import.meta.env.INDIANA_IAM_RELEASE_URL": JSON.stringify(releasePath(releaseId)) } };
|
|
@@ -37,26 +38,40 @@ export function indianaIam(options = {}) {
|
|
|
37
38
|
base = /^\/(?:[^/]+\/)*$/.test(config.base) ? config.base : "/";
|
|
38
39
|
server = Boolean(config.build.ssr);
|
|
39
40
|
},
|
|
40
|
-
transform
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
transform: {
|
|
42
|
+
// TanStack also runs a pre-transform. Anchor the original JSX before its
|
|
43
|
+
// reference/virtual module split, using the same original source path.
|
|
44
|
+
order: "pre",
|
|
45
|
+
handler(code, id) {
|
|
46
|
+
if (!enabled || server || !automaticAnchors || !releaseId || !root || id.startsWith("\0")) return null;
|
|
47
|
+
const [sourceId, query] = id.split("?");
|
|
48
|
+
if (query !== undefined) {
|
|
49
|
+
const parameters = [...new URLSearchParams(query)];
|
|
50
|
+
if (id.split("?").length !== 2 || parameters.length !== 1 || !["tsr-split", "tsr-shared"].includes(parameters[0][0]) || !parameters[0][1] || parameters[0][1].length > 256) return null;
|
|
51
|
+
}
|
|
52
|
+
const file = path.relative(root, sourceId).split(path.sep).join("/");
|
|
53
|
+
if (file.startsWith("../") || path.isAbsolute(file)) return null;
|
|
54
|
+
return transformSourceForIam(code, file);
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
buildEnd(error) {
|
|
58
|
+
if (error) buildFailed = true;
|
|
45
59
|
},
|
|
46
60
|
async closeBundle() {
|
|
47
61
|
const environment = this?.environment?.name;
|
|
48
|
-
if (!releaseId || server || (environment && environment !== "client")) return;
|
|
62
|
+
if (!releaseId || server || buildFailed || (environment && environment !== "client")) return;
|
|
49
63
|
await finishBuildRelease({
|
|
50
64
|
root,
|
|
51
65
|
releaseId,
|
|
52
66
|
name,
|
|
67
|
+
entry,
|
|
53
68
|
automaticAnchors,
|
|
54
69
|
cssDirectory: outDir,
|
|
55
70
|
mounts: [{ directory: outDir, urlPath: base }],
|
|
56
71
|
publicDirectory: outDir,
|
|
57
72
|
rootFont,
|
|
58
73
|
omitSvgResources,
|
|
59
|
-
upload: { apiKey, baseUrl, upload, fetch },
|
|
74
|
+
upload: { apiKey, baseUrl, upload, client, fetch },
|
|
60
75
|
strict,
|
|
61
76
|
logger,
|
|
62
77
|
});
|