@bettercms-ai/convert 0.3.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/dist/index.d.ts CHANGED
@@ -698,7 +698,7 @@ declare function attrsFor(path: string, kind: string, props?: AttrBinding[], sco
698
698
  declare function propsAttribute(props: AttrBinding[]): string;
699
699
 
700
700
  /** Bumped whenever the emitted source changes. `isKnownHelper` upgrades anything older. */
701
- declare const HELPER_VERSION = 3;
701
+ declare const HELPER_VERSION = 4;
702
702
  /** Where each dialect's helper lives. Null = this dialect reads nothing at build time. */
703
703
  declare const HELPER_PATH: Record<Dialect, string | null>;
704
704
  /** The directory the snapshots live in, at the repository root. */
@@ -979,6 +979,15 @@ interface ComponentizePlanSection {
979
979
  componentId?: string;
980
980
  proposedSlug?: string;
981
981
  };
982
+ /**
983
+ * WHERE THIS PLACEMENT'S COPY LIVES — Phase B's one new field.
984
+ *
985
+ * `"instance"` says the server moved the group's values onto the instance's `overrides`, so the
986
+ * placement carries no `bind` and its elements declare the BLOCK lane. ABSENT MEANS `"bind"`:
987
+ * a plan written by a Phase A server says nothing here, and a codemod that required the field
988
+ * would refuse every plan older than itself. @see readPlan
989
+ */
990
+ copy?: string;
982
991
  /** The SERVER already decided it cannot place this one. Not this codemod's to extract. */
983
992
  pending?: {
984
993
  reason?: string;
@@ -1024,10 +1033,21 @@ interface ComponentizePlan {
1024
1033
  * `DIALECT_UNSUPPORTED` the page is svelte / vue / html; nothing is written for it.
1025
1034
  * `HELPER_CONFLICT` `src/bcms-content.ts` is a module this package did not write.
1026
1035
  * `SNAPSHOT_INVALID` `bcms-content/<page>.json` is not JSON this can add `blocks` to.
1036
+ * `COPY_MODE_MISMATCH` `--copy instance` was asked of a plan whose placements are all
1037
+ * still bound to page field groups. @see ComponentizeOptions
1038
+ * `PROP_MAP_INCONSISTENT` the plan's `fields[].path` is not `<one prefix> + fields[].key`,
1039
+ * so a page path cannot be turned into a prop key losslessly.
1040
+ * `DUPLICATE_FIELD_BINDING` one element in the section carries more than one
1041
+ * `data-bcms-field`, and there is no single address to rewrite.
1042
+ * `INLINE_NEEDS_INSTANCE` the page cannot be looped, and the in-place call site the codemod
1043
+ * would write carries no `blockId`/`overrides` — so a placement
1044
+ * whose copy has MOVED could neither render nor address it.
1045
+ * `SECTION_UNMIGRATABLE` an OLDER generated component at this section's path cannot be
1046
+ * upgraded to the current format. @see migrateSections
1027
1047
  * `NOT_IN_SOURCE` no file we were given renders the group, or the route names no
1028
1048
  * page file this package can find.
1029
1049
  */
1030
- type SectionPendingReason = "SECTION_ROOT_AMBIGUOUS" | "SECTION_NOT_CONTIGUOUS" | "SECTION_FREE_IDENTIFIERS" | "COMPONENT_CONFLICT" | "REGISTRY_CONFLICT" | "REGISTRY_UNREADABLE" | "ROUTE_FILE_AMBIGUOUS" | "DIALECT_UNSUPPORTED" | "HELPER_CONFLICT" | "SNAPSHOT_INVALID" | "NOT_IN_SOURCE";
1050
+ type SectionPendingReason = "SECTION_ROOT_AMBIGUOUS" | "SECTION_NOT_CONTIGUOUS" | "SECTION_FREE_IDENTIFIERS" | "COMPONENT_CONFLICT" | "REGISTRY_CONFLICT" | "REGISTRY_UNREADABLE" | "ROUTE_FILE_AMBIGUOUS" | "DIALECT_UNSUPPORTED" | "HELPER_CONFLICT" | "SNAPSHOT_INVALID" | "COPY_MODE_MISMATCH" | "PROP_MAP_INCONSISTENT" | "DUPLICATE_FIELD_BINDING" | "INLINE_NEEDS_INSTANCE" | "SECTION_UNMIGRATABLE" | "NOT_IN_SOURCE";
1031
1051
  interface PendingSection {
1032
1052
  route: string;
1033
1053
  groupKey: string;
@@ -1070,6 +1090,15 @@ interface SectionsReceipt {
1070
1090
  interface ComponentizeReceipt {
1071
1091
  /** The plan this run was made against, carried so a receipt can be matched to one. */
1072
1092
  planDigest: string;
1093
+ /**
1094
+ * Which copy model this run was asked for — the same word the server's receipt carries.
1095
+ *
1096
+ * It does NOT change the bytes of an extracted component: the lane an element declares is
1097
+ * decided at render time from the placement's own props, so one file serves both. What it
1098
+ * changes is what the run will accept — `"instance"` against a plan that moved no copy is
1099
+ * `COPY_MODE_MISMATCH` — and what the registry's shipped fallback binds. @see bcmsFields
1100
+ */
1101
+ copy: "bind" | "instance";
1073
1102
  sections: SectionsReceipt;
1074
1103
  /** The component slugs this run wrote a file for, sorted. */
1075
1104
  components: string[];
@@ -1106,9 +1135,27 @@ declare function assertSections(total: number, sections: SectionsReceipt): Secti
1106
1135
  interface ComponentizeOptions {
1107
1136
  /** Replace a helper module this package did not write, instead of refusing. The CLI's flag. */
1108
1137
  overwriteHelper?: boolean;
1138
+ /**
1139
+ * WHICH COPY MODEL THE OPERATOR MEANT — `"bind"` (Phase A, the default) or `"instance"`.
1140
+ *
1141
+ * 🔴 AN ASSERTION, NOT A SWITCH. The extracted files are identical either way, so this flag
1142
+ * exists to catch the order-of-operations mistake that would otherwise be silent: running
1143
+ * `--copy instance` in the repository BEFORE the server has moved the copy leaves a tree that
1144
+ * looks converted and renders every section out of page fields the dashboard is about to hide.
1145
+ * A plan whose placements are all still bound says so, and the run refuses by name.
1146
+ */
1147
+ copy?: "bind" | "instance";
1109
1148
  }
1110
- /** The marker that says a file is OURS. Idempotence is decided on it, never on a path. */
1111
- declare const SECTION_MARKER = "// @bettercms-ai/convert section v1";
1149
+ /**
1150
+ * The marker that says a file is OURS — and WHICH FORMAT it is in.
1151
+ *
1152
+ * 🔴 THE VERSION IS LOAD-BEARING, NOT DECORATION. Idempotence is decided on this marker, so a v1
1153
+ * component (0.3: page-path bindings, no render-time lane) read as "already ours, nothing to do"
1154
+ * was skipped forever — every repository converted before Phase B stayed on the page lane, and
1155
+ * `--copy instance` there reported five sections done and moved no address at all. A format change
1156
+ * bumps the version, and anything older is MIGRATED before it is called done. @see migrateSections
1157
+ */
1158
+ declare const SECTION_MARKER = "// @bettercms-ai/convert section v2";
1112
1159
  /** The same, for the two modules that hold the registry rather than a section. */
1113
1160
  declare const REGISTRY_MARKER = "// @bettercms-ai/convert sections v1";
1114
1161
  /** Where the generated components live. Fixed, so a second run knows its own output on sight. */