@samva/markup 0.3.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/AGENTS.md +17 -0
- package/dist/{ast-63I-VLQx.d.ts → ast-BLybiDxp.d.ts} +34 -60
- package/dist/ast.d.ts +2 -2
- package/dist/ast.js +4 -52
- package/dist/catalog-Db0UcCTg.d.ts +356 -0
- package/dist/{checks-DXuERO4B.js → checks-CmmITP6j.js} +14 -14
- package/dist/checks.d.ts +1 -1
- package/dist/checks.js +1 -1
- package/dist/classes.d.ts +1 -1
- package/dist/compile-sms.d.ts +3 -3
- package/dist/compile-whatsapp.d.ts +5 -5
- package/dist/compile-whatsapp.js +3 -3
- package/dist/compile.d.ts +5 -5
- package/dist/compile.js +5 -5
- package/dist/compiler.d.ts +4 -4
- package/dist/compiler.js +6 -6
- package/dist/components.d.ts +4 -4
- package/dist/conditionals.js +3 -3
- package/dist/corpus-CM7rKX41.d.ts +106 -0
- package/dist/{css-ar2lU3NC.d.ts → css-DoNc7CiC.d.ts} +4 -5
- package/dist/diagnostics-CqepLcpI.d.ts +47 -0
- package/dist/diagnostics-eFM9A_TU.d.ts +46 -0
- package/dist/diagnostics.d.ts +2 -2
- package/dist/diagnostics.js +15 -29
- package/dist/{elements-DtwKlFVH.d.ts → elements-ChJULZlh.d.ts} +40 -161
- package/dist/email/components.d.ts +1 -1
- package/dist/email/diagnostics.d.ts +1 -1
- package/dist/email/diagnostics.js +8 -43
- package/dist/email/elements.d.ts +1 -1
- package/dist/email/html.d.ts +2 -2
- package/dist/email/html.js +9 -9
- package/dist/email/jsx-dev-runtime.d.ts +3 -21
- package/dist/email/jsx-runtime.d.ts +1 -1
- package/dist/email/jsx-runtime.js +29 -3
- package/dist/email/render.d.ts +4 -4
- package/dist/email/render.js +1 -1
- package/dist/email/selection.d.ts +20 -31
- package/dist/email/selection.js +1 -53
- package/dist/email/source-edit.d.ts +1 -1
- package/dist/email/source-edit.js +2 -2
- package/dist/email/stylesheets.d.ts +1 -1
- package/dist/email/text.d.ts +1 -1
- package/dist/email/text.js +3 -3
- package/dist/emit.d.ts +2 -2
- package/dist/emit.js +5 -5
- package/dist/guards-eV1qLbf2.js +9 -0
- package/dist/{input-schema-BIfzI63B.d.ts → input-schema-7dPFVvNE.d.ts} +2 -2
- package/dist/input-schema-zjkgrXn2.js +455 -0
- package/dist/input-schema.d.ts +1 -1
- package/dist/input-schema.js +1 -169
- package/dist/interpolate.d.ts +9 -12
- package/dist/interpolate.js +1 -19
- package/dist/jsx-dev-runtime.d.ts +2 -2
- package/dist/{jsx-runtime-C5k_Zq0A.d.ts → jsx-runtime-BI4gI19E.d.ts} +3 -3
- package/dist/jsx-runtime.d.ts +1 -1
- package/dist/jsx-runtime.js +3 -3
- package/dist/model.d.ts +18 -33
- package/dist/model.js +4 -17
- package/dist/ops.d.ts +78 -172
- package/dist/ops.js +51 -117
- package/dist/{parser-CGBS73Gz.d.ts → parser-b_Kp5MT6.d.ts} +5 -5
- package/dist/parser.d.ts +1 -1
- package/dist/parser.js +8 -8
- package/dist/{predicate-G2SeSvoN.d.ts → predicate-Bmvgw7Ao.d.ts} +4 -4
- package/dist/{predicate-CvkzT-a2.js → predicate-DwXzmqIY.js} +11 -11
- package/dist/predicate.d.ts +1 -1
- package/dist/predicate.js +1 -1
- package/dist/presets/category-mapping.d.ts +1 -1
- package/dist/presets/corpus.d.ts +1 -1
- package/dist/presets/corpus.js +87 -140
- package/dist/presets/public-gallery.d.ts +106 -130
- package/dist/presets/public-gallery.js +131 -209
- package/dist/presets/public-handoff.d.ts +4 -4
- package/dist/presets/public-handoff.js +13 -11
- package/dist/presets/public-preview-artifacts.d.ts +5 -5
- package/dist/presets/public-preview-artifacts.js +9 -9
- package/dist/presets/public-preview.d.ts +0 -4
- package/dist/presets/public-preview.js +37 -362
- package/dist/presets/showcase.d.ts +2 -0
- package/dist/presets/showcase.js +627 -0
- package/dist/presets/sources.d.ts +1 -1
- package/dist/presets/sources.js +5767 -2023
- package/dist/presets.d.ts +2 -384
- package/dist/presets.js +299 -765
- package/dist/printer.d.ts +1 -1
- package/dist/{render-ykQhtMs_.js → render-T6IFPnP4.js} +12 -12
- package/dist/render-template.d.ts +7 -7
- package/dist/render-template.js +6 -6
- package/dist/showcase-dvJMn-Lo.d.ts +456 -0
- package/dist/{source-locations-BCJQnIfU.d.ts → source-locations-D6Te6Gy1.d.ts} +4 -26
- package/dist/source-locations.d.ts +2 -2
- package/dist/source-locations.js +3 -26
- package/dist/{template-Dy5yOPyp.d.ts → template-G-QPcfmn.d.ts} +4 -4
- package/dist/template.d.ts +1 -1
- package/dist/template.js +3 -3
- package/dist/theme-css.d.ts +3 -3
- package/dist/theme-css.js +3 -3
- package/dist/tsx-source-instrumentation.d.ts +1 -3
- package/dist/tsx-source-instrumentation.js +6 -6
- package/dist/tsx-tracer.d.ts +7 -11
- package/dist/tsx-tracer.js +164 -164
- package/dist/{variables-if1VrV34.d.ts → variables-BnKs1iqb.d.ts} +2 -2
- package/dist/variables.d.ts +1 -1
- package/dist/variables.js +4 -4
- package/package.json +8 -3
- package/dist/corpus-qrUD5O6r.d.ts +0 -254
- package/dist/diagnostics-Djd9ckLg.d.ts +0 -90
- package/dist/diagnostics-oveE-laV.d.ts +0 -79
package/dist/presets/corpus.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
|
+
import { n as isObject } from "../guards-eV1qLbf2.js";
|
|
1
2
|
import { presetCatalog } from "../presets.js";
|
|
2
|
-
import {
|
|
3
|
+
import { showcaseProject, showcaseProjects, showcaseSourcePath } from "./showcase.js";
|
|
4
|
+
import { Result } from "better-result";
|
|
3
5
|
//#region presets/corpus.ts
|
|
4
|
-
const TemplateCorpusKind = Schema.Literals([
|
|
5
|
-
"owned-editable-sml",
|
|
6
|
-
"brand-recreation-sml",
|
|
7
|
-
"inspiration-reference"
|
|
8
|
-
]);
|
|
9
6
|
const templateFacetOptions = {
|
|
10
7
|
jobType: [
|
|
11
8
|
"account-access",
|
|
@@ -46,121 +43,24 @@ const templateFacetOptions = {
|
|
|
46
43
|
],
|
|
47
44
|
brandProvenance: ["samva-original", "third-party-reference"]
|
|
48
45
|
};
|
|
49
|
-
const JobTypeFacet = Schema.Literals(templateFacetOptions.jobType);
|
|
50
|
-
const LifecycleFacet = Schema.Literals(templateFacetOptions.lifecycle);
|
|
51
|
-
const IndustryFacet = Schema.Literals(templateFacetOptions.industry);
|
|
52
|
-
const SeasonFacet = Schema.Literals(templateFacetOptions.season);
|
|
53
|
-
const AudienceFacet = Schema.Literals(templateFacetOptions.audience);
|
|
54
|
-
const DesignFacet = Schema.Literals(templateFacetOptions.design);
|
|
55
|
-
const BrandProvenanceFacet = Schema.Literals(templateFacetOptions.brandProvenance);
|
|
56
|
-
const TemplateFacetSet = Schema.Struct({
|
|
57
|
-
jobType: Schema.Array(JobTypeFacet),
|
|
58
|
-
lifecycle: Schema.Array(LifecycleFacet),
|
|
59
|
-
industry: Schema.Array(IndustryFacet),
|
|
60
|
-
season: Schema.Array(SeasonFacet),
|
|
61
|
-
audience: Schema.Array(AudienceFacet),
|
|
62
|
-
design: Schema.Array(DesignFacet),
|
|
63
|
-
brandProvenance: Schema.Array(BrandProvenanceFacet)
|
|
64
|
-
});
|
|
65
|
-
const CorpusReview = Schema.Struct({
|
|
66
|
-
state: Schema.Literals([
|
|
67
|
-
"draft",
|
|
68
|
-
"approved",
|
|
69
|
-
"rejected"
|
|
70
|
-
]),
|
|
71
|
-
reviewedBy: Schema.String,
|
|
72
|
-
reviewedAt: Schema.String,
|
|
73
|
-
notes: Schema.String
|
|
74
|
-
});
|
|
75
|
-
const CorpusDisplay = Schema.Struct({
|
|
76
|
-
state: Schema.Literals(["hidden", "public"]),
|
|
77
|
-
attributionLabel: Schema.String
|
|
78
|
-
});
|
|
79
|
-
const CorpusRetention = Schema.Struct({
|
|
80
|
-
policy: Schema.Literals(["retain-until-withdrawn", "retain-while-linked"]),
|
|
81
|
-
reviewedAt: Schema.String
|
|
82
|
-
});
|
|
83
|
-
const CorpusTakedown = Schema.Struct({
|
|
84
|
-
state: Schema.Literals(["active", "removed"]),
|
|
85
|
-
contact: Schema.String,
|
|
86
|
-
procedureUrl: Schema.String
|
|
87
|
-
});
|
|
88
|
-
const OwnedEditablePreset = Schema.TaggedStruct("OwnedEditablePreset", {
|
|
89
|
-
corpusKind: Schema.Literal("owned-editable-sml"),
|
|
90
|
-
provenance: Schema.Struct({
|
|
91
|
-
owner: Schema.Literal("Samva"),
|
|
92
|
-
sourcePath: Schema.String,
|
|
93
|
-
recordedAt: Schema.String
|
|
94
|
-
}),
|
|
95
|
-
review: CorpusReview,
|
|
96
|
-
display: CorpusDisplay,
|
|
97
|
-
retention: CorpusRetention,
|
|
98
|
-
takedown: CorpusTakedown
|
|
99
|
-
});
|
|
100
|
-
const BrandRecreationPreset = Schema.TaggedStruct("BrandRecreationPreset", {
|
|
101
|
-
corpusKind: Schema.Literal("brand-recreation-sml"),
|
|
102
|
-
provenance: Schema.Struct({
|
|
103
|
-
owner: Schema.Literal("Samva"),
|
|
104
|
-
sourcePath: Schema.String,
|
|
105
|
-
recordedAt: Schema.String,
|
|
106
|
-
/** The brand whose own email is recreated, named on every public surface. */
|
|
107
|
-
brand: Schema.String,
|
|
108
|
-
/** What that brand's email does, in the customer's words. */
|
|
109
|
-
subject: Schema.String,
|
|
110
|
-
reviewedNote: Schema.String
|
|
111
|
-
}),
|
|
112
|
-
review: CorpusReview,
|
|
113
|
-
display: CorpusDisplay,
|
|
114
|
-
retention: CorpusRetention,
|
|
115
|
-
takedown: CorpusTakedown
|
|
116
|
-
});
|
|
117
46
|
/** Clean-room recreations of a named brand's own email, authored as editable Samva projects. */
|
|
118
|
-
const brandRecreationProvenance = {
|
|
119
|
-
"
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
},
|
|
127
|
-
"vercel-invitation": {
|
|
128
|
-
owner: "Samva",
|
|
129
|
-
sourcePath: "examples/email-showcase/emails/vercel-invitation.tsx",
|
|
130
|
-
recordedAt: "2026-09-08T00:00:00.000Z",
|
|
131
|
-
brand: "Vercel",
|
|
132
|
-
subject: "team invitation",
|
|
133
|
-
reviewedNote: "Reviewed recreation of Vercel's team invitation email, its canonical project assets, and its brand attribution."
|
|
134
|
-
}
|
|
135
|
-
};
|
|
47
|
+
const brandRecreationProvenance = Object.fromEntries(showcaseProjects.flatMap((project) => project.provenance.kind === "brand-recreation" ? [[project.id, {
|
|
48
|
+
owner: "Samva",
|
|
49
|
+
sourcePath: showcaseSourcePath(project),
|
|
50
|
+
recordedAt: project.recordedAt,
|
|
51
|
+
brand: project.provenance.brand,
|
|
52
|
+
subject: project.provenance.subject,
|
|
53
|
+
reviewedNote: project.provenance.reviewedNote
|
|
54
|
+
}]] : []));
|
|
136
55
|
/**
|
|
137
56
|
* Owned presets authored as complete showcase projects with their own stylesheet and assets.
|
|
138
57
|
* Every other owned preset is the single module `packages/markup/presets/<id>.tsx`.
|
|
139
58
|
*/
|
|
140
|
-
const ownedShowcasePresetSources =
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
"
|
|
59
|
+
const ownedShowcasePresetSources = Object.fromEntries(showcaseProjects.flatMap((project) => project.provenance.kind === "owned" ? [[project.id, showcaseSourcePath(project)]] : []));
|
|
60
|
+
const ownedPresetSourcePath = (id) => {
|
|
61
|
+
const project = showcaseProject(id);
|
|
62
|
+
return project === void 0 || project.provenance.kind !== "owned" ? `packages/markup/presets/${id}.tsx` : showcaseSourcePath(project);
|
|
144
63
|
};
|
|
145
|
-
const ownedPresetSourcePath = (id) => Object.hasOwn(ownedShowcasePresetSources, id) ? ownedShowcasePresetSources[id] : `packages/markup/presets/${id}.tsx`;
|
|
146
|
-
const InspirationReference = Schema.TaggedStruct("InspirationReference", {
|
|
147
|
-
corpusKind: Schema.Literal("inspiration-reference"),
|
|
148
|
-
provenance: Schema.Struct({
|
|
149
|
-
publisher: Schema.String,
|
|
150
|
-
sourceUrl: Schema.String,
|
|
151
|
-
capturedAt: Schema.String,
|
|
152
|
-
rightsBasis: Schema.Literals(["display-link-and-commentary", "permission"])
|
|
153
|
-
}),
|
|
154
|
-
review: CorpusReview,
|
|
155
|
-
display: CorpusDisplay,
|
|
156
|
-
retention: CorpusRetention,
|
|
157
|
-
takedown: CorpusTakedown
|
|
158
|
-
});
|
|
159
|
-
const TemplateCorpusRecord = Schema.Union([
|
|
160
|
-
OwnedEditablePreset,
|
|
161
|
-
BrandRecreationPreset,
|
|
162
|
-
InspirationReference
|
|
163
|
-
]);
|
|
164
64
|
const ISO_TIMESTAMP = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/;
|
|
165
65
|
const nonEmpty = (value) => value.trim().length > 0;
|
|
166
66
|
const isHttpsUrl = (value) => {
|
|
@@ -176,65 +76,112 @@ const requiredFacetDimensions = [
|
|
|
176
76
|
"design",
|
|
177
77
|
"brandProvenance"
|
|
178
78
|
];
|
|
79
|
+
/** Exact key sets: a record carrying anything else is not the shape this gate admits. */
|
|
80
|
+
const exactKeys = (value, keys) => isObject(value) && Object.keys(value).length === keys.length && keys.every((key) => Object.hasOwn(value, key));
|
|
81
|
+
const isStringIn = (value, values) => typeof value === "string" && values.includes(value);
|
|
82
|
+
const isStringArrayIn = (value, values) => Array.isArray(value) && value.every((entry) => isStringIn(entry, values));
|
|
83
|
+
const isReview = (value) => exactKeys(value, [
|
|
84
|
+
"state",
|
|
85
|
+
"reviewedBy",
|
|
86
|
+
"reviewedAt",
|
|
87
|
+
"notes"
|
|
88
|
+
]) && isStringIn(value.state, [
|
|
89
|
+
"draft",
|
|
90
|
+
"approved",
|
|
91
|
+
"rejected"
|
|
92
|
+
]) && typeof value.reviewedBy === "string" && typeof value.reviewedAt === "string" && typeof value.notes === "string";
|
|
93
|
+
const isDisplay = (value) => exactKeys(value, ["state", "attributionLabel"]) && isStringIn(value.state, ["hidden", "public"]) && typeof value.attributionLabel === "string";
|
|
94
|
+
const isRetention = (value) => exactKeys(value, ["policy", "reviewedAt"]) && isStringIn(value.policy, ["retain-until-withdrawn", "retain-while-linked"]) && typeof value.reviewedAt === "string";
|
|
95
|
+
const isTakedown = (value) => exactKeys(value, [
|
|
96
|
+
"state",
|
|
97
|
+
"contact",
|
|
98
|
+
"procedureUrl"
|
|
99
|
+
]) && isStringIn(value.state, ["active", "removed"]) && typeof value.contact === "string" && typeof value.procedureUrl === "string";
|
|
100
|
+
/** The four governance blocks every corpus record carries, whatever its kind. */
|
|
101
|
+
const hasGovernance = (value) => isReview(value.review) && isDisplay(value.display) && isRetention(value.retention) && isTakedown(value.takedown);
|
|
102
|
+
const CORPUS_KEYS = [
|
|
103
|
+
"type",
|
|
104
|
+
"corpusKind",
|
|
105
|
+
"provenance",
|
|
106
|
+
"review",
|
|
107
|
+
"display",
|
|
108
|
+
"retention",
|
|
109
|
+
"takedown"
|
|
110
|
+
];
|
|
111
|
+
const isCorpusRecord = (value) => {
|
|
112
|
+
if (!exactKeys(value, CORPUS_KEYS) || !hasGovernance(value)) return false;
|
|
113
|
+
const provenance = value.provenance;
|
|
114
|
+
if (value.type === "OwnedEditablePreset") return value.corpusKind === "owned-editable-sml" && exactKeys(provenance, [
|
|
115
|
+
"owner",
|
|
116
|
+
"sourcePath",
|
|
117
|
+
"recordedAt"
|
|
118
|
+
]) && provenance.owner === "Samva" && typeof provenance.sourcePath === "string" && typeof provenance.recordedAt === "string";
|
|
119
|
+
if (value.type === "BrandRecreationPreset") return value.corpusKind === "brand-recreation-sml" && exactKeys(provenance, [
|
|
120
|
+
"owner",
|
|
121
|
+
"sourcePath",
|
|
122
|
+
"recordedAt",
|
|
123
|
+
"brand",
|
|
124
|
+
"subject",
|
|
125
|
+
"reviewedNote"
|
|
126
|
+
]) && provenance.owner === "Samva" && typeof provenance.sourcePath === "string" && typeof provenance.recordedAt === "string" && typeof provenance.brand === "string" && typeof provenance.subject === "string" && typeof provenance.reviewedNote === "string";
|
|
127
|
+
return value.type === "InspirationReference" && value.corpusKind === "inspiration-reference" && exactKeys(provenance, [
|
|
128
|
+
"publisher",
|
|
129
|
+
"sourceUrl",
|
|
130
|
+
"capturedAt",
|
|
131
|
+
"rightsBasis"
|
|
132
|
+
]) && typeof provenance.publisher === "string" && typeof provenance.sourceUrl === "string" && typeof provenance.capturedAt === "string" && isStringIn(provenance.rightsBasis, ["display-link-and-commentary", "permission"]);
|
|
133
|
+
};
|
|
134
|
+
const isFacetSet = (value) => exactKeys(value, requiredFacetDimensions) && requiredFacetDimensions.every((dimension) => isStringArrayIn(value[dimension], templateFacetOptions[dimension]));
|
|
135
|
+
const isCorpusEntry = (value) => exactKeys(value, [
|
|
136
|
+
"id",
|
|
137
|
+
"corpus",
|
|
138
|
+
"facets"
|
|
139
|
+
]) && typeof value.id === "string" && isCorpusRecord(value.corpus) && isFacetSet(value.facets);
|
|
179
140
|
const canonicalOwnedPresetSources = new Map(presetCatalog.filter((preset) => preset.channel === "email" && !Object.hasOwn(brandRecreationProvenance, preset.id)).map((preset) => [preset.id, ownedPresetSourcePath(preset.id)]));
|
|
180
141
|
/** Decode and gate a record before it can enter any public projection. */
|
|
181
142
|
const registerPublicCorpusEntry = (input) => {
|
|
182
|
-
|
|
183
|
-
id: Schema.String,
|
|
184
|
-
corpus: TemplateCorpusRecord,
|
|
185
|
-
facets: TemplateFacetSet
|
|
186
|
-
}), { onExcessProperty: "error" })(input);
|
|
187
|
-
if (Result.isFailure(decoded)) return Result.fail({
|
|
143
|
+
if (!isCorpusEntry(input)) return Result.err({
|
|
188
144
|
id: "unknown",
|
|
189
145
|
message: "record does not match a corpus schema"
|
|
190
146
|
});
|
|
191
|
-
const { id, corpus, facets } =
|
|
147
|
+
const { id, corpus, facets } = input;
|
|
192
148
|
const timestamps = [
|
|
193
149
|
corpus.review.reviewedAt,
|
|
194
150
|
corpus.retention.reviewedAt,
|
|
195
|
-
corpus.
|
|
151
|
+
corpus.type === "InspirationReference" ? corpus.provenance.capturedAt : corpus.provenance.recordedAt
|
|
196
152
|
];
|
|
197
|
-
if (!nonEmpty(id) || corpus.review.state !== "approved" || !nonEmpty(corpus.review.reviewedBy) || !nonEmpty(corpus.review.notes) || corpus.display.state !== "public" || !nonEmpty(corpus.display.attributionLabel) || corpus.takedown.state !== "active" || !nonEmpty(corpus.takedown.contact) || !isHttpsUrl(corpus.takedown.procedureUrl) || timestamps.some((timestamp) => !ISO_TIMESTAMP.test(timestamp))) return Result.
|
|
153
|
+
if (!nonEmpty(id) || corpus.review.state !== "approved" || !nonEmpty(corpus.review.reviewedBy) || !nonEmpty(corpus.review.notes) || corpus.display.state !== "public" || !nonEmpty(corpus.display.attributionLabel) || corpus.takedown.state !== "active" || !nonEmpty(corpus.takedown.contact) || !isHttpsUrl(corpus.takedown.procedureUrl) || timestamps.some((timestamp) => !ISO_TIMESTAMP.test(timestamp))) return Result.err({
|
|
198
154
|
id,
|
|
199
155
|
message: "public corpus records require approved review, display, retention, and takedown metadata"
|
|
200
156
|
});
|
|
201
|
-
if (corpus.
|
|
157
|
+
if (corpus.type === "OwnedEditablePreset" && (canonicalOwnedPresetSources.get(id) !== corpus.provenance.sourcePath || corpus.retention.policy !== "retain-until-withdrawn" || facets.brandProvenance.some((value) => value !== "samva-original"))) return Result.err({
|
|
202
158
|
id,
|
|
203
159
|
message: "owned presets require a canonical editable TSX source"
|
|
204
160
|
});
|
|
205
|
-
if (corpus.
|
|
161
|
+
if (corpus.type === "BrandRecreationPreset") {
|
|
206
162
|
const canonical = Object.entries(brandRecreationProvenance).find(([presetId]) => presetId === id)?.[1];
|
|
207
|
-
if (canonical === void 0 || Object.entries(canonical).some(([key, value]) => corpus.provenance[key] !== value) || !nonEmpty(corpus.provenance.brand) || !nonEmpty(corpus.provenance.subject) || corpus.retention.policy !== "retain-until-withdrawn" || facets.brandProvenance.some((value) => value !== "third-party-reference")) return Result.
|
|
163
|
+
if (canonical === void 0 || Object.entries(canonical).some(([key, value]) => corpus.provenance[key] !== value) || !nonEmpty(corpus.provenance.brand) || !nonEmpty(corpus.provenance.subject) || corpus.retention.policy !== "retain-until-withdrawn" || facets.brandProvenance.some((value) => value !== "third-party-reference")) return Result.err({
|
|
208
164
|
id,
|
|
209
165
|
message: "brand recreations require a canonical source, a referenced brand and subject, and third-party provenance"
|
|
210
166
|
});
|
|
211
167
|
}
|
|
212
|
-
if (corpus.
|
|
168
|
+
if (corpus.type === "InspirationReference" && (!isHttpsUrl(corpus.provenance.sourceUrl) || corpus.retention.policy !== "retain-while-linked" || facets.brandProvenance.some((value) => value !== "third-party-reference"))) return Result.err({
|
|
213
169
|
id,
|
|
214
170
|
message: "inspiration references require an HTTPS source and third-party provenance facet"
|
|
215
171
|
});
|
|
216
172
|
for (const dimension of requiredFacetDimensions) {
|
|
217
173
|
const values = facets[dimension];
|
|
218
|
-
if (values.length === 0 || new Set(values).size !== values.length) return Result.
|
|
174
|
+
if (values.length === 0 || new Set(values).size !== values.length) return Result.err({
|
|
219
175
|
id,
|
|
220
176
|
message: `facet ${dimension} must be populated without duplicates`
|
|
221
177
|
});
|
|
222
178
|
}
|
|
223
|
-
return Result.
|
|
179
|
+
return Result.ok({
|
|
224
180
|
id,
|
|
225
181
|
corpus,
|
|
226
182
|
facets
|
|
227
183
|
});
|
|
228
184
|
};
|
|
229
|
-
const TemplateFacetQuery = Schema.Struct({
|
|
230
|
-
jobType: Schema.optionalKey(Schema.Array(JobTypeFacet)),
|
|
231
|
-
lifecycle: Schema.optionalKey(Schema.Array(LifecycleFacet)),
|
|
232
|
-
industry: Schema.optionalKey(Schema.Array(IndustryFacet)),
|
|
233
|
-
season: Schema.optionalKey(Schema.Array(SeasonFacet)),
|
|
234
|
-
audience: Schema.optionalKey(Schema.Array(AudienceFacet)),
|
|
235
|
-
design: Schema.optionalKey(Schema.Array(DesignFacet)),
|
|
236
|
-
brandProvenance: Schema.optionalKey(Schema.Array(BrandProvenanceFacet))
|
|
237
|
-
});
|
|
238
185
|
/** Strict intersection: every selected value in every selected dimension must match. */
|
|
239
186
|
const matchesTemplateFacets = (facets, query) => requiredFacetDimensions.every((dimension) => {
|
|
240
187
|
const selected = query[dimension];
|
|
@@ -242,6 +189,6 @@ const matchesTemplateFacets = (facets, query) => requiredFacetDimensions.every((
|
|
|
242
189
|
return selected === void 0 || selected.every((value) => available.has(value));
|
|
243
190
|
});
|
|
244
191
|
//#endregion
|
|
245
|
-
export {
|
|
192
|
+
export { brandRecreationProvenance, matchesTemplateFacets, ownedPresetSourcePath, ownedShowcasePresetSources, registerPublicCorpusEntry, templateFacetOptions };
|
|
246
193
|
|
|
247
194
|
//# sourceMappingURL=corpus.js.map
|