@valbuild/core 0.105.0 → 0.105.1

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.
@@ -16,7 +16,61 @@ export type ExtractedValModules = {
16
16
  sourcesSha: string;
17
17
  configSha: string;
18
18
  moduleErrors: ExtractedModuleError[];
19
+ /**
20
+ * What the SHAs above are a fold over, in order.
21
+ *
22
+ * Kept so they can be recomputed from a source that did NOT come from
23
+ * evaluating the modules — see {@link computeValModuleShas}. A record keyed by
24
+ * path could not do this: the fold is order-dependent, and the order is
25
+ * `val.modules`, which a record does not promise to preserve.
26
+ */
27
+ shaEntries: ValModuleShaEntry[];
19
28
  };
29
+ /**
30
+ * One module's contribution to the SHAs, in fold order.
31
+ *
32
+ * The SHAs are a FOLD, not a hash of a set: each module is mixed into the
33
+ * running value in `val.modules` order, so reproducing one means replaying the
34
+ * same modules with the same inputs in the same order. That is what this type
35
+ * is for — see {@link computeValModuleShas}.
36
+ */
37
+ export type ValModuleShaEntry = {
38
+ path: ModuleFilePath;
39
+ source: Source;
40
+ serializedSchema: SerializedSchema;
41
+ /**
42
+ * How many module errors had been collected when this module was folded in.
43
+ *
44
+ * The base SHA mixes in the error array as it stood at each step, so a module
45
+ * that failed to load changes the hash of every module folded in AFTER it and
46
+ * of none before. Errors are only ever appended, so the state at step _i_ is
47
+ * the final array's first `moduleErrorsAt` entries — one number is enough to
48
+ * reproduce it exactly, and a per-step copy is not needed.
49
+ */
50
+ moduleErrorsAt: number;
51
+ };
52
+ export type ValModuleShas = {
53
+ baseSha: string;
54
+ schemaSha: string;
55
+ sourcesSha: string;
56
+ configSha: string;
57
+ };
58
+ /**
59
+ * The SHAs, from the entries they are a fold over.
60
+ *
61
+ * Split out from {@link extractValModules} because there are two ways to arrive
62
+ * at a set of sources. Extraction evaluates the modules; the server also
63
+ * PROMOTES the sources it has just written to disk, because re-evaluating gets
64
+ * it nothing — a module `def` is the app's own `import()`, which resolves from
65
+ * the module registry rather than from the file that was just rewritten. Both
66
+ * have to produce SHAs the other side can compare, so the fold has one
67
+ * implementation and both call it.
68
+ *
69
+ * Feeding back the entries a previous fold used, unchanged, reproduces its SHAs
70
+ * exactly. That is the property the promotion relies on: only the modules whose
71
+ * source actually moved change anything.
72
+ */
73
+ export declare function computeValModuleShas(config: ValModules["config"], entries: readonly ValModuleShaEntry[], moduleErrors: readonly ExtractedModuleError[]): ValModuleShas;
20
74
  /**
21
75
  * Extracts schemas and sources from a ValModules registry and computes the
22
76
  * deterministic SHAs that the server and client both use to detect changes.
@@ -1,6 +1,6 @@
1
1
  export { initVal, type ConfigDirectory } from "./initVal.js";
2
2
  export { modules, type ValModules } from "./modules.js";
3
- export { extractValModules, type ExtractedValModules, type ExtractedModuleError, } from "./extractValModules.js";
3
+ export { extractValModules, computeValModuleShas, type ExtractedValModules, type ValModuleShaEntry, type ValModuleShas, type ExtractedModuleError, } from "./extractValModules.js";
4
4
  export type { InitVal, ValConfig, ValConstructor, ContentConstructor, } from "./initVal.js";
5
5
  export { Schema, type SerializedSchema, type SelectorOfSchema } from "./schema/index.js";
6
6
  export { hasRemoteFileSchema } from "./schema/hasRemoteFileSchema.js";
@@ -6808,6 +6808,84 @@ function collectObjectRecursive(item, collector) {
6808
6808
  }
6809
6809
  }
6810
6810
 
6811
+ /**
6812
+ * One module's contribution to the SHAs, in fold order.
6813
+ *
6814
+ * The SHAs are a FOLD, not a hash of a set: each module is mixed into the
6815
+ * running value in `val.modules` order, so reproducing one means replaying the
6816
+ * same modules with the same inputs in the same order. That is what this type
6817
+ * is for — see {@link computeValModuleShas}.
6818
+ */
6819
+
6820
+ /**
6821
+ * The SHAs, from the entries they are a fold over.
6822
+ *
6823
+ * Split out from {@link extractValModules} because there are two ways to arrive
6824
+ * at a set of sources. Extraction evaluates the modules; the server also
6825
+ * PROMOTES the sources it has just written to disk, because re-evaluating gets
6826
+ * it nothing — a module `def` is the app's own `import()`, which resolves from
6827
+ * the module registry rather than from the file that was just rewritten. Both
6828
+ * have to produce SHAs the other side can compare, so the fold has one
6829
+ * implementation and both call it.
6830
+ *
6831
+ * Feeding back the entries a previous fold used, unchanged, reproduces its SHAs
6832
+ * exactly. That is the property the promotion relies on: only the modules whose
6833
+ * source actually moved change anything.
6834
+ */
6835
+ function computeValModuleShas(config, entries, moduleErrors) {
6836
+ var configSha = hash(JSON.stringify(config));
6837
+ var sourcesSha = "";
6838
+ var baseSha = configSha;
6839
+ // NOTE: schemaSha is deliberately NOT seeded with configSha. It is compared
6840
+ // across bundles (the server extracts from the Node bundle, the editor SPA
6841
+ // from the browser bundle) to detect that a new version has been deployed.
6842
+ // The config contains values that are not part of the schema and that differ
6843
+ // between those two bundles - most notably the documented
6844
+ // `gitCommit: process.env.VERCEL_GIT_COMMIT_SHA` / `gitBranch`, which are
6845
+ // server-only env vars and therefore `undefined` in the browser. Seeding with
6846
+ // them made the two sides disagree on every production load.
6847
+ var schemaSha = "";
6848
+ var _iterator = _createForOfIteratorHelper(entries),
6849
+ _step;
6850
+ try {
6851
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
6852
+ var entry = _step.value;
6853
+ var path = entry.path,
6854
+ source = entry.source,
6855
+ serializedSchema = entry.serializedSchema;
6856
+ sourcesSha = hash(sourcesSha + JSON.stringify({
6857
+ path: path,
6858
+ source: source
6859
+ }));
6860
+ baseSha = hash(baseSha + JSON.stringify({
6861
+ path: path,
6862
+ schema: serializedSchema,
6863
+ source: source,
6864
+ modulesErrors: moduleErrors.slice(0, entry.moduleErrorsAt)
6865
+ }));
6866
+ // The PATH is part of the schema set, not just the schema: renaming a
6867
+ // module while leaving its schema byte-identical still changes which paths
6868
+ // exist, and an open client keyed its schema cache by the old path. Hashing
6869
+ // the schema alone left this SHA unchanged, so with no commitSha to fall
6870
+ // back on the client never refetched /schema.
6871
+ schemaSha = hash(schemaSha + JSON.stringify({
6872
+ path: path,
6873
+ schema: serializedSchema
6874
+ }));
6875
+ }
6876
+ } catch (err) {
6877
+ _iterator.e(err);
6878
+ } finally {
6879
+ _iterator.f();
6880
+ }
6881
+ return {
6882
+ baseSha: baseSha,
6883
+ schemaSha: schemaSha,
6884
+ sourcesSha: sourcesSha,
6885
+ configSha: configSha
6886
+ };
6887
+ }
6888
+
6811
6889
  /**
6812
6890
  * Extracts schemas and sources from a ValModules registry and computes the
6813
6891
  * deterministic SHAs that the server and client both use to detect changes.
@@ -6820,7 +6898,7 @@ function extractValModules(_x) {
6820
6898
  }
6821
6899
  function _extractValModules() {
6822
6900
  _extractValModules = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(valModules) {
6823
- var moduleErrors, addModuleError, sources, schemas, serializedSchemas, configSha, sourcesSha, baseSha, schemaSha, moduleIdx, module, at, value, path, schema, source, serializedSchema, pathM, _t, _t2;
6901
+ var moduleErrors, addModuleError, sources, schemas, serializedSchemas, shaEntries, moduleIdx, module, at, value, path, schema, source, serializedSchema, pathM, _t, _t2;
6824
6902
  return _regenerator().w(function (_context) {
6825
6903
  while (1) switch (_context.p = _context.n) {
6826
6904
  case 0:
@@ -6835,17 +6913,15 @@ function _extractValModules() {
6835
6913
  sources = {};
6836
6914
  schemas = {};
6837
6915
  serializedSchemas = {};
6838
- configSha = hash(JSON.stringify(valModules.config));
6839
- sourcesSha = "";
6840
- baseSha = configSha; // NOTE: schemaSha is deliberately NOT seeded with configSha. It is compared
6841
- // across bundles (the server extracts from the Node bundle, the editor SPA
6842
- // from the browser bundle) to detect that a new version has been deployed.
6843
- // The config contains values that are not part of the schema and that differ
6844
- // between those two bundles - most notably the documented
6845
- // `gitCommit: process.env.VERCEL_GIT_COMMIT_SHA` / `gitBranch`, which are
6846
- // server-only env vars and therefore `undefined` in the browser. Seeding with
6847
- // them made the two sides disagree on every production load.
6848
- schemaSha = "";
6916
+ /**
6917
+ * What the fold below runs over, collected here rather than hashed inline.
6918
+ *
6919
+ * The hashing itself moved to `computeValModuleShas`, so the server can
6920
+ * recompute these SHAs for sources it did not get by evaluating the modules.
6921
+ * Collected in loop order, which is `val.modules` order, which is the order
6922
+ * the fold is defined by.
6923
+ */
6924
+ shaEntries = [];
6849
6925
  moduleIdx = 0;
6850
6926
  case 1:
6851
6927
  if (!(moduleIdx < valModules.modules.length)) {
@@ -6948,40 +7024,27 @@ function _extractValModules() {
6948
7024
  sources[pathM] = source;
6949
7025
  schemas[pathM] = schema;
6950
7026
  serializedSchemas[pathM] = serializedSchema;
6951
- sourcesSha = hash(sourcesSha + JSON.stringify({
6952
- path: path,
6953
- source: source
6954
- }));
6955
- baseSha = hash(baseSha + JSON.stringify({
6956
- path: path,
6957
- schema: serializedSchema,
7027
+ shaEntries.push({
7028
+ path: pathM,
6958
7029
  source: source,
6959
- modulesErrors: moduleErrors
6960
- }));
6961
- // The PATH is part of the schema set, not just the schema: renaming a
6962
- // module while leaving its schema byte-identical still changes which paths
6963
- // exist, and an open client keyed its schema cache by the old path. Hashing
6964
- // the schema alone left this SHA unchanged, so with no commitSha to fall
6965
- // back on the client never refetched /schema.
6966
- schemaSha = hash(schemaSha + JSON.stringify({
6967
- path: path,
6968
- schema: serializedSchema
6969
- }));
7030
+ serializedSchema: serializedSchema,
7031
+ // The errors so far, which is what the base SHA used to mix in by hashing
7032
+ // the live array at this point in the loop. See `moduleErrorsAt`.
7033
+ moduleErrorsAt: moduleErrors.length
7034
+ });
6970
7035
  case 17:
6971
7036
  moduleIdx++;
6972
7037
  _context.n = 1;
6973
7038
  break;
6974
7039
  case 18:
6975
- return _context.a(2, {
7040
+ return _context.a(2, _objectSpread2(_objectSpread2({
6976
7041
  sources: sources,
6977
7042
  schemas: schemas,
6978
- serializedSchemas: serializedSchemas,
6979
- baseSha: baseSha,
6980
- schemaSha: schemaSha,
6981
- sourcesSha: sourcesSha,
6982
- configSha: configSha,
6983
- moduleErrors: moduleErrors
6984
- });
7043
+ serializedSchemas: serializedSchemas
7044
+ }, computeValModuleShas(valModules.config, shaEntries, moduleErrors)), {}, {
7045
+ moduleErrors: moduleErrors,
7046
+ shaEntries: shaEntries
7047
+ }));
6985
7048
  }
6986
7049
  }, _callee, null, [[14, 15], [4, 6]]);
6987
7050
  }));
@@ -8590,4 +8653,4 @@ function tryJsonParse(str) {
8590
8653
  }
8591
8654
  }
8592
8655
 
8593
- export { ArraySchema as A, BooleanSchema as B, ColorSchema as C, DEFAULT_CONTENT_HOST as D, FATAL_ERROR_TYPES as F, GenericSelector as G, Internal as I, KeyOfSchema as K, LiteralSchema as L, ModuleFilePathSep as M, NumberSchema as N, ObjectSchema as O, PatchError as P, RecordSchema as R, Schema as S, UnionSchema as U, VAL_EXTENSION as V, _typeof as _, _slicedToArray as a, _createClass as b, _classCallCheck as c, _toConsumableArray as d, DEFAULT_APP_HOST as e, extractValModules as f, DEFAULT_VAL_REMOTE_HOST as g, hasRemoteFileSchema as h, initVal as i, derefPatch as j, StringSchema as k, ImageSchema as l, modules as m, FileSchema as n, DateSchema as o, COLOR_FORMATS as p, DEFAULT_COLOR_FORMAT as q, DateTimeSchema as r, splitModuleFilePathAndModulePath as s, RouteSchema as t, RichTextSchema as u, deserializeSchema as v, previewScope as w, CODE_LANGUAGES as x, getSourcePathFromRoute as y };
8656
+ export { ArraySchema as A, BooleanSchema as B, ColorSchema as C, DEFAULT_CONTENT_HOST as D, FATAL_ERROR_TYPES as F, GenericSelector as G, Internal as I, KeyOfSchema as K, LiteralSchema as L, ModuleFilePathSep as M, NumberSchema as N, ObjectSchema as O, PatchError as P, RecordSchema as R, Schema as S, UnionSchema as U, VAL_EXTENSION as V, _typeof as _, _slicedToArray as a, _createClass as b, _classCallCheck as c, _toConsumableArray as d, DEFAULT_APP_HOST as e, extractValModules as f, computeValModuleShas as g, hasRemoteFileSchema as h, initVal as i, DEFAULT_VAL_REMOTE_HOST as j, derefPatch as k, StringSchema as l, modules as m, ImageSchema as n, FileSchema as o, DateSchema as p, COLOR_FORMATS as q, DEFAULT_COLOR_FORMAT as r, splitModuleFilePathAndModulePath as s, DateTimeSchema as t, RouteSchema as u, RichTextSchema as v, deserializeSchema as w, previewScope as x, CODE_LANGUAGES as y, getSourcePathFromRoute as z };
@@ -6810,6 +6810,84 @@ function collectObjectRecursive(item, collector) {
6810
6810
  }
6811
6811
  }
6812
6812
 
6813
+ /**
6814
+ * One module's contribution to the SHAs, in fold order.
6815
+ *
6816
+ * The SHAs are a FOLD, not a hash of a set: each module is mixed into the
6817
+ * running value in `val.modules` order, so reproducing one means replaying the
6818
+ * same modules with the same inputs in the same order. That is what this type
6819
+ * is for — see {@link computeValModuleShas}.
6820
+ */
6821
+
6822
+ /**
6823
+ * The SHAs, from the entries they are a fold over.
6824
+ *
6825
+ * Split out from {@link extractValModules} because there are two ways to arrive
6826
+ * at a set of sources. Extraction evaluates the modules; the server also
6827
+ * PROMOTES the sources it has just written to disk, because re-evaluating gets
6828
+ * it nothing — a module `def` is the app's own `import()`, which resolves from
6829
+ * the module registry rather than from the file that was just rewritten. Both
6830
+ * have to produce SHAs the other side can compare, so the fold has one
6831
+ * implementation and both call it.
6832
+ *
6833
+ * Feeding back the entries a previous fold used, unchanged, reproduces its SHAs
6834
+ * exactly. That is the property the promotion relies on: only the modules whose
6835
+ * source actually moved change anything.
6836
+ */
6837
+ function computeValModuleShas(config, entries, moduleErrors) {
6838
+ var configSha = hash(JSON.stringify(config));
6839
+ var sourcesSha = "";
6840
+ var baseSha = configSha;
6841
+ // NOTE: schemaSha is deliberately NOT seeded with configSha. It is compared
6842
+ // across bundles (the server extracts from the Node bundle, the editor SPA
6843
+ // from the browser bundle) to detect that a new version has been deployed.
6844
+ // The config contains values that are not part of the schema and that differ
6845
+ // between those two bundles - most notably the documented
6846
+ // `gitCommit: process.env.VERCEL_GIT_COMMIT_SHA` / `gitBranch`, which are
6847
+ // server-only env vars and therefore `undefined` in the browser. Seeding with
6848
+ // them made the two sides disagree on every production load.
6849
+ var schemaSha = "";
6850
+ var _iterator = result._createForOfIteratorHelper(entries),
6851
+ _step;
6852
+ try {
6853
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
6854
+ var entry = _step.value;
6855
+ var path = entry.path,
6856
+ source = entry.source,
6857
+ serializedSchema = entry.serializedSchema;
6858
+ sourcesSha = hash(sourcesSha + JSON.stringify({
6859
+ path: path,
6860
+ source: source
6861
+ }));
6862
+ baseSha = hash(baseSha + JSON.stringify({
6863
+ path: path,
6864
+ schema: serializedSchema,
6865
+ source: source,
6866
+ modulesErrors: moduleErrors.slice(0, entry.moduleErrorsAt)
6867
+ }));
6868
+ // The PATH is part of the schema set, not just the schema: renaming a
6869
+ // module while leaving its schema byte-identical still changes which paths
6870
+ // exist, and an open client keyed its schema cache by the old path. Hashing
6871
+ // the schema alone left this SHA unchanged, so with no commitSha to fall
6872
+ // back on the client never refetched /schema.
6873
+ schemaSha = hash(schemaSha + JSON.stringify({
6874
+ path: path,
6875
+ schema: serializedSchema
6876
+ }));
6877
+ }
6878
+ } catch (err) {
6879
+ _iterator.e(err);
6880
+ } finally {
6881
+ _iterator.f();
6882
+ }
6883
+ return {
6884
+ baseSha: baseSha,
6885
+ schemaSha: schemaSha,
6886
+ sourcesSha: sourcesSha,
6887
+ configSha: configSha
6888
+ };
6889
+ }
6890
+
6813
6891
  /**
6814
6892
  * Extracts schemas and sources from a ValModules registry and computes the
6815
6893
  * deterministic SHAs that the server and client both use to detect changes.
@@ -6822,7 +6900,7 @@ function extractValModules(_x) {
6822
6900
  }
6823
6901
  function _extractValModules() {
6824
6902
  _extractValModules = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(valModules) {
6825
- var moduleErrors, addModuleError, sources, schemas, serializedSchemas, configSha, sourcesSha, baseSha, schemaSha, moduleIdx, module, at, value, path, schema, source, serializedSchema, pathM, _t, _t2;
6903
+ var moduleErrors, addModuleError, sources, schemas, serializedSchemas, shaEntries, moduleIdx, module, at, value, path, schema, source, serializedSchema, pathM, _t, _t2;
6826
6904
  return _regenerator().w(function (_context) {
6827
6905
  while (1) switch (_context.p = _context.n) {
6828
6906
  case 0:
@@ -6837,17 +6915,15 @@ function _extractValModules() {
6837
6915
  sources = {};
6838
6916
  schemas = {};
6839
6917
  serializedSchemas = {};
6840
- configSha = hash(JSON.stringify(valModules.config));
6841
- sourcesSha = "";
6842
- baseSha = configSha; // NOTE: schemaSha is deliberately NOT seeded with configSha. It is compared
6843
- // across bundles (the server extracts from the Node bundle, the editor SPA
6844
- // from the browser bundle) to detect that a new version has been deployed.
6845
- // The config contains values that are not part of the schema and that differ
6846
- // between those two bundles - most notably the documented
6847
- // `gitCommit: process.env.VERCEL_GIT_COMMIT_SHA` / `gitBranch`, which are
6848
- // server-only env vars and therefore `undefined` in the browser. Seeding with
6849
- // them made the two sides disagree on every production load.
6850
- schemaSha = "";
6918
+ /**
6919
+ * What the fold below runs over, collected here rather than hashed inline.
6920
+ *
6921
+ * The hashing itself moved to `computeValModuleShas`, so the server can
6922
+ * recompute these SHAs for sources it did not get by evaluating the modules.
6923
+ * Collected in loop order, which is `val.modules` order, which is the order
6924
+ * the fold is defined by.
6925
+ */
6926
+ shaEntries = [];
6851
6927
  moduleIdx = 0;
6852
6928
  case 1:
6853
6929
  if (!(moduleIdx < valModules.modules.length)) {
@@ -6950,40 +7026,27 @@ function _extractValModules() {
6950
7026
  sources[pathM] = source;
6951
7027
  schemas[pathM] = schema;
6952
7028
  serializedSchemas[pathM] = serializedSchema;
6953
- sourcesSha = hash(sourcesSha + JSON.stringify({
6954
- path: path,
6955
- source: source
6956
- }));
6957
- baseSha = hash(baseSha + JSON.stringify({
6958
- path: path,
6959
- schema: serializedSchema,
7029
+ shaEntries.push({
7030
+ path: pathM,
6960
7031
  source: source,
6961
- modulesErrors: moduleErrors
6962
- }));
6963
- // The PATH is part of the schema set, not just the schema: renaming a
6964
- // module while leaving its schema byte-identical still changes which paths
6965
- // exist, and an open client keyed its schema cache by the old path. Hashing
6966
- // the schema alone left this SHA unchanged, so with no commitSha to fall
6967
- // back on the client never refetched /schema.
6968
- schemaSha = hash(schemaSha + JSON.stringify({
6969
- path: path,
6970
- schema: serializedSchema
6971
- }));
7032
+ serializedSchema: serializedSchema,
7033
+ // The errors so far, which is what the base SHA used to mix in by hashing
7034
+ // the live array at this point in the loop. See `moduleErrorsAt`.
7035
+ moduleErrorsAt: moduleErrors.length
7036
+ });
6972
7037
  case 17:
6973
7038
  moduleIdx++;
6974
7039
  _context.n = 1;
6975
7040
  break;
6976
7041
  case 18:
6977
- return _context.a(2, {
7042
+ return _context.a(2, _objectSpread2(_objectSpread2({
6978
7043
  sources: sources,
6979
7044
  schemas: schemas,
6980
- serializedSchemas: serializedSchemas,
6981
- baseSha: baseSha,
6982
- schemaSha: schemaSha,
6983
- sourcesSha: sourcesSha,
6984
- configSha: configSha,
6985
- moduleErrors: moduleErrors
6986
- });
7045
+ serializedSchemas: serializedSchemas
7046
+ }, computeValModuleShas(valModules.config, shaEntries, moduleErrors)), {}, {
7047
+ moduleErrors: moduleErrors,
7048
+ shaEntries: shaEntries
7049
+ }));
6987
7050
  }
6988
7051
  }, _callee, null, [[14, 15], [4, 6]]);
6989
7052
  }));
@@ -8626,6 +8689,7 @@ exports._createClass = _createClass;
8626
8689
  exports._slicedToArray = _slicedToArray;
8627
8690
  exports._toConsumableArray = _toConsumableArray;
8628
8691
  exports._typeof = _typeof;
8692
+ exports.computeValModuleShas = computeValModuleShas;
8629
8693
  exports.derefPatch = derefPatch;
8630
8694
  exports.deserializeSchema = deserializeSchema;
8631
8695
  exports.extractValModules = extractValModules;
@@ -6810,6 +6810,84 @@ function collectObjectRecursive(item, collector) {
6810
6810
  }
6811
6811
  }
6812
6812
 
6813
+ /**
6814
+ * One module's contribution to the SHAs, in fold order.
6815
+ *
6816
+ * The SHAs are a FOLD, not a hash of a set: each module is mixed into the
6817
+ * running value in `val.modules` order, so reproducing one means replaying the
6818
+ * same modules with the same inputs in the same order. That is what this type
6819
+ * is for — see {@link computeValModuleShas}.
6820
+ */
6821
+
6822
+ /**
6823
+ * The SHAs, from the entries they are a fold over.
6824
+ *
6825
+ * Split out from {@link extractValModules} because there are two ways to arrive
6826
+ * at a set of sources. Extraction evaluates the modules; the server also
6827
+ * PROMOTES the sources it has just written to disk, because re-evaluating gets
6828
+ * it nothing — a module `def` is the app's own `import()`, which resolves from
6829
+ * the module registry rather than from the file that was just rewritten. Both
6830
+ * have to produce SHAs the other side can compare, so the fold has one
6831
+ * implementation and both call it.
6832
+ *
6833
+ * Feeding back the entries a previous fold used, unchanged, reproduces its SHAs
6834
+ * exactly. That is the property the promotion relies on: only the modules whose
6835
+ * source actually moved change anything.
6836
+ */
6837
+ function computeValModuleShas(config, entries, moduleErrors) {
6838
+ var configSha = hash(JSON.stringify(config));
6839
+ var sourcesSha = "";
6840
+ var baseSha = configSha;
6841
+ // NOTE: schemaSha is deliberately NOT seeded with configSha. It is compared
6842
+ // across bundles (the server extracts from the Node bundle, the editor SPA
6843
+ // from the browser bundle) to detect that a new version has been deployed.
6844
+ // The config contains values that are not part of the schema and that differ
6845
+ // between those two bundles - most notably the documented
6846
+ // `gitCommit: process.env.VERCEL_GIT_COMMIT_SHA` / `gitBranch`, which are
6847
+ // server-only env vars and therefore `undefined` in the browser. Seeding with
6848
+ // them made the two sides disagree on every production load.
6849
+ var schemaSha = "";
6850
+ var _iterator = result._createForOfIteratorHelper(entries),
6851
+ _step;
6852
+ try {
6853
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
6854
+ var entry = _step.value;
6855
+ var path = entry.path,
6856
+ source = entry.source,
6857
+ serializedSchema = entry.serializedSchema;
6858
+ sourcesSha = hash(sourcesSha + JSON.stringify({
6859
+ path: path,
6860
+ source: source
6861
+ }));
6862
+ baseSha = hash(baseSha + JSON.stringify({
6863
+ path: path,
6864
+ schema: serializedSchema,
6865
+ source: source,
6866
+ modulesErrors: moduleErrors.slice(0, entry.moduleErrorsAt)
6867
+ }));
6868
+ // The PATH is part of the schema set, not just the schema: renaming a
6869
+ // module while leaving its schema byte-identical still changes which paths
6870
+ // exist, and an open client keyed its schema cache by the old path. Hashing
6871
+ // the schema alone left this SHA unchanged, so with no commitSha to fall
6872
+ // back on the client never refetched /schema.
6873
+ schemaSha = hash(schemaSha + JSON.stringify({
6874
+ path: path,
6875
+ schema: serializedSchema
6876
+ }));
6877
+ }
6878
+ } catch (err) {
6879
+ _iterator.e(err);
6880
+ } finally {
6881
+ _iterator.f();
6882
+ }
6883
+ return {
6884
+ baseSha: baseSha,
6885
+ schemaSha: schemaSha,
6886
+ sourcesSha: sourcesSha,
6887
+ configSha: configSha
6888
+ };
6889
+ }
6890
+
6813
6891
  /**
6814
6892
  * Extracts schemas and sources from a ValModules registry and computes the
6815
6893
  * deterministic SHAs that the server and client both use to detect changes.
@@ -6822,7 +6900,7 @@ function extractValModules(_x) {
6822
6900
  }
6823
6901
  function _extractValModules() {
6824
6902
  _extractValModules = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(valModules) {
6825
- var moduleErrors, addModuleError, sources, schemas, serializedSchemas, configSha, sourcesSha, baseSha, schemaSha, moduleIdx, module, at, value, path, schema, source, serializedSchema, pathM, _t, _t2;
6903
+ var moduleErrors, addModuleError, sources, schemas, serializedSchemas, shaEntries, moduleIdx, module, at, value, path, schema, source, serializedSchema, pathM, _t, _t2;
6826
6904
  return _regenerator().w(function (_context) {
6827
6905
  while (1) switch (_context.p = _context.n) {
6828
6906
  case 0:
@@ -6837,17 +6915,15 @@ function _extractValModules() {
6837
6915
  sources = {};
6838
6916
  schemas = {};
6839
6917
  serializedSchemas = {};
6840
- configSha = hash(JSON.stringify(valModules.config));
6841
- sourcesSha = "";
6842
- baseSha = configSha; // NOTE: schemaSha is deliberately NOT seeded with configSha. It is compared
6843
- // across bundles (the server extracts from the Node bundle, the editor SPA
6844
- // from the browser bundle) to detect that a new version has been deployed.
6845
- // The config contains values that are not part of the schema and that differ
6846
- // between those two bundles - most notably the documented
6847
- // `gitCommit: process.env.VERCEL_GIT_COMMIT_SHA` / `gitBranch`, which are
6848
- // server-only env vars and therefore `undefined` in the browser. Seeding with
6849
- // them made the two sides disagree on every production load.
6850
- schemaSha = "";
6918
+ /**
6919
+ * What the fold below runs over, collected here rather than hashed inline.
6920
+ *
6921
+ * The hashing itself moved to `computeValModuleShas`, so the server can
6922
+ * recompute these SHAs for sources it did not get by evaluating the modules.
6923
+ * Collected in loop order, which is `val.modules` order, which is the order
6924
+ * the fold is defined by.
6925
+ */
6926
+ shaEntries = [];
6851
6927
  moduleIdx = 0;
6852
6928
  case 1:
6853
6929
  if (!(moduleIdx < valModules.modules.length)) {
@@ -6950,40 +7026,27 @@ function _extractValModules() {
6950
7026
  sources[pathM] = source;
6951
7027
  schemas[pathM] = schema;
6952
7028
  serializedSchemas[pathM] = serializedSchema;
6953
- sourcesSha = hash(sourcesSha + JSON.stringify({
6954
- path: path,
6955
- source: source
6956
- }));
6957
- baseSha = hash(baseSha + JSON.stringify({
6958
- path: path,
6959
- schema: serializedSchema,
7029
+ shaEntries.push({
7030
+ path: pathM,
6960
7031
  source: source,
6961
- modulesErrors: moduleErrors
6962
- }));
6963
- // The PATH is part of the schema set, not just the schema: renaming a
6964
- // module while leaving its schema byte-identical still changes which paths
6965
- // exist, and an open client keyed its schema cache by the old path. Hashing
6966
- // the schema alone left this SHA unchanged, so with no commitSha to fall
6967
- // back on the client never refetched /schema.
6968
- schemaSha = hash(schemaSha + JSON.stringify({
6969
- path: path,
6970
- schema: serializedSchema
6971
- }));
7032
+ serializedSchema: serializedSchema,
7033
+ // The errors so far, which is what the base SHA used to mix in by hashing
7034
+ // the live array at this point in the loop. See `moduleErrorsAt`.
7035
+ moduleErrorsAt: moduleErrors.length
7036
+ });
6972
7037
  case 17:
6973
7038
  moduleIdx++;
6974
7039
  _context.n = 1;
6975
7040
  break;
6976
7041
  case 18:
6977
- return _context.a(2, {
7042
+ return _context.a(2, _objectSpread2(_objectSpread2({
6978
7043
  sources: sources,
6979
7044
  schemas: schemas,
6980
- serializedSchemas: serializedSchemas,
6981
- baseSha: baseSha,
6982
- schemaSha: schemaSha,
6983
- sourcesSha: sourcesSha,
6984
- configSha: configSha,
6985
- moduleErrors: moduleErrors
6986
- });
7045
+ serializedSchemas: serializedSchemas
7046
+ }, computeValModuleShas(valModules.config, shaEntries, moduleErrors)), {}, {
7047
+ moduleErrors: moduleErrors,
7048
+ shaEntries: shaEntries
7049
+ }));
6987
7050
  }
6988
7051
  }, _callee, null, [[14, 15], [4, 6]]);
6989
7052
  }));
@@ -8626,6 +8689,7 @@ exports._createClass = _createClass;
8626
8689
  exports._slicedToArray = _slicedToArray;
8627
8690
  exports._toConsumableArray = _toConsumableArray;
8628
8691
  exports._typeof = _typeof;
8692
+ exports.computeValModuleShas = computeValModuleShas;
8629
8693
  exports.derefPatch = derefPatch;
8630
8694
  exports.deserializeSchema = deserializeSchema;
8631
8695
  exports.extractValModules = extractValModules;
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var dist_valbuildCore = require('./index-730a5254.cjs.dev.js');
5
+ var dist_valbuildCore = require('./index-baa3109b.cjs.dev.js');
6
6
  require('./result-bb1f436e.cjs.dev.js');
7
7
 
8
8
 
@@ -35,6 +35,7 @@ exports.Schema = dist_valbuildCore.Schema;
35
35
  exports.StringSchema = dist_valbuildCore.StringSchema;
36
36
  exports.UnionSchema = dist_valbuildCore.UnionSchema;
37
37
  exports.VAL_EXTENSION = dist_valbuildCore.VAL_EXTENSION;
38
+ exports.computeValModuleShas = dist_valbuildCore.computeValModuleShas;
38
39
  exports.derefPatch = dist_valbuildCore.derefPatch;
39
40
  exports.deserializeSchema = dist_valbuildCore.deserializeSchema;
40
41
  exports.extractValModules = dist_valbuildCore.extractValModules;
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var dist_valbuildCore = require('./index-e990b6ad.cjs.prod.js');
5
+ var dist_valbuildCore = require('./index-4013c9f8.cjs.prod.js');
6
6
  require('./result-787e35f6.cjs.prod.js');
7
7
 
8
8
 
@@ -35,6 +35,7 @@ exports.Schema = dist_valbuildCore.Schema;
35
35
  exports.StringSchema = dist_valbuildCore.StringSchema;
36
36
  exports.UnionSchema = dist_valbuildCore.UnionSchema;
37
37
  exports.VAL_EXTENSION = dist_valbuildCore.VAL_EXTENSION;
38
+ exports.computeValModuleShas = dist_valbuildCore.computeValModuleShas;
38
39
  exports.derefPatch = dist_valbuildCore.derefPatch;
39
40
  exports.deserializeSchema = dist_valbuildCore.deserializeSchema;
40
41
  exports.extractValModules = dist_valbuildCore.extractValModules;
@@ -1,2 +1,2 @@
1
- export { A as ArraySchema, B as BooleanSchema, x as CODE_LANGUAGES, p as COLOR_FORMATS, C as ColorSchema, e as DEFAULT_APP_HOST, q as DEFAULT_COLOR_FORMAT, D as DEFAULT_CONTENT_HOST, g as DEFAULT_VAL_REMOTE_HOST, o as DateSchema, r as DateTimeSchema, F as FATAL_ERROR_TYPES, n as FileSchema, G as GenericSelector, l as ImageSchema, I as Internal, K as KeyOfSchema, L as LiteralSchema, M as ModuleFilePathSep, N as NumberSchema, O as ObjectSchema, R as RecordSchema, u as RichTextSchema, t as RouteSchema, S as Schema, k as StringSchema, U as UnionSchema, V as VAL_EXTENSION, j as derefPatch, v as deserializeSchema, f as extractValModules, y as getSourcePathFromRoute, h as hasRemoteFileSchema, i as initVal, m as modules, w as previewScope } from './index-d7cc2231.esm.js';
1
+ export { A as ArraySchema, B as BooleanSchema, y as CODE_LANGUAGES, q as COLOR_FORMATS, C as ColorSchema, e as DEFAULT_APP_HOST, r as DEFAULT_COLOR_FORMAT, D as DEFAULT_CONTENT_HOST, j as DEFAULT_VAL_REMOTE_HOST, p as DateSchema, t as DateTimeSchema, F as FATAL_ERROR_TYPES, o as FileSchema, G as GenericSelector, n as ImageSchema, I as Internal, K as KeyOfSchema, L as LiteralSchema, M as ModuleFilePathSep, N as NumberSchema, O as ObjectSchema, R as RecordSchema, v as RichTextSchema, u as RouteSchema, S as Schema, l as StringSchema, U as UnionSchema, V as VAL_EXTENSION, g as computeValModuleShas, k as derefPatch, w as deserializeSchema, f as extractValModules, z as getSourcePathFromRoute, h as hasRemoteFileSchema, i as initVal, m as modules, x as previewScope } from './index-005f51a5.esm.js';
2
2
  import './result-daff1cae.esm.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@valbuild/core",
3
- "version": "0.105.0",
3
+ "version": "0.105.1",
4
4
  "private": false,
5
5
  "description": "Val - supercharged hard-coded content",
6
6
  "repository": {
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var dist_valbuildCore = require('../../dist/index-730a5254.cjs.dev.js');
5
+ var dist_valbuildCore = require('../../dist/index-baa3109b.cjs.dev.js');
6
6
  var result = require('../../dist/result-bb1f436e.cjs.dev.js');
7
7
  var util = require('../../dist/util-b213092b.cjs.dev.js');
8
8
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var dist_valbuildCore = require('../../dist/index-e990b6ad.cjs.prod.js');
5
+ var dist_valbuildCore = require('../../dist/index-4013c9f8.cjs.prod.js');
6
6
  var result = require('../../dist/result-787e35f6.cjs.prod.js');
7
7
  var util = require('../../dist/util-030d8a1f.cjs.prod.js');
8
8
 
@@ -1,5 +1,5 @@
1
- import { _ as _typeof, a as _slicedToArray, P as PatchError, s as splitModuleFilePathAndModulePath, b as _createClass, c as _classCallCheck, d as _toConsumableArray } from '../../dist/index-d7cc2231.esm.js';
2
- export { P as PatchError } from '../../dist/index-d7cc2231.esm.js';
1
+ import { _ as _typeof, a as _slicedToArray, P as PatchError, s as splitModuleFilePathAndModulePath, b as _createClass, c as _classCallCheck, d as _toConsumableArray } from '../../dist/index-005f51a5.esm.js';
2
+ export { P as PatchError } from '../../dist/index-005f51a5.esm.js';
3
3
  import { f as isNonEmpty, e as err, o as ok, m as map, g as flatMap, i as isErr, h as flatMapReduce, j as filterOrElse, k as mapErr, l as map$1, n as all, p as flatten, q as allT } from '../../dist/result-daff1cae.esm.js';
4
4
  import { p as pipe } from '../../dist/util-18613e99.esm.js';
5
5