mirror of
https://github.com/morluto/rea.git
synced 2026-10-26 17:35:11 +00:00
fix(apple): preserve own artifact metadata through schema projection
This commit is contained in:
1 parent
b7e76a57cd
commit
fef76a02fb
3 files changed
+43
-6
No files matched your search
@@ -659,3 +659,34 @@ it.each(["Toolbar", "MissingToolbar"])(
|
||||
expect(result.resource_key_coverage.status).toBe("complete");
|
||||
},
|
||||
);
|
||||
|
||||
it("preserves every own JSON metadata field through catalog inspection and page projection", async () => {
|
||||
const bundle = await createTestTempDirectory("rea-asset-metadata-members-");
|
||||
const catalog = Buffer.from("inert catalog for the output-decoding boundary");
|
||||
await writeFile(join(bundle, "Assets.car"), catalog);
|
||||
// Authored producer text exercises the accepted metadata contract; it is not
|
||||
// evidence that native assetutil emits these additional field names.
|
||||
const output =
|
||||
'[{"Name":"Toolbar","RenditionName":"Toolbar@2x","__proto__":{"Name":"metadata, not an inherited asset name"},"constructor":"retained constructor metadata","toString":false,"Unknown":{"__proto__":{"value":0}},"Empty":"","Zero":0,"Absent":null}]';
|
||||
const result = await analyzeAppleAssetCatalogs({
|
||||
bundlePath: bundle,
|
||||
targetSha256: "a".repeat(64),
|
||||
environment: {},
|
||||
runAssetUtil: async (path) => {
|
||||
expect(path).toBe(join(bundle, "Assets.car"));
|
||||
return output;
|
||||
},
|
||||
});
|
||||
const expected: unknown = JSON.parse(output);
|
||||
expect(result.records.map(({ metadata }) => metadata)).toEqual(expected);
|
||||
expect(result.records[0]).toMatchObject({
|
||||
asset_name: "Toolbar",
|
||||
rendition_name: "Toolbar@2x",
|
||||
catalog_path: "Assets.car",
|
||||
catalog_sha256: createHash("sha256").update(catalog).digest("hex"),
|
||||
});
|
||||
const metadata = result.records[0]?.metadata;
|
||||
if (metadata === undefined) throw new Error("missing catalog metadata");
|
||||
expect(Object.hasOwn(metadata, "__proto__")).toBe(true);
|
||||
expect(Object.getPrototypeOf(metadata)).toBe(Object.prototype);
|
||||
});
|
||||
@@ -1,7 +1,7 @@
|
||||
import { z } from "zod";
|
||||
import { bundleResourceBoundResultSchema } from "./bundleResourceRoot.js";
|
||||
|
||||
import { jsonValueSchema } from "../jsonValue.js";
|
||||
import { jsonObjectSchema, jsonValueSchema } from "../jsonValue.js";
|
||||
import { AnalysisOutputError } from "../analysisErrorCore.js";
|
||||
import {
|
||||
artifactInventoryCoverageSchema,
|
||||
@@ -51,7 +51,7 @@ const recordSchema = z.strictObject({
|
||||
kind: z.enum(["catalog", "rendition"]),
|
||||
asset_name: z.string().nullable(),
|
||||
rendition_name: z.string().nullable(),
|
||||
metadata: z.record(z.string(), jsonValueSchema),
|
||||
metadata: jsonObjectSchema,
|
||||
});
|
||||
|
||||
const resourceKeyMatchSchema = z.strictObject({
|
||||
@@ -116,7 +116,7 @@ export const parseAppleAssetCatalogRecords = (
|
||||
"assetutil output must be a JSON array",
|
||||
);
|
||||
return value.map((record, index) => {
|
||||
const parsed = z.record(z.string(), jsonValueSchema).safeParse(record);
|
||||
const parsed = jsonObjectSchema.safeParse(record);
|
||||
if (!parsed.success)
|
||||
throw new AnalysisOutputError(
|
||||
"inspect_asset_catalog",
|
||||
|
||||
@@ -43,7 +43,7 @@ it("keeps literal wrapper-shaped dictionaries as real root maps", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("retains own binary dictionary facts when a prototype key changes the decoder prototype", () => {
|
||||
it("retains an own binary dictionary prototype key without changing the decoded prototype", () => {
|
||||
const object = Object.fromEntries([
|
||||
["__proto__", { inherited: "not an own fact" }],
|
||||
["payload", "retained"],
|
||||
@@ -63,8 +63,14 @@ it("retains own binary dictionary facts when a prototype key changes the decoder
|
||||
kind: "dictionary",
|
||||
value: { payload: "retained" },
|
||||
});
|
||||
expect(graph.objects[1]?.value).toEqual({ payload: "retained" });
|
||||
expect(graph.limitations).toContainEqual(
|
||||
const value = graph.objects[1]?.value;
|
||||
expect(value).toEqual(object);
|
||||
if (value === null || typeof value !== "object")
|
||||
throw new Error("Expected a decoded dictionary");
|
||||
expect(Object.hasOwn(value, "__proto__")).toBe(true);
|
||||
expect(Object.hasOwn(value, "inherited")).toBe(false);
|
||||
expect(Object.getPrototypeOf(value)).toBe(Object.prototype);
|
||||
expect(graph.limitations).not.toContainEqual(
|
||||
expect.stringContaining("__proto__"),
|
||||
);
|
||||
});
|
||||
Reference in new issue
Block a user