@contentrain/types 1.29.0 → 1.31.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 +2 -1
- package/dist/index.d.mts +137 -8
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +160 -14
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -659,11 +659,32 @@ function isClaimOrigin(x) {
|
|
|
659
659
|
if (url.origin !== x || url.hostname.endsWith(".")) return false;
|
|
660
660
|
return url.protocol === "https:" || url.protocol === "http:" && LOCAL_HOSTS.has(url.hostname);
|
|
661
661
|
}
|
|
662
|
+
/** A compact JWS: three base64url segments, the signature non-empty. */
|
|
663
|
+
function isCompactJws(x) {
|
|
664
|
+
return typeof x === "string" && x.length <= 2048 && /^[\w-]+\.[\w-]+\.[\w-]+$/.test(x);
|
|
665
|
+
}
|
|
666
|
+
/** A fetchable export address: https (http for localhost), no credentials, query or fragment — nowhere for a secret. */
|
|
667
|
+
function isExportUrl(x) {
|
|
668
|
+
if (typeof x !== "string" || x.length > 2048) return false;
|
|
669
|
+
let url;
|
|
670
|
+
try {
|
|
671
|
+
url = new URL(x);
|
|
672
|
+
} catch {
|
|
673
|
+
return false;
|
|
674
|
+
}
|
|
675
|
+
if (url.username || url.password || url.search || url.hash || url.hostname.endsWith(".")) return false;
|
|
676
|
+
return url.protocol === "https:" || url.protocol === "http:" && LOCAL_HOSTS.has(url.hostname);
|
|
677
|
+
}
|
|
662
678
|
/**
|
|
663
679
|
* Check a decoded, signature-verified payload against the contract. Pass
|
|
664
680
|
* `now` (seconds since the epoch) to also check the validity window; without
|
|
665
681
|
* it only the shape and the window's own bounds are checked. Returns every
|
|
666
682
|
* problem found, as stable machine-readable strings (`field: problem`).
|
|
683
|
+
*
|
|
684
|
+
* A malformed `comments_export` does not fail the claim: it is an add-on, and
|
|
685
|
+
* a Migrate still sending an older shape must not stop the trial. It is
|
|
686
|
+
* dropped from `claim` and reported in `warnings`; Studio then offers the
|
|
687
|
+
* file upload instead.
|
|
667
688
|
*/
|
|
668
689
|
function validateMigrateStudioClaim(input, options = {}) {
|
|
669
690
|
const errors = [];
|
|
@@ -707,17 +728,42 @@ function validateMigrateStudioClaim(input, options = {}) {
|
|
|
707
728
|
else if (c.scale !== void 0 && c.scale !== null && typeof c.scale !== "string") errors.push(`capabilities[${i}].scale: invalid`);
|
|
708
729
|
});
|
|
709
730
|
if (x.origin !== void 0 && !isClaimOrigin(x.origin)) errors.push("origin: invalid");
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
731
|
+
const warnings = [];
|
|
732
|
+
if (x.comments_export !== void 0) {
|
|
733
|
+
const ce = x.comments_export;
|
|
734
|
+
if (!isObject(ce)) warnings.push("comments_export: invalid");
|
|
735
|
+
else {
|
|
736
|
+
if (!isExportUrl(ce.url)) warnings.push("comments_export.url: invalid");
|
|
737
|
+
if (!isCompactJws(ce.token)) warnings.push("comments_export.token: invalid");
|
|
738
|
+
if (!isSeconds(ce.expires_at)) warnings.push("comments_export.expires_at: invalid");
|
|
739
|
+
else if (isSeconds(x.iat) && ce.expires_at <= x.iat) warnings.push("comments_export.expires_at: not after iat");
|
|
740
|
+
if (typeof ce.comments !== "number" || !Number.isInteger(ce.comments) || ce.comments < 0) warnings.push("comments_export.comments: invalid");
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
if (errors.length > 0) return {
|
|
714
744
|
ok: false,
|
|
715
745
|
errors
|
|
716
746
|
};
|
|
747
|
+
if (warnings.length === 0) return {
|
|
748
|
+
ok: true,
|
|
749
|
+
claim: x
|
|
750
|
+
};
|
|
751
|
+
const { comments_export: _dropped, ...rest } = x;
|
|
752
|
+
return {
|
|
753
|
+
ok: true,
|
|
754
|
+
claim: rest,
|
|
755
|
+
warnings
|
|
756
|
+
};
|
|
717
757
|
}
|
|
718
|
-
/**
|
|
758
|
+
/**
|
|
759
|
+
* Shape-only type guard (no clock check). The signature is the consumer's job. Stricter than
|
|
760
|
+
* `validateMigrateStudioClaim`: a claim whose `comments_export` would be dropped is `false` here,
|
|
761
|
+
* since the guard narrows the input itself, malformed export included. To keep such a claim, use
|
|
762
|
+
* `result.claim` from `validateMigrateStudioClaim`.
|
|
763
|
+
*/
|
|
719
764
|
function isMigrateStudioClaim(input) {
|
|
720
|
-
|
|
765
|
+
const result = validateMigrateStudioClaim(input);
|
|
766
|
+
return result.ok && !result.warnings;
|
|
721
767
|
}
|
|
722
768
|
//#endregion
|
|
723
769
|
//#region src/project-plan.ts
|
|
@@ -784,6 +830,24 @@ function footerMenusOf(site) {
|
|
|
784
830
|
}
|
|
785
831
|
/** A font size the starter writes into a style: a length, or a `clamp()`/`calc()`/`min()`/`max()` of lengths (a theme's fluid size). */
|
|
786
832
|
const CSS_LENGTH = /^(?!.*url\()(?:\d+(?:\.\d+)?(?:px|rem|em|%)|(?:clamp|calc|min|max)\([\d\s.,+*/()a-z%-]+\))$/;
|
|
833
|
+
/**
|
|
834
|
+
* How many object levels a field nests: 0 for a scalar or a list of scalars, 1 for an object of scalars,
|
|
835
|
+
* 2 for an object holding a list of objects (`hero.actions[]`). A list adds no level of its own.
|
|
836
|
+
*/
|
|
837
|
+
function fieldDepth(field) {
|
|
838
|
+
const children = [...Object.values(field.fields ?? {}), ...typeof field.items === "object" ? [field.items] : []];
|
|
839
|
+
return (field.type === "object" ? 1 : 0) + Math.max(0, ...children.map(fieldDepth));
|
|
840
|
+
}
|
|
841
|
+
/**
|
|
842
|
+
* Placement `rule`: a mapping table's section rule (`elementor:section:hero.split`) or element rule
|
|
843
|
+
* (`gutenberg:element:core/details`, `gutenberg:element:core/template-part:header`), a site component
|
|
844
|
+
* (`opus`), or the rich-text fallback.
|
|
845
|
+
*/
|
|
846
|
+
const PLAN_SECTION_RULE = /^(?:(?:gutenberg|elementor|divi|classic):(?:section:[a-z][\w.-]*|element:[a-z][\w./:-]*)|opus|prose)$/;
|
|
847
|
+
/** A content prop's field name in a section object: the prop in snake_case (`ctaLabel` → `cta_label`). */
|
|
848
|
+
function sectionFieldName(prop) {
|
|
849
|
+
return prop.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);
|
|
850
|
+
}
|
|
787
851
|
function validateProjectPlan(plan) {
|
|
788
852
|
const errors = [];
|
|
789
853
|
const warnings = [];
|
|
@@ -802,13 +866,18 @@ function validateProjectPlan(plan) {
|
|
|
802
866
|
].includes(part)) || new Set(parts).size !== parts.length) errors.push("site.post.header lists a part twice or one the starter does not have");
|
|
803
867
|
if (!Number.isSafeInteger(site.post.more) || site.post.more < 0 || site.post.more > 20) errors.push("site.post.more is not a count from 0 to 20");
|
|
804
868
|
}
|
|
805
|
-
if (site?.lists && ![
|
|
869
|
+
if (site?.lists && ![
|
|
870
|
+
"cards",
|
|
871
|
+
"list",
|
|
872
|
+
"full"
|
|
873
|
+
].includes(site.lists.display)) errors.push(`site.lists.display ${site.lists.display} is not cards, list or full`);
|
|
806
874
|
if (site?.lists?.text !== void 0 && !CSS_LENGTH.test(site.lists.text)) errors.push(`site.lists.text ${site.lists.text} is not a CSS size`);
|
|
807
875
|
const chrome = site?.chrome;
|
|
808
876
|
if (chrome?.brand !== void 0 && !CSS_LENGTH.test(chrome.brand)) errors.push(`site.chrome.brand ${chrome.brand} is not a CSS size`);
|
|
809
877
|
if (chrome?.tagline !== void 0 && typeof chrome.tagline !== "boolean") errors.push("site.chrome.tagline is not a boolean");
|
|
810
878
|
if (chrome?.titleLinks !== void 0 && typeof chrome.titleLinks !== "boolean") errors.push("site.chrome.titleLinks is not a boolean");
|
|
811
879
|
if (chrome?.navLinks !== void 0 && typeof chrome.navLinks !== "boolean") errors.push("site.chrome.navLinks is not a boolean");
|
|
880
|
+
if (chrome?.footerAlign !== void 0 && !["start", "center"].includes(chrome.footerAlign)) errors.push(`site.chrome.footerAlign ${chrome.footerAlign} is not start or center`);
|
|
812
881
|
if (chrome?.copyright !== void 0 && (typeof chrome.copyright !== "string" || !chrome.copyright.trim() || chrome.copyright.length > 200 || /[<>]/.test(chrome.copyright))) errors.push("site.chrome.copyright is not a line of plain text (1–200 characters, no markup)");
|
|
813
882
|
const footer = site?.menus?.footer;
|
|
814
883
|
if (typeof footer === "string") {
|
|
@@ -839,11 +908,13 @@ function validateProjectPlan(plan) {
|
|
|
839
908
|
if (m.origin === "plan") {
|
|
840
909
|
if (!m.fields) errors.push(`plan model ${m.id} has no fields`);
|
|
841
910
|
if (!m.name || !m.domain) errors.push(`plan model ${m.id} needs name and domain`);
|
|
842
|
-
if (m.kind === "collection" || m.kind === "document") {
|
|
843
|
-
const title = m.title_field ? m.fields
|
|
844
|
-
if (!m.title_field) errors.push(`plan model ${m.id} has no title_field`);
|
|
845
|
-
else if (
|
|
846
|
-
else if (
|
|
911
|
+
if (m.kind === "collection" || m.kind === "document" || m.kind === "singleton" && m.title_field) {
|
|
912
|
+
const title = m.title_field ? titleFieldTarget(m.fields, m.title_field) : void 0;
|
|
913
|
+
if (!m.title_field || !title) errors.push(`plan model ${m.id} has no title_field`);
|
|
914
|
+
else if (title.kind === "too-deep") errors.push(`plan model ${m.id}: title_field ${m.title_field} reaches more than one object deep`);
|
|
915
|
+
else if (title.kind === "not-object") errors.push(`plan model ${m.id}: title_field ${m.title_field} goes through ${title.at} (${title.type}), not an object field`);
|
|
916
|
+
else if (title.kind === "missing") errors.push(`plan model ${m.id}: title_field ${m.title_field} is not one of its fields`);
|
|
917
|
+
else if (!isTitleFieldType(title.def.type)) errors.push(`plan model ${m.id}: title_field ${m.title_field} is ${title.def.type}, not a text-like type`);
|
|
847
918
|
}
|
|
848
919
|
if (!m.extract?.length && !m.form) warnings.push(`plan model ${m.id} has no extraction — its entries start empty`);
|
|
849
920
|
}
|
|
@@ -856,9 +927,11 @@ function validateProjectPlan(plan) {
|
|
|
856
927
|
}
|
|
857
928
|
for (const x of m.extract ?? []) {
|
|
858
929
|
if (!x.rule && !x.fields) errors.push(`model ${m.id} extraction from ${x.from} has neither rule nor fields`);
|
|
930
|
+
if (x.field !== void 0 && m.fields && m.fields[x.field]?.type !== "object") errors.push(`model ${m.id} extraction from ${x.from} fills ${x.field}, which is not an object field`);
|
|
859
931
|
if (x.rule && !/^(gutenberg|elementor|divi|classic):[\w./:-]+$/.test(x.rule)) errors.push(`model ${m.id} extraction rule ${x.rule} is not <builder>:<match>`);
|
|
932
|
+
const target = x.field !== void 0 ? m.fields?.[x.field]?.fields : m.fields;
|
|
860
933
|
for (const [field, path] of Object.entries(x.fields ?? {})) {
|
|
861
|
-
if (
|
|
934
|
+
if (target && !target[field]) errors.push(`model ${m.id} extraction fills unknown field ${field}`);
|
|
862
935
|
if (!/^attr:[\w.-]+$|^[\d.]+\|(text|href|src|alt|datetime)$|^(?:dom|img|link|html):[^@]*(?:@[\w-]+)?$/.test(path)) errors.push(`model ${m.id} field ${field}: path ${path} is not "<path>|<prop>", "attr:<name>" or an element expression`);
|
|
863
936
|
}
|
|
864
937
|
}
|
|
@@ -883,6 +956,21 @@ function validateProjectPlan(plan) {
|
|
|
883
956
|
const b = s.bind;
|
|
884
957
|
if ("model" in b && !knownModel(b.model)) errors.push(`${at}: model ${b.model} is not declared`);
|
|
885
958
|
if (b.kind === "entry" && !route?.source) errors.push(`${at}: binds the route entry but ${route ? "the route has no source" : "layout has no entry"}`);
|
|
959
|
+
if (s.id !== void 0 && !/^[a-z][a-z0-9-]*$/.test(s.id)) errors.push(`${at}: id ${s.id} is not kebab-case`);
|
|
960
|
+
if (s.rule !== void 0 && !PLAN_SECTION_RULE.test(s.rule)) errors.push(`${at}: rule ${s.rule} is not <builder>:section:<id>, <builder>:element:<match>, opus or prose`);
|
|
961
|
+
if (b.kind === "section") {
|
|
962
|
+
const m = models.get(b.model);
|
|
963
|
+
const field = m?.fields?.[b.field];
|
|
964
|
+
const ownEntry = route?.page === b.model && route.source?.model === b.model;
|
|
965
|
+
if (m && m.origin === "plan" && m.kind !== "singleton" && b.entry === void 0 && !ownEntry) errors.push(`${at}: section of ${b.model} names no entry and ${b.model} is neither a singleton nor this route's page`);
|
|
966
|
+
if (m?.fields && !field) errors.push(`${at}: ${b.model} has no field ${b.field}`);
|
|
967
|
+
else if (field && field.type !== "object") errors.push(`${at}: ${b.model}.${b.field} is ${field.type}, not an object`);
|
|
968
|
+
else if (field && fieldDepth(field) > 2) errors.push(`${at}: ${b.model}.${b.field} nests deeper than 2 (an object inside a list item's object)`);
|
|
969
|
+
const fieldOf = new Map(Object.keys(c.props ?? {}).map((prop) => [sectionFieldName(prop), prop]));
|
|
970
|
+
if (c.props && field?.fields) {
|
|
971
|
+
for (const key of Object.keys(field.fields)) if (!fieldOf.has(key)) errors.push(`${at}: ${c.id} has no prop for field ${b.model}.${b.field}.${key} (fields are the props in snake_case)`);
|
|
972
|
+
}
|
|
973
|
+
}
|
|
886
974
|
const values = {
|
|
887
975
|
..."props" in b ? b.props : {},
|
|
888
976
|
...b.kind === "collection" && !b.into ? b.item : {}
|
|
@@ -892,8 +980,11 @@ function validateProjectPlan(plan) {
|
|
|
892
980
|
...b.kind === "collection" ? b.item : {}
|
|
893
981
|
})) if (!PLAN_VALUE_PATTERN.test(value)) errors.push(`${at}: ${prop} = ${value} is not a plan value (field: media: ref: href: term: ui: site: menu: page: const:)`);
|
|
894
982
|
if (c.props) {
|
|
983
|
+
const byField = new Map(Object.keys(c.props).map((prop) => [sectionFieldName(prop), prop]));
|
|
984
|
+
const spread = b.kind === "section" ? Object.keys(models.get(b.model)?.fields?.[b.field]?.fields ?? {}).flatMap((key) => byField.get(key) ?? []) : [];
|
|
895
985
|
const bound = new Set([
|
|
896
986
|
...Object.keys(values),
|
|
987
|
+
...spread,
|
|
897
988
|
...Object.keys(s.labels ?? {}),
|
|
898
989
|
..."into" in b && b.into ? [b.into] : b.kind === "menu" ? ["items"] : []
|
|
899
990
|
]);
|
|
@@ -914,6 +1005,18 @@ function validateProjectPlan(plan) {
|
|
|
914
1005
|
(byModel.get(r.source.model) ?? byModel.set(r.source.model, []).get(r.source.model)).push(r);
|
|
915
1006
|
}
|
|
916
1007
|
if (r.body === "composed" && !r.sections.length) warnings.push(`route ${r.id} is composed but has no sections`);
|
|
1008
|
+
if (r.page !== void 0) {
|
|
1009
|
+
const page = models.get(r.page);
|
|
1010
|
+
if (!page) errors.push(`route ${r.id}: page ${r.page} is not declared`);
|
|
1011
|
+
else if (page.kind === "collection" ? r.source?.model !== r.page : page.kind !== "singleton") errors.push(`route ${r.id}: page ${r.page} is a ${page.kind}; a page is a singleton, or a collection that is the route's source`);
|
|
1012
|
+
if (r.body !== "composed") errors.push(`route ${r.id}: a page model needs body composed`);
|
|
1013
|
+
}
|
|
1014
|
+
const sectionIds = /* @__PURE__ */ new Set();
|
|
1015
|
+
for (const s of r.sections) {
|
|
1016
|
+
if (s.id === void 0) continue;
|
|
1017
|
+
if (sectionIds.has(s.id)) errors.push(`route ${r.id}: section id ${s.id} is used twice`);
|
|
1018
|
+
sectionIds.add(s.id);
|
|
1019
|
+
}
|
|
917
1020
|
r.sections.forEach((s, i) => placement(s, `route ${r.id} section ${i}`, r));
|
|
918
1021
|
}
|
|
919
1022
|
const byPattern = /* @__PURE__ */ new Map();
|
|
@@ -1566,6 +1669,49 @@ const TITLE_FIELD_TYPE_SET = new Set(TITLE_FIELD_TYPES);
|
|
|
1566
1669
|
function isTitleFieldType(type) {
|
|
1567
1670
|
return TITLE_FIELD_TYPE_SET.has(type);
|
|
1568
1671
|
}
|
|
1672
|
+
/** Resolve a `title_field` path against a model's fields. A field named exactly `path` wins over splitting it. */
|
|
1673
|
+
function titleFieldTarget(fields, path) {
|
|
1674
|
+
if (fields && Object.hasOwn(fields, path)) return {
|
|
1675
|
+
kind: "field",
|
|
1676
|
+
def: fields[path]
|
|
1677
|
+
};
|
|
1678
|
+
const segments = path.split(".");
|
|
1679
|
+
if (segments.length > 2) return { kind: "too-deep" };
|
|
1680
|
+
const [head, leaf] = segments;
|
|
1681
|
+
const def = fields && Object.hasOwn(fields, head) ? fields[head] : void 0;
|
|
1682
|
+
if (!def) return {
|
|
1683
|
+
kind: "missing",
|
|
1684
|
+
at: head
|
|
1685
|
+
};
|
|
1686
|
+
if (leaf === void 0) return {
|
|
1687
|
+
kind: "field",
|
|
1688
|
+
def
|
|
1689
|
+
};
|
|
1690
|
+
if (def.type !== "object") return {
|
|
1691
|
+
kind: "not-object",
|
|
1692
|
+
at: head,
|
|
1693
|
+
type: def.type
|
|
1694
|
+
};
|
|
1695
|
+
const child = def.fields && Object.hasOwn(def.fields, leaf) ? def.fields[leaf] : void 0;
|
|
1696
|
+
if (!child) return {
|
|
1697
|
+
kind: "missing",
|
|
1698
|
+
at: path
|
|
1699
|
+
};
|
|
1700
|
+
return {
|
|
1701
|
+
kind: "field",
|
|
1702
|
+
def: child,
|
|
1703
|
+
parent: def
|
|
1704
|
+
};
|
|
1705
|
+
}
|
|
1706
|
+
/** An entry's title value: `data[title_field]`, or one level into an object for a dotted path. */
|
|
1707
|
+
function titleFieldValue(data, path) {
|
|
1708
|
+
if (data && Object.hasOwn(data, path)) return data[path];
|
|
1709
|
+
const [head, leaf, ...rest] = path.split(".");
|
|
1710
|
+
if (!data || head === void 0 || rest.length > 0) return void 0;
|
|
1711
|
+
const value = data[head];
|
|
1712
|
+
if (leaf === void 0) return value;
|
|
1713
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value[leaf] : void 0;
|
|
1714
|
+
}
|
|
1569
1715
|
/** Extensions we can name a MIME type for. Deliberately small — this is a sniff. */
|
|
1570
1716
|
const EXTENSION_MIME = {
|
|
1571
1717
|
jpg: "image/jpeg",
|
|
@@ -1986,6 +2132,6 @@ function serializeMarkdownFrontmatter(data, body) {
|
|
|
1986
2132
|
return lines.join("\n");
|
|
1987
2133
|
}
|
|
1988
2134
|
//#endregion
|
|
1989
|
-
export { APPROVAL_GATES, APPROVAL_MODES, CANONICAL_JSON, CAPABILITY_KEYS, CHROME_BODY_SLOT, CHROME_COMPONENT_CLOSE, CHROME_COMPONENT_OPEN, CHROME_IF_CLOSE, CHROME_IF_OPEN, CHROME_REPEAT_CLOSE, CHROME_REPEAT_OPEN, COMMENTS_EXPORT_FORMAT, COMPONENT_TYPES, CONTENTRAIN_BRANCH, CONTENTRAIN_DIR, DEFAULT_APPROVAL_POLICY, DICTIONARY_TITLE_FIELD, ENTRY_ID_PATTERN, EXECUTION_CONTRACT_VERSION, INTEGRATION_CATEGORIES, INTEGRATION_EVIDENCE_KINDS, LEGACY_CSS_LAYER, LIST_ITEMS_SLOT, LOCALE_PATTERN, LOCAL_CAPABILITIES, MIGRATE_STUDIO_CLAIM_ALG, MIGRATE_STUDIO_CLAIM_AUDIENCE, MIGRATE_STUDIO_CLAIM_CLOCK_SKEW_SECONDS, MIGRATE_STUDIO_CLAIM_ISSUER, MIGRATE_STUDIO_CLAIM_MAX_TRIAL_DAYS, MIGRATE_STUDIO_CLAIM_MAX_TTL_SECONDS, MIGRATE_STUDIO_CLAIM_VERSION, MIGRATE_STUDIO_PLANS, MIGRATION_CONTRACT_VERSION, MODEL_EXTENSION_KEYS, MODEL_FIELD_ORDER, PAGE_BODY_KINDS, PATH_PATTERNS, PLAN_BEHAVIOR_REASON, PLAN_STARTER_FEATURES, PLAN_TOKEN_ROLES, PLAN_VALUE_PATTERN, PROJECT_PLAN_FORMAT, RAW_MARK_SUFFIX, RESERVED_PATHS, RISK_CLASSES, RUN_STATUSES, SCHEDULE_KINDS, SECRET_PATTERNS, SEO_PROVIDERS, SLUG_PATTERN, SOURCE_ACCESS_LADDER, SOURCE_DELTA_OPS, TERMINAL_RUN_STATUSES, TEXT_CANDIDATE_KINDS, TEXT_EXCLUDE_REASONS, TITLE_FIELD_TYPES, approversFor, canonicalStringify, commentsExportSource, componentSlot, computePlanHash, conflictId, describeModelLocaleScope, detectSecrets, effectiveRisk, evaluateApproval, footerMenusOf, generateEntryId, highestRisk, isMediaType, isMigrateStudioClaim, isRepoRelativePath, isReservedPath, isStoredMediaPath, isTerminalRunStatus, isTitleFieldType, looksLikeCredential, orderedFieldNames, parseFrontmatterScalar, parseFrontmatterScalarString, parseMarkdownFrontmatter, planHashPayload, requiredApprovals, resolveFieldLabel, resolveModelLocales, rewriteEntryMedia, rewriteFieldMedia, rewriteMarkdownMedia, rewriteMediaUrl, riskRank, serializeMarkdownFrontmatter, sortKeys, splitFrontmatterList, stableHash, toDeliveryUrl, validateAccept, validateEntryId, validateFieldValue, validateHandoffCommentsExport, validateLocale, validateMigrateStudioClaim, validateModelLocales, validateProjectPlan, validateSemanticType, validateSlug };
|
|
2135
|
+
export { APPROVAL_GATES, APPROVAL_MODES, CANONICAL_JSON, CAPABILITY_KEYS, CHROME_BODY_SLOT, CHROME_COMPONENT_CLOSE, CHROME_COMPONENT_OPEN, CHROME_IF_CLOSE, CHROME_IF_OPEN, CHROME_REPEAT_CLOSE, CHROME_REPEAT_OPEN, COMMENTS_EXPORT_FORMAT, COMPONENT_TYPES, CONTENTRAIN_BRANCH, CONTENTRAIN_DIR, DEFAULT_APPROVAL_POLICY, DICTIONARY_TITLE_FIELD, ENTRY_ID_PATTERN, EXECUTION_CONTRACT_VERSION, INTEGRATION_CATEGORIES, INTEGRATION_EVIDENCE_KINDS, LEGACY_CSS_LAYER, LIST_ITEMS_SLOT, LOCALE_PATTERN, LOCAL_CAPABILITIES, MIGRATE_STUDIO_CLAIM_ALG, MIGRATE_STUDIO_CLAIM_AUDIENCE, MIGRATE_STUDIO_CLAIM_CLOCK_SKEW_SECONDS, MIGRATE_STUDIO_CLAIM_ISSUER, MIGRATE_STUDIO_CLAIM_MAX_TRIAL_DAYS, MIGRATE_STUDIO_CLAIM_MAX_TTL_SECONDS, MIGRATE_STUDIO_CLAIM_VERSION, MIGRATE_STUDIO_PLANS, MIGRATION_CONTRACT_VERSION, MODEL_EXTENSION_KEYS, MODEL_FIELD_ORDER, PAGE_BODY_KINDS, PATH_PATTERNS, PLAN_BEHAVIOR_REASON, PLAN_SECTION_RULE, PLAN_STARTER_FEATURES, PLAN_TOKEN_ROLES, PLAN_VALUE_PATTERN, PROJECT_PLAN_FORMAT, RAW_MARK_SUFFIX, RESERVED_PATHS, RISK_CLASSES, RUN_STATUSES, SCHEDULE_KINDS, SECRET_PATTERNS, SEO_PROVIDERS, SLUG_PATTERN, SOURCE_ACCESS_LADDER, SOURCE_DELTA_OPS, TERMINAL_RUN_STATUSES, TEXT_CANDIDATE_KINDS, TEXT_EXCLUDE_REASONS, TITLE_FIELD_TYPES, approversFor, canonicalStringify, commentsExportSource, componentSlot, computePlanHash, conflictId, describeModelLocaleScope, detectSecrets, effectiveRisk, evaluateApproval, fieldDepth, footerMenusOf, generateEntryId, highestRisk, isMediaType, isMigrateStudioClaim, isRepoRelativePath, isReservedPath, isStoredMediaPath, isTerminalRunStatus, isTitleFieldType, looksLikeCredential, orderedFieldNames, parseFrontmatterScalar, parseFrontmatterScalarString, parseMarkdownFrontmatter, planHashPayload, requiredApprovals, resolveFieldLabel, resolveModelLocales, rewriteEntryMedia, rewriteFieldMedia, rewriteMarkdownMedia, rewriteMediaUrl, riskRank, sectionFieldName, serializeMarkdownFrontmatter, sortKeys, splitFrontmatterList, stableHash, titleFieldTarget, titleFieldValue, toDeliveryUrl, validateAccept, validateEntryId, validateFieldValue, validateHandoffCommentsExport, validateLocale, validateMigrateStudioClaim, validateModelLocales, validateProjectPlan, validateSemanticType, validateSlug };
|
|
1990
2136
|
|
|
1991
2137
|
//# sourceMappingURL=index.mjs.map
|