@valbuild/shared 0.145.0 → 0.146.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.
@@ -761,14 +761,16 @@ var VAL_ENABLE_COOKIE_NAME = Internal.VAL_ENABLE_COOKIE_NAME;
761
761
  * byte-identical each time, because the query and the session are fixed for the
762
762
  * length of a request. This is what makes the second and third call free.
763
763
  *
764
- * ## Why the scope is the REQUEST and can never be wider
764
+ * ## Why the scope is the REQUEST
765
765
  *
766
- * The memoised response is `own_patch_groups_only: true` — it contains the
767
- * CALLER'S OWN unpublished work, resolved from their session cookie. A memo
768
- * that outlived the request would serve one author's staged edits to the next
769
- * visitor, which is the exact failure `own_patch_groups_only` exists to
770
- * prevent, and it would be invisible: the draft would simply render somebody
771
- * else's half-finished sentence.
766
+ * The memoised response is a DRAFT -- unpublished work, read with the caller's
767
+ * session cookie. Every caller allowed to read drafts gets the same draft (patch
768
+ * groups, which made it per author, are gone), but whether a caller is allowed
769
+ * at all is decided per session. A memo that outlived the request would hand
770
+ * the draft to the next visitor without asking, and it would be invisible: the
771
+ * page would simply render somebody's half-finished sentence. Sharing it across
772
+ * requests is possible now, keyed on the chain's head, and would be its own
773
+ * measured change.
772
774
  *
773
775
  * So this module holds NO state of its own. The caller supplies the box, and
774
776
  * the box has to come from something the framework already scopes to the
@@ -1726,21 +1728,6 @@ var StatProposal = z.object({
1726
1728
  /** `val/p/<name>`. */
1727
1729
  branch: z.string()
1728
1730
  });
1729
-
1730
- /**
1731
- * A patch group: the set of patches one user has chosen to publish.
1732
- *
1733
- * Not a patch *set* — a patch set is computed from the schema and says which
1734
- * patches must move together; a patch group is curated and says which ones this
1735
- * user wants live. See `docs/independent-publish/PLAN.md`.
1736
- */
1737
- var PatchGroup = z.object({
1738
- patchGroupId: z.string(),
1739
- authorId: z.string().nullable(),
1740
- createdAt: z.string(),
1741
- publishedAt: z.string().nullable(),
1742
- patchIds: z.array(PatchId)
1743
- });
1744
1731
  var GenericPatchError = z.union([z.object({
1745
1732
  patchId: PatchId,
1746
1733
  message: z.string(),
@@ -2249,14 +2236,6 @@ var Api = {
2249
2236
  * highest version. Optional, for the same reason `headPatchId` is.
2250
2237
  */
2251
2238
  headVersion: z.number().optional(),
2252
- /**
2253
- * Every group on the branch and which listed patches it holds,
2254
- * read with the list and `headVersion`. What a Studio's view of
2255
- * the groups is taken from, so a stage or an unstage made in
2256
- * another browser reaches it with the next stat. Absent where
2257
- * the content service has no groups.
2258
- */
2259
- patchGroups: z.array(PatchGroup).optional(),
2260
2239
  commits: z.array(ValCommit),
2261
2240
  /**
2262
2241
  * The publishes the content service knows about.
@@ -2553,24 +2532,6 @@ var Api = {
2553
2532
  id: z.array(PatchId).min(1, "At least one patch id is required")
2554
2533
  },
2555
2534
  body: z.object({
2556
- /*
2557
- * Patches that are NOT being deleted but must lose their patch
2558
- * group membership because these are.
2559
- *
2560
- * Deleting a patch out of the middle of a patch set leaves every
2561
- * group holding the rest with a non-prefix intersection, and a
2562
- * prefix is the one invariant a group has. Which patches those are
2563
- * needs the content schema, so the client computes the forward
2564
- * closure and sends it; the content API drops the memberships
2565
- * without touching the patches.
2566
- *
2567
- * In the BODY while the ids to delete are in the query, because
2568
- * this list is unbounded in the same way and the query string is
2569
- * already chunked to fit. Optional throughout: `fs` mode has no
2570
- * groups, and a client that predates this is deleting correctly,
2571
- * just not repairing.
2572
- */
2573
- unstagePatchIds: z.array(PatchId).optional(),
2574
2535
  /*
2575
2536
  * Answer with `{ deleted, headVersion }` rather than the bare id
2576
2537
  * array. Asked for rather than always sent, because the array is
@@ -2612,16 +2573,7 @@ var Api = {
2612
2573
  path: ModuleFilePath,
2613
2574
  patchId: PatchId,
2614
2575
  patch: z.any() // TODO: this should be Patch instead - we got a weird validation error: although input looks good, it still does not accept objects as values... Which it should do via the z.record(JSONValue) type
2615
- })),
2616
- // Patch group membership. Sent with the patch itself, in one request, so
2617
- // there is no window in which a patch exists but belongs to no group.
2618
- // Absent means "the caller does not know about groups" - the server then
2619
- // behaves exactly as before.
2620
- patchGroupId: z.string().nullish(),
2621
- // What has to come with the patch: other patch ids that must join the
2622
- // same group for it to stay applicable. Computed on the client, which
2623
- // is the only side that has the schema needed to derive patch sets.
2624
- withPatchIds: z.array(PatchId).optional()
2576
+ }))
2625
2577
  }),
2626
2578
  cookies: {
2627
2579
  val_session: z.string().optional()
@@ -2663,7 +2615,6 @@ var Api = {
2663
2615
  error: PlanRefusalError,
2664
2616
  newPatchIds: z.array(PatchId),
2665
2617
  parentRef: ParentRef,
2666
- patchGroupId: z.string().optional(),
2667
2618
  headVersion: z.number().optional()
2668
2619
  })
2669
2620
  }), z.object({
@@ -2671,7 +2622,6 @@ var Api = {
2671
2622
  json: z.object({
2672
2623
  newPatchIds: z.array(PatchId),
2673
2624
  parentRef: ParentRef,
2674
- patchGroupId: z.string().optional(),
2675
2625
  /**
2676
2626
  * The chain version the last of these patches made, comparable with
2677
2627
  * `headVersion` on `/stat`. A client keeps the highest version, so a
@@ -2686,16 +2636,7 @@ var Api = {
2686
2636
  req: {
2687
2637
  query: {
2688
2638
  patch_id: z.array(PatchId).optional(),
2689
- exclude_patch_ops: onlyOneBooleanQueryParam.optional(),
2690
- /**
2691
- * Include the patch group annotation in the answer.
2692
- *
2693
- * Off by default because the client CHUNKS this request — a long
2694
- * chain is several round trips — and the groups are a property of the
2695
- * branch, identical in every chunk. Asking on each one is N identical
2696
- * lookups against the content API to learn the same thing.
2697
- */
2698
- include_patch_groups: onlyOneBooleanQueryParam.optional()
2639
+ exclude_patch_ops: onlyOneBooleanQueryParam.optional()
2699
2640
  },
2700
2641
  cookies: {
2701
2642
  val_session: z.string().optional()
@@ -2724,12 +2665,8 @@ var Api = {
2724
2665
  authorId: z.string().nullable(),
2725
2666
  appliedAt: z.object({
2726
2667
  commitSha: z.string()
2727
- }).nullable(),
2728
- // Which patch groups hold this patch. Optional so that FS mode, and
2729
- // any server that predates patch groups, can leave it out.
2730
- patchGroupIds: z.array(z.string()).optional()
2668
+ }).nullable()
2731
2669
  })),
2732
- patchGroups: z.array(PatchGroup).optional(),
2733
2670
  baseSha: z.string(),
2734
2671
  error: GenericError.optional(),
2735
2672
  errors: z.record(PatchId, GenericError).optional()
@@ -2737,111 +2674,6 @@ var Api = {
2737
2674
  })])
2738
2675
  }
2739
2676
  },
2740
- // Patch group membership. Both are idempotent set operations, and both take an
2741
- // already-closed set: the client computes the prefix closure (staging) or the
2742
- // forward closure (unstaging) because only the client has the schema needed to
2743
- // derive patch sets. See `docs/independent-publish/PLAN.md`.
2744
- "/patch-groups/~/patches": {
2745
- PUT: {
2746
- req: {
2747
- body: z.object({
2748
- /**
2749
- * The group to stage into. Absent means the caller's open group on
2750
- * the branch, created if there is none — which is what the Studio
2751
- * sends, so a stage never has to wait for a group to exist.
2752
- */
2753
- patchGroupId: z.string().optional(),
2754
- /** What the user asked to stage. */
2755
- patchIds: z.array(PatchId),
2756
- /*
2757
- * What has to come with it, because the staged patches are written on
2758
- * top of it.
2759
- *
2760
- * The content API records membership as `explicit` or `dependency`
2761
- * and reads what it is not told about as a dependency — so folding
2762
- * the two halves into `patchIds` files the patch someone clicked as
2763
- * something the closure dragged in.
2764
- */
2765
- withPatchIds: z.array(PatchId).optional()
2766
- }).refine(function (body) {
2767
- var _body$withPatchIds$le, _body$withPatchIds;
2768
- return body.patchIds.length > 0 || ((_body$withPatchIds$le = (_body$withPatchIds = body.withPatchIds) === null || _body$withPatchIds === void 0 ? void 0 : _body$withPatchIds.length) !== null && _body$withPatchIds$le !== void 0 ? _body$withPatchIds$le : 0) > 0;
2769
- },
2770
- // Either half alone is a real request: a stage of only what came with
2771
- // it happens when the deferred queue's scope filter drops everything
2772
- // the user originally clicked.
2773
- "At least one patch id is required"),
2774
- cookies: {
2775
- val_session: z.string().optional()
2776
- }
2777
- },
2778
- res: z.union([unauthorizedResponse, z.object({
2779
- status: z.literal(403),
2780
- json: GenericError
2781
- }), z.object({
2782
- // The group has already been published, so its membership is frozen.
2783
- status: z.literal(409),
2784
- json: GenericError
2785
- }), z.object({
2786
- status: z.literal(500),
2787
- json: GenericError
2788
- }), z.object({
2789
- status: z.literal(200),
2790
- json: z.object({
2791
- /** `null` for an unstage when the caller has no open group. */
2792
- patchGroupId: z.string().nullable(),
2793
- patchIds: z.array(PatchId),
2794
- /**
2795
- * The chain version the change committed at. The client keeps its
2796
- * own view of the change until a stat at least this new shows it.
2797
- * Absent from a content service that predates it.
2798
- */
2799
- headVersion: z.number().optional()
2800
- })
2801
- })])
2802
- },
2803
- DELETE: {
2804
- req: {
2805
- body: z.object({
2806
- /** See the PUT. Absent with no open group is a no-op. */
2807
- patchGroupId: z.string().optional(),
2808
- /** What the user asked to unstage. */
2809
- patchIds: z.array(PatchId),
2810
- /** What has to go with it: everything built on top of it. */
2811
- withPatchIds: z.array(PatchId).optional()
2812
- }).refine(function (body) {
2813
- var _body$withPatchIds$le2, _body$withPatchIds2;
2814
- return body.patchIds.length > 0 || ((_body$withPatchIds$le2 = (_body$withPatchIds2 = body.withPatchIds) === null || _body$withPatchIds2 === void 0 ? void 0 : _body$withPatchIds2.length) !== null && _body$withPatchIds$le2 !== void 0 ? _body$withPatchIds$le2 : 0) > 0;
2815
- }, "At least one patch id is required"),
2816
- cookies: {
2817
- val_session: z.string().optional()
2818
- }
2819
- },
2820
- res: z.union([unauthorizedResponse, z.object({
2821
- status: z.literal(403),
2822
- json: GenericError
2823
- }), z.object({
2824
- status: z.literal(409),
2825
- json: GenericError
2826
- }), z.object({
2827
- status: z.literal(500),
2828
- json: GenericError
2829
- }), z.object({
2830
- status: z.literal(200),
2831
- json: z.object({
2832
- /** `null` for an unstage when the caller has no open group. */
2833
- patchGroupId: z.string().nullable(),
2834
- patchIds: z.array(PatchId),
2835
- /**
2836
- * The chain version the change committed at. The client keeps its
2837
- * own view of the change until a stat at least this new shows it.
2838
- * Absent from a content service that predates it.
2839
- */
2840
- headVersion: z.number().optional()
2841
- })
2842
- })])
2843
- }
2844
- },
2845
2677
  "/schema": {
2846
2678
  GET: {
2847
2679
  req: {
@@ -2878,34 +2710,7 @@ var Api = {
2878
2710
  validate_sources: onlyOneBooleanQueryParam.optional(),
2879
2711
  validate_binary_files: onlyOneBooleanQueryParam.optional(),
2880
2712
  exclude_patches: onlyOneBooleanQueryParam.optional(),
2881
- apply_patches: onlyOneBooleanQueryParam.optional(),
2882
- /**
2883
- * Apply ONLY these patches, rather than everything pending.
2884
- *
2885
- * This is what makes a draft-mode render match the caller's staged
2886
- * view. Without it `/sources/~` replays every pending patch on the
2887
- * branch, so a server-rendered preview shows other people's
2888
- * unpublished work — the one thing independent publish is for.
2889
- *
2890
- * Omitted means everything pending, which is the behaviour every
2891
- * existing caller has and must keep. An EMPTY array is a different
2892
- * answer and is honoured as one: a group holding nothing renders
2893
- * base.
2894
- */
2895
- patch_id: z.array(PatchId).optional(),
2896
- /**
2897
- * Apply only the patches in the CALLER'S OWN patch groups.
2898
- *
2899
- * The server resolves them from the session, so a draft render does
2900
- * not have to know its own group ids — which it cannot, since it has
2901
- * no client state. This is what makes `fetchVal` in draft mode show
2902
- * the person their own staged work rather than everybody's.
2903
- *
2904
- * Ignored when `patch_id` is given: an explicit list is a caller that
2905
- * already knows what it wants, and silently intersecting the two
2906
- * would make the narrower one invisible.
2907
- */
2908
- own_patch_groups_only: onlyOneBooleanQueryParam.optional()
2713
+ apply_patches: onlyOneBooleanQueryParam.optional()
2909
2714
  },
2910
2715
  cookies: {
2911
2716
  val_session: z.string().optional()
@@ -3065,18 +2870,6 @@ var Api = {
3065
2870
  body: z.object({
3066
2871
  message: z.string().optional(),
3067
2872
  patchIds: z.array(PatchId),
3068
- /*
3069
- * The patch group this commit EMPTIES, if it empties one.
3070
- *
3071
- * Forwarded to the content API, which closes the group it names —
3072
- * and closes it unconditionally, without checking that the commit
3073
- * shipped all of it. So the client sends it only when the publish
3074
- * accounts for every patch the group still holds; a partial publish
3075
- * omits it and the group stays open with the rest in it.
3076
- *
3077
- * Optional, and absent in `fs` mode, which has no groups.
3078
- */
3079
- patchGroupId: z.string().optional(),
3080
2873
  /*
3081
2874
  * The newest commit this client knew about when it decided.
3082
2875
  *
@@ -3185,19 +2978,6 @@ var Api = {
3185
2978
  */
3186
2979
  headVersion: z.number().optional()
3187
2980
  })
3188
- }),
3189
- /*
3190
- * The named patch group is not this caller's, or the lookup that would
3191
- * say so failed.
3192
- *
3193
- * Publishing may CLOSE a group, and closing somebody else's leaves
3194
- * their pending work in a closed group and in no open one. So `/save`
3195
- * runs the same ownership check stage and unstage do, and refuses the
3196
- * same way — see `refuseUnlessOwn`.
3197
- */
3198
- z.object({
3199
- status: z.literal(403),
3200
- json: GenericError
3201
2981
  }), z.object({
3202
2982
  status: z.literal(500),
3203
2983
  json: GenericError
@@ -3215,8 +2995,7 @@ var Api = {
3215
2995
  z.object({
3216
2996
  message: z.string(),
3217
2997
  publishRefusal: PublishRefusal
3218
- }), /** A group that has already shipped. See the 403 above. */
3219
- z.object({
2998
+ }), z.object({
3220
2999
  message: z.string()
3221
3000
  }), z.object({
3222
3001
  message: z.string(),
@@ -3235,22 +3014,6 @@ var Api = {
3235
3014
  z.object({
3236
3015
  message: z.string(),
3237
3016
  headMoved: z.literal(true)
3238
- }),
3239
- /**
3240
- * The group this commit named has already been published.
3241
- *
3242
- * A third thing sharing 409, and flagged for the same reason
3243
- * `headMoved` is: read as a plain not-fast-forward it looks
3244
- * retryable, and it is the opposite — the id will never be writable
3245
- * again, so retrying reproduces it forever.
3246
- *
3247
- * It means this author published from somewhere else. The client
3248
- * forgets the id and falls back to the annotation, which is the
3249
- * same recovery a 409 on stage or unstage triggers.
3250
- */
3251
- z.object({
3252
- message: z.string(),
3253
- patchGroupPublished: z.literal(true)
3254
3017
  })])
3255
3018
  }), z.object({
3256
3019
  status: z.literal(400),
@@ -3545,16 +3308,7 @@ var Api = {
3545
3308
  limit: onlyOneIntQueryParam.refine(function (arg) {
3546
3309
  return arg > 0 && arg <= JSON_ENTRIES_BATCH_MAX;
3547
3310
  }, "limit must be between 1 and ".concat(JSON_ENTRIES_BATCH_MAX)).optional(),
3548
- apply_patches: onlyOneBooleanQueryParam.optional(),
3549
- /**
3550
- * The caller's own staged work, and nobody else's.
3551
- *
3552
- * The same flag `/sources/~` takes, and for the same reason — a draft
3553
- * page renders both, so a scoped module beside an unscoped
3554
- * `jsonValues` entry showed one person's view and everybody's pending
3555
- * work on the same screen.
3556
- */
3557
- own_patch_groups_only: onlyOneBooleanQueryParam.optional()
3311
+ apply_patches: onlyOneBooleanQueryParam.optional()
3558
3312
  },
3559
3313
  cookies: _defineProperty({}, VAL_SESSION_COOKIE, z.string().optional())
3560
3314
  },
@@ -4620,13 +4374,11 @@ function newestCommitSha(commits) {
4620
4374
  *
4621
4375
  * The head the server REPORTS (`headPatchId`) when it reports one, and not the
4622
4376
  * last patch it listed. The list — `/applicable/patches`, and `/stat` on top of
4623
- * it — leaves out patches the running deployment already contains, and since
4624
- * patch groups a publish can ship later patches while an earlier one stays
4625
- * pending (another author's change that nets to nothing can never be published
4626
- * at all). The last listed id is then behind the head for good, and the content
4627
- * service accepts a write only on the head, so every save naming it is refused
4628
- * — and a re-sync returns the same list. What fixed it in the Studio before
4629
- * this existed was discarding the other author's change.
4377
+ * it — leaves out patches the running deployment already contains, and a
4378
+ * publish can ship later patches while an earlier one stays pending (a failed
4379
+ * publish holds its changes back). The last listed id is then behind the head
4380
+ * for good, and the content service accepts a write only on the head, so every
4381
+ * save naming it is refused — and a re-sync returns the same list.
4630
4382
  *
4631
4383
  * `null` is a REPORTED empty chain, not "unknown". `undefined` is a server
4632
4384
  * that reports no head (`fs` mode, which ignores the parent anyway, or a
@@ -7854,7 +7606,20 @@ var buildTargetResponse = z.object({
7854
7606
  rscRuntimePath: z.string(),
7855
7607
  flightServer: z.string(),
7856
7608
  serverFnBase: z.string()
7857
- })
7609
+ }),
7610
+ /*
7611
+ * What the base layer is built from and what its chunks export, which
7612
+ * `val publish` checks a project's layer against (`BuildTarget.base` in
7613
+ * @valbuild/tanstack-build). Declared, because `z.object` DROPS a key it
7614
+ * does not name: left out, they never reached the build, and every
7615
+ * publish skipped both checks while saying the platform had not sent them.
7616
+ * Optional, for a platform that predates them.
7617
+ */
7618
+ pins: z.record(z.string(), z.string()).optional(),
7619
+ exports: z.object({
7620
+ worker: z.record(z.string(), z.array(z.string())),
7621
+ browser: z.record(z.string(), z.array(z.string()))
7622
+ }).optional()
7858
7623
  }),
7859
7624
  project: z.object({
7860
7625
  rev: z.string().nullable(),
@@ -8068,4 +7833,515 @@ function parse(schema, body, call) {
8068
7833
  return parsed.data;
8069
7834
  }
8070
7835
 
8071
- export { AA_LARGE, AA_TEXT, Api, BRAND_CONTRAST_PAIRS, BinaryFileRef, CodeOptions, ColorOptions, DEFAULT_ERROR_MESSAGE, DateOptions, ENCODE_DEFAULTS, ENCODE_MIME_TYPE_OF, FileOptions, HistoricalCommit, HistoricalModule, HistoricalPatchSet, HistoryError, ImageEncodeOption, ImageOptions, JSONValue, JSON_ENTRIES_BATCH_MAX, ModuleComparison, NEVER_ENCODED, ParentRef$1 as ParentRef, Patch, PatchBlock, PatchGroup, PatchId, PatchJSON, PlanRefusalError, PublishProtocolError, RAMP_STEPS, RemirrorBr, RemirrorBulletList, RemirrorHeading, RemirrorImage, RemirrorJSON, RemirrorLinkMark, RemirrorListItem, RemirrorOrderedList, RemirrorParagraph, RemirrorText, RemirrorTextMark, RestoreVerdict, RichTextOptions, SCHEMA_SOURCE_FIXES, SerializedArraySchema, SerializedBooleanSchema, SerializedCodeSchema, SerializedColorSchema, SerializedDateSchema, SerializedDateTimeSchema, SerializedDiscriminatedUnionSchema, SerializedEnumSchema, SerializedFileSchema, SerializedImageSchema, SerializedKeyOfSchema, SerializedLiteralSchema, SerializedLocaleSchema, SerializedNumberSchema, SerializedObjectSchema, SerializedRecordSchema, SerializedRichTextSchema, SerializedRouteSchema, SerializedSchema, SerializedSettingsSchema, SerializedStringSchema, SerializedValViewSchema, SerializedVideoSchema, SharedValConfig, VAL_ENABLE_COOKIE_NAME, VAL_GREEN_RAMP, VAL_SESSION_COOKIE, VAL_STATE_COOKIE, VAL_STUDIO_HEADER, ValCommit, ValDeployment, VideoOptions, VideoStreamOption, accentRamp, buildDuplicatePatch, buildEmptyAtPathPatch, buildFileRefValue, buildImageGalleryPatch, buildRemoveImageGalleryEntryPatch, buildSearchIndex, chainHeadOf, checkCompatibility, chooseEncoded, concatModulePath, contrastRatio, createRegExpFromPattern, createSearchIndex, createValClient, declaredLocales, describeContainerAtPath, emptyOf, explainIncompatible, filterBlockingValidationErrors, filterRoutesByPatterns, findSimilar, fitWithin, flattenRichText, forEachRichTextImage, getErrorMessageFromUnknownJson, getFilenameFromRef, getInlineImgInfo, getKeyOfRecordAt, getRefParts, getRoutesOf, getRoutesWithModulePaths, getSourceAt, indexModule, isMimeTypeAccepted, isRemoteSchema, isSchemaSourceFixError, isSkippedSource, keyOfRecordPath, levenshtein, localeAt, memoizePerRequest, newestCommitSha, parseArtifacts, parseBuildTarget, parseCancel, parseDeclare, parseDiscard, parseJob, parseNewestCiRun, parsePress, parseProblems, parseProjectSource, parsePromote, parsePublishToken, parseRenew, parseRequestStatus, parseStatus, parseUpdateTarget, parseVerify, partitionValidationErrors, performSearch, relativeLuminance, remirrorToRichTextSource, removeModule, resolveEncodeSettings, resolvePairGround, resolveSchemaSourceFixForError, resolveSchemaSourceFixes, resolveSerializedSchemaAtPath, richTextImageSchema, richTextToRemirror, safeParsePatch, sourcePathOfChild, themeCustomProperties, toolNames, traverseSchemaSource, urlOf, validateRoutePatterns, withExtension };
7836
+ /**
7837
+ * This functions returns all the possible schema types of a given module path.
7838
+ */
7839
+ function schemaTypesOfPath(schema, patchPath) {
7840
+ if (!patchPath || patchPath.length === 0) {
7841
+ return new Set([schema.type]);
7842
+ }
7843
+ var branches = new Set();
7844
+ var current = schema;
7845
+ var i = -1;
7846
+ var _iterator = _createForOfIteratorHelper(patchPath),
7847
+ _step;
7848
+ try {
7849
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
7850
+ var pathPart = _step.value;
7851
+ i++;
7852
+ if (!current) {
7853
+ break;
7854
+ }
7855
+ if (current.type === "array") {
7856
+ current = current.item;
7857
+ } else if (current.type === "record") {
7858
+ current = current.item;
7859
+ } else if (current.type === "object" || current.type === "settings") {
7860
+ current = current.items[pathPart];
7861
+ } else if (current.type === "richtext") {
7862
+ // richtext has internal structure (nodes with indices and tags), allow traversal
7863
+ break;
7864
+ } else if (current.type === "discriminated-union") {
7865
+ var types = current.items;
7866
+ var _iterator2 = _createForOfIteratorHelper(types),
7867
+ _step2;
7868
+ try {
7869
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
7870
+ var type = _step2.value;
7871
+ var subTypes = schemaTypesOfPath(type, patchPath.slice(i));
7872
+ for (var _i = 0, _Array$from = Array.from(subTypes.values()); _i < _Array$from.length; _i++) {
7873
+ var subType = _Array$from[_i];
7874
+ branches.add(subType);
7875
+ }
7876
+ }
7877
+ } catch (err) {
7878
+ _iterator2.e(err);
7879
+ } finally {
7880
+ _iterator2.f();
7881
+ }
7882
+ return branches;
7883
+ } else if (current.type === "enum" || current.type === "boolean" || current.type === "number" || current.type === "string" || current.type === "date" || current.type === "dateTime" || current.type === "color" || current.type === "code" || current.type === "file" || current.type === "image" || current.type === "video" || current.type === "keyOf" || current.type === "route" || current.type === "locale" || current.type === "literal" ||
7884
+ // Nothing is patchable at a view path: the target module owns its source.
7885
+ current.type === "view") {
7886
+ if (current.type === "image" || current.type === "file") {
7887
+ // allow changes to metadata
7888
+ if (patchPath[i] === "metadata") {
7889
+ break;
7890
+ }
7891
+ }
7892
+ if (current.type === "video") {
7893
+ // A video is edited a property at a time — its poster time, a caption
7894
+ // track's label — so that two editors changing different parts of one
7895
+ // video do not overwrite each other. Everything below it is the video.
7896
+ break;
7897
+ }
7898
+ if (i !== patchPath.length - 1) {
7899
+ throw new Error("Found " + current.type + " (primitive), but path has more parts: " + patchPath.join("/") + " at " + pathPart);
7900
+ }
7901
+ break;
7902
+ } else {
7903
+ var _unreachable = current;
7904
+ var unknownType = _unreachable.type;
7905
+ console.error("Unexecpted resolved schema type: ".concat(unknownType, " in ").concat(patchPath.join("/"), " at ").concat(pathPart));
7906
+ return new Set([unknownType]);
7907
+ }
7908
+ }
7909
+ } catch (err) {
7910
+ _iterator.e(err);
7911
+ } finally {
7912
+ _iterator.f();
7913
+ }
7914
+ if (current) {
7915
+ branches.add(current.type);
7916
+ // A discriminated union's value IS an object, and an enum's IS a string:
7917
+ // a patch op typed for either has to be accepted here too.
7918
+ if (current.type === "discriminated-union") {
7919
+ branches.add("object");
7920
+ } else if (current.type === "enum") {
7921
+ branches.add("string");
7922
+ }
7923
+ }
7924
+ return branches;
7925
+ }
7926
+
7927
+ // Examples: /file/name.val.ts?/path/to/patch
7928
+
7929
+ /**
7930
+ * A patch set is a set of patches that are non-independent of each other. This is useful for example when we want to apply a set of patches atomically.
7931
+ * A patch set is identified by a module file path and a json patch path delimited by a '?' character. We call this the patch set path. Example: /file/name.val.ts?/path/to/patch
7932
+ *
7933
+ *
7934
+ * NOTE: the order of patch sets is always newest first. This is because the UX always shows the newest patches first.
7935
+ */
7936
+
7937
+ /**
7938
+ * Is `inner` strictly nested inside the patch set `outer`?
7939
+ *
7940
+ * A plain `inner.startsWith(outer)` is not enough, and the difference is not
7941
+ * cosmetic. The file part of a key is terminated by the '?' delimiter, but the
7942
+ * segments of the patch path are not terminated by anything, so a raw prefix
7943
+ * test also matches siblings whose *name* merely starts with the same
7944
+ * characters: '/p.val.ts?foobar/title' starts with '/p.val.ts?foo', so removing
7945
+ * record key "foo" and retitling record key "foobar" would be merged into one
7946
+ * patch set.
7947
+ *
7948
+ * That used to only over-group two unrelated changes in the compare view. Now
7949
+ * that patch sets decide what moves between branches as one (whole patch sets,
7950
+ * as `changesToMove` moves them), it means moving one key silently moves its
7951
+ * similarly-named sibling — so the boundary has to be
7952
+ * checked explicitly: '?' when `outer` is a bare module file path, '/' when it
7953
+ * already has a patch path.
7954
+ */
7955
+ function isInsidePatchSetPath(inner, outer) {
7956
+ if (!inner.startsWith(outer)) {
7957
+ return false;
7958
+ }
7959
+ var boundary = inner[outer.length];
7960
+ return outer.includes("?") ? boundary === "/" : boundary === "?";
7961
+ }
7962
+ var PatchSets = /*#__PURE__*/function () {
7963
+ function PatchSets() {
7964
+ _classCallCheck(this, PatchSets);
7965
+ _defineProperty(this, "insertedPatches", void 0);
7966
+ _defineProperty(this, "patchSetMetadata", void 0);
7967
+ _defineProperty(this, "orderedInsertKeys", void 0);
7968
+ this.patchSetMetadata = {};
7969
+ this.orderedInsertKeys = [];
7970
+ this.insertedPatches = new Set();
7971
+ }
7972
+ return _createClass(PatchSets, [{
7973
+ key: "reset",
7974
+ value: function reset() {
7975
+ this.patchSetMetadata = {};
7976
+ this.orderedInsertKeys = [];
7977
+ this.insertedPatches = new Set();
7978
+ }
7979
+ }, {
7980
+ key: "getInsertedPatches",
7981
+ value: function getInsertedPatches() {
7982
+ return this.insertedPatches;
7983
+ }
7984
+ }, {
7985
+ key: "insertPath",
7986
+ value: function insertPath(moduleFilePath, affectsPatchPath, patchId, createdAt, author, opType, schemaTypes, opPath) {
7987
+ var newPatchSetPath = affectsPatchPath.length > 0 ? "".concat(moduleFilePath, "?").concat(affectsPatchPath.join("/")) : moduleFilePath;
7988
+ var pathIndexesThatMustBeMerged = [];
7989
+ // TODO: current implementation is O(n), with isInside it is: O(n x m) - there's room for optimization (Trie?). Just make sure order is maintained and that insert AND then serialize is what we optimize for because the UX will do an insert, then serialize immediately after
7990
+ for (var i = this.orderedInsertKeys.length - 1; i >= 0; i--) {
7991
+ var currentInsertKey = this.orderedInsertKeys[i];
7992
+ if (newPatchSetPath !== currentInsertKey) {
7993
+ if (isInsidePatchSetPath(newPatchSetPath, currentInsertKey)) {
7994
+ // This new patch set is inside an existing patch set...
7995
+ // Use the existing patch set as the new name
7996
+ newPatchSetPath = currentInsertKey;
7997
+ // Move to new patch set to head
7998
+ this.orderedInsertKeys.splice(i, 1);
7999
+ this.orderedInsertKeys.unshift(newPatchSetPath);
8000
+ } else if (isInsidePatchSetPath(currentInsertKey, newPatchSetPath)) {
8001
+ // We found a patch set (with a shorter path) that needs to be merged into this new patch set
8002
+ pathIndexesThatMustBeMerged.push(i);
8003
+ }
8004
+ } else {
8005
+ // This patch set already exists
8006
+ // Move to new patch set to head
8007
+ this.orderedInsertKeys.splice(i, 1);
8008
+ this.orderedInsertKeys.unshift(newPatchSetPath);
8009
+ }
8010
+ }
8011
+
8012
+ // Merge existing patch sets into this new one:
8013
+ for (var _i = 0, _pathIndexesThatMustB = pathIndexesThatMustBeMerged; _i < _pathIndexesThatMustB.length; _i++) {
8014
+ var pathIndexThatMustBeMerged = _pathIndexesThatMustB[_i];
8015
+ var moduleFileOrPatchSetPath = this.orderedInsertKeys[pathIndexThatMustBeMerged];
8016
+
8017
+ // 1) remove the old patch set path from ordered insert key
8018
+ this.orderedInsertKeys.splice(pathIndexThatMustBeMerged, 1);
8019
+
8020
+ // 2) merge metadata into new
8021
+ var existingPatchSetMetadata = this.patchSetMetadata[moduleFileOrPatchSetPath];
8022
+ if (!this.patchSetMetadata[newPatchSetPath]) {
8023
+ this.patchSetMetadata[newPatchSetPath] = {
8024
+ moduleFilePath: moduleFilePath,
8025
+ patchPath: affectsPatchPath,
8026
+ patches: [],
8027
+ authors: [],
8028
+ opTypes: [],
8029
+ schemaTypes: Array.from(schemaTypes),
8030
+ lastUpdated: createdAt,
8031
+ lastUpdatedBy: author
8032
+ };
8033
+ }
8034
+ if (existingPatchSetMetadata) {
8035
+ var _iterator = _createForOfIteratorHelper(existingPatchSetMetadata.patches.slice()),
8036
+ _step;
8037
+ try {
8038
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
8039
+ var patchMetadata = _step.value;
8040
+ this.patchSetMetadata[newPatchSetPath].patches.unshift(patchMetadata);
8041
+ if (patchMetadata.author !== null) {
8042
+ this.patchSetMetadata[newPatchSetPath].authors.unshift(patchMetadata.author);
8043
+ }
8044
+ this.patchSetMetadata[newPatchSetPath].opTypes.unshift(patchMetadata.opType);
8045
+ }
8046
+ } catch (err) {
8047
+ _iterator.e(err);
8048
+ } finally {
8049
+ _iterator.f();
8050
+ }
8051
+ } else {
8052
+ throw new Error("Could not find patch set metadata or patch metadata for (inserted) patch set path: ".concat(moduleFileOrPatchSetPath));
8053
+ }
8054
+
8055
+ // 3) delete old metadata
8056
+ if (moduleFileOrPatchSetPath !== newPatchSetPath) {
8057
+ delete this.patchSetMetadata[moduleFileOrPatchSetPath];
8058
+ }
8059
+ }
8060
+
8061
+ // Insert new metadata
8062
+ if (!this.patchSetMetadata[newPatchSetPath]) {
8063
+ this.patchSetMetadata[newPatchSetPath] = {
8064
+ moduleFilePath: moduleFilePath,
8065
+ patchPath: affectsPatchPath,
8066
+ patches: [],
8067
+ authors: [],
8068
+ opTypes: [],
8069
+ schemaTypes: schemaTypes,
8070
+ lastUpdated: createdAt,
8071
+ lastUpdatedBy: author
8072
+ };
8073
+ }
8074
+ if (author !== null && !this.patchSetMetadata[newPatchSetPath].authors.includes(author)) {
8075
+ this.patchSetMetadata[newPatchSetPath].authors.unshift(author);
8076
+ }
8077
+ this.patchSetMetadata[newPatchSetPath].lastUpdatedBy = author;
8078
+ this.patchSetMetadata[newPatchSetPath].lastUpdated = createdAt;
8079
+ if (!this.patchSetMetadata[newPatchSetPath].opTypes.includes(opType)) {
8080
+ this.patchSetMetadata[newPatchSetPath].opTypes.unshift(opType);
8081
+ }
8082
+ this.patchSetMetadata[newPatchSetPath].patches.unshift({
8083
+ patchPath: opPath,
8084
+ patchId: patchId,
8085
+ author: author,
8086
+ createdAt: createdAt,
8087
+ opType: opType,
8088
+ schemaTypes: schemaTypes
8089
+ });
8090
+ if (!this.orderedInsertKeys.includes(newPatchSetPath)) {
8091
+ this.orderedInsertKeys.unshift(newPatchSetPath);
8092
+ }
8093
+ }
8094
+
8095
+ /**
8096
+ * Insert a whole patch.
8097
+ *
8098
+ * Takes the patch rather than one op because the de-duplication below is
8099
+ * per-*patch*: a patch is either known to this instance or it is not. When this
8100
+ * took a single op, callers looped and every call after the first hit the
8101
+ * `insertedPatches` guard and returned — so only a patch's first op ever reached
8102
+ * a patch set. A patch that touched two places (a `move`, or a `file` op sitting
8103
+ * before its source op) was therefore mis-grouped, which is invisible in the
8104
+ * compare view but decides what moves as one.
8105
+ */
8106
+ }, {
8107
+ key: "insert",
8108
+ value: function insert(moduleFilePath, schema, patch, patchId, createdAt, author) {
8109
+ if (this.insertedPatches.has(patchId)) {
8110
+ return;
8111
+ }
8112
+ // Marked inserted unconditionally, schema or not. An earlier revision of this
8113
+ // fix only marked it once a schema was available, so that a patch grouped
8114
+ // under the whole-module fallback could be re-inserted later with the real
8115
+ // schema. That is no longer this class's problem: `PatchSetChain` invalidates
8116
+ // on `schema:init` and a rebuild calls `reset()`, which clears this set — so
8117
+ // the fallback is already re-derived from scratch when the schema lands, and a
8118
+ // conditional here would only leave the per-patch de-duplication half-applied.
8119
+ this.insertedPatches.add(patchId);
8120
+ var _iterator2 = _createForOfIteratorHelper(patch),
8121
+ _step2;
8122
+ try {
8123
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
8124
+ var op = _step2.value;
8125
+ this.insertOp(moduleFilePath, schema, op, patchId, createdAt, author);
8126
+ }
8127
+ } catch (err) {
8128
+ _iterator2.e(err);
8129
+ } finally {
8130
+ _iterator2.f();
8131
+ }
8132
+ }
8133
+ }, {
8134
+ key: "insertOp",
8135
+ value: function insertOp(moduleFilePath, schema, op, patchId, createdAt, author) {
8136
+ if (!schema) {
8137
+ this.insertPath(moduleFilePath, [], patchId, createdAt, author, op.op, [], op.path);
8138
+ return;
8139
+ }
8140
+ if (op.op === "file" || op.op === "test") {
8141
+ return;
8142
+ }
8143
+ try {
8144
+ if (op.op === "replace") {
8145
+ var schemaTypesAtPath = schemaTypesOfPath(schema, op.path);
8146
+ this.insertPath(moduleFilePath, op.path, patchId, createdAt, author, op.op, Array.from(schemaTypesAtPath), op.path);
8147
+ } else if (op.op === "add" || op.op === "remove" || op.op === "move" || op.op === "copy") {
8148
+ // This is the default case, were we, to be sure, take the parent of the path and as the patch set
8149
+ var path = op.path.slice(0, -1);
8150
+ var _schemaTypesAtPath = schemaTypesOfPath(schema, path);
8151
+ if (_schemaTypesAtPath.size === 1 && _schemaTypesAtPath.has("array")) {
8152
+ // for arrays we would need a lot of logic to create a patch set that is not on the entire parent so for now we do just that
8153
+ this.insertPath(moduleFilePath, path, patchId, createdAt, author, op.op, Array.from(_schemaTypesAtPath), op.path);
8154
+ if (op.op === "move" || op.op === "copy") {
8155
+ // `copy` as well as `move`: it does not write the source, but it
8156
+ // READS it, so the value it produces depends on every pending edit
8157
+ // to that source and on the indices around it.
8158
+ var _path = op.from.slice(0, -1);
8159
+ var _schemaTypesAtPath2 = schemaTypesOfPath(schema, _path);
8160
+ this.insertPath(moduleFilePath, _path, patchId, createdAt, author, op.op, Array.from(_schemaTypesAtPath2), op.path);
8161
+ }
8162
+ } else if (_schemaTypesAtPath.size === 1 && (_schemaTypesAtPath.has("record") ||
8163
+ // An OBJECT is keyed too: its keys are named rather than
8164
+ // positional, so neither `add` (create-or-set, `addToNode` in
8165
+ // `@valbuild/core/patch`) nor `remove` (delete the property)
8166
+ // disturbs any sibling. Either way the op affects exactly the key
8167
+ // it names and nothing else, which is the property this branch
8168
+ // needs — unlike an array, where both shift every later index.
8169
+ //
8170
+ // The studio emits `add` rather than `replace` here on purpose, so
8171
+ // that the write survives the key having gone away in the meantime:
8172
+ // see `ImageField`'s alt write and
8173
+ // `ModuleGallery.handleAltTextChange`, which both say so.
8174
+ //
8175
+ // That last one is why this branch exists. `s.imagedir()`
8176
+ // serializes as a record whose ITEM is an object, so editing the
8177
+ // alt text of a gallery entry resolves `object` here, hit the throw
8178
+ // below, and terminated the whole media module into one patch set —
8179
+ // once per keystroke. Moving any one change in that module then
8180
+ // dragged every other change in it along, because changes move a
8181
+ // whole patch set at a time.
8182
+ _schemaTypesAtPath.has("object") ||
8183
+ // A settings SECTION is addressed like a record: its keys are
8184
+ // named, and an `add` at ["theme", "accent"] modifies exactly that
8185
+ // one. Without this it fell to the throw below — every settings
8186
+ // edit terminated the whole module into one patch set, which is why
8187
+ // the publish diff said "Settings" where `settingsChangeLabels` has
8188
+ // a name for the field. Both sections write `add` this way; see
8189
+ // `useWriteAssistantSetting`, which has to create an absent section
8190
+ // in a single op.
8191
+ _schemaTypesAtPath.has("settings"))) {
8192
+ // If we know this is a record, we can be more specific and only insert the path that is being modified
8193
+ var _path2 = op.path;
8194
+ var _schemaTypesAtPath3 = schemaTypesOfPath(schema, _path2);
8195
+ this.insertPath(moduleFilePath, _path2, patchId, createdAt, author, op.op, Array.from(_schemaTypesAtPath3), op.path);
8196
+ if (op.op === "move" || op.op === "copy") {
8197
+ // The SOURCE is classified on its own terms, not the
8198
+ // destination's. A move out of an array item shifts every later
8199
+ // index, so that side has to be the array — exactly as the branch
8200
+ // above does for a move whose destination is an array. Only when
8201
+ // the source parent is keyed too does `op.from` name the whole of
8202
+ // what the op affects.
8203
+ //
8204
+ // `copy` reaches here as well as `move`. It does not write the
8205
+ // source, but the value it produces is read from it, so it depends
8206
+ // on every pending edit to that source just as a move does.
8207
+ // Duplicating a record entry (`useDuplicateRecordEntry`) is
8208
+ // the copy that actually ships, and its source went ungrouped.
8209
+ var fromParent = op.from.slice(0, -1);
8210
+ var fromParentTypes = schemaTypesOfPath(schema, fromParent);
8211
+ // ANY possible array parent widens, rather than only an
8212
+ // unambiguous one: a discriminated union resolves to every
8213
+ // variant's type at once, so a source inside one can be an array
8214
+ // here and an object there. Requiring a single type grouped it at
8215
+ // the item, which is wrong the moment the array variant is the
8216
+ // live one — and the whole array is the safe direction.
8217
+ var isPositionalSource = fromParentTypes.has("array");
8218
+ var _path3 = isPositionalSource ? fromParent : op.from;
8219
+ var _schemaTypesAtPath4 = schemaTypesOfPath(schema, _path3);
8220
+ this.insertPath(moduleFilePath, _path3, patchId, createdAt, author, op.op, Array.from(_schemaTypesAtPath4), op.path);
8221
+ }
8222
+ } else if (_schemaTypesAtPath.size === 1 && !(_schemaTypesAtPath.has("image") || _schemaTypesAtPath.has("file"))) {
8223
+ // What is left is a parent this function cannot isolate a key
8224
+ // inside. Two different reasons end up here, and the message covers
8225
+ // both: a PRIMITIVE cannot hold the key at all, which means the path
8226
+ // no longer fits the schema — a genuinely stale patch; and `richtext`
8227
+ // can, but its children are positional, so isolating one would let a
8228
+ // node insert be moved without the edits whose indices it shifted.
8229
+ // Both keep reporting, and the catch below terminates the module,
8230
+ // which is the conservative thing to do when we cannot say what a
8231
+ // change affects.
8232
+ throw new Error("Cannot isolate a patch set for op: '".concat(op.op, "' \u2014 no addressable key inside schema type: ").concat(_schemaTypesAtPath.values().next().value));
8233
+ } else {
8234
+ // we cannot really know if this is a record or array so the entire module is the patch set
8235
+ this.insertPath(moduleFilePath, path, patchId, createdAt, author, op.op, [schema.type], op.path);
8236
+ }
8237
+ } else {
8238
+ var _unreachable = op;
8239
+ throw new Error("Unreachable op: " + _unreachable);
8240
+ }
8241
+ } catch (e) {
8242
+ // We might be in this situation if the schema changes, etc etc:
8243
+ if (e instanceof Error) {
8244
+ console.error("Could not resolve path while creating patch set", e.message);
8245
+ } else {
8246
+ console.error("Could not resolve path while creating patch set", e);
8247
+ }
8248
+ // "terminate" the entire module file path (i.e. all patches are their own patch set)
8249
+ this.insertPath(moduleFilePath, [], patchId, createdAt, author, op.op, [schema.type], op.path);
8250
+ }
8251
+ }
8252
+ }, {
8253
+ key: "isInserted",
8254
+ value: function isInserted(patchId) {
8255
+ return this.insertedPatches.has(patchId);
8256
+ }
8257
+ }, {
8258
+ key: "serialize",
8259
+ value: function serialize() {
8260
+ var _this = this;
8261
+ return this.orderedInsertKeys.map(function (key) {
8262
+ if (key in _this.patchSetMetadata) {
8263
+ return _this.patchSetMetadata[key];
8264
+ } else {
8265
+ throw new Error("Could not find patch set metadata or patch metadata for (inserted) patch set path: ".concat(key));
8266
+ }
8267
+ });
8268
+ }
8269
+ }]);
8270
+ }();
8271
+
8272
+ /**
8273
+ * Update from the site, for a proposal with code (valbuild/home
8274
+ * `docs/hosted-publishing.md` step 8.2, slice 1b): what content hands over,
8275
+ * what the builder tab makes of it, and what Val's server reads -- one
8276
+ * definition of each for the three.
8277
+ */
8278
+
8279
+ /** Content a schema does not allow, by path in the module. */
8280
+
8281
+ /** Content's `merge-trees` answer. */
8282
+
8283
+ /** Which tree: where the proposal started, the site, or the proposal. */
8284
+
8285
+ /** A module, as evaluating its tree in the tab gave it. */
8286
+
8287
+ /** A side's files: the site's tree, the base's changes over it, the proposal's over that. */
8288
+ function sideFiles(trees, side) {
8289
+ var layers = side === "site" ? [] : side === "base" ? [trees.trees.base] : [trees.trees.base, trees.trees.proposal];
8290
+ var files = _objectSpread2({}, trees.trees.site);
8291
+ for (var _i = 0, _layers = layers; _i < _layers.length; _i++) {
8292
+ var layer = _layers[_i];
8293
+ for (var _i2 = 0, _Object$entries = Object.entries(layer); _i2 < _Object$entries.length; _i2++) {
8294
+ var _Object$entries$_i = _slicedToArray(_Object$entries[_i2], 2),
8295
+ path = _Object$entries$_i[0],
8296
+ text = _Object$entries$_i[1];
8297
+ if (text === null) delete files[path];else files[path] = text;
8298
+ }
8299
+ }
8300
+ return files;
8301
+ }
8302
+
8303
+ /** A side's Source of a module, from content's index; `null` when it has none. */
8304
+ function sideSource(trees, side, moduleFilePath) {
8305
+ var _trees$modules$module, _trees$modules$module2, _trees$sources$sha;
8306
+ var sha = (_trees$modules$module = (_trees$modules$module2 = trees.modules[moduleFilePath]) === null || _trees$modules$module2 === void 0 ? void 0 : _trees$modules$module2[side]) !== null && _trees$modules$module !== void 0 ? _trees$modules$module : null;
8307
+ return sha === null ? null : (_trees$sources$sha = trees.sources[sha]) !== null && _trees$sources$sha !== void 0 ? _trees$sources$sha : null;
8308
+ }
8309
+
8310
+ /**
8311
+ * What a schema reports about this content, without the errors the server
8312
+ * fixes on its own (those with `fixes`): run on the schema instance that
8313
+ * evaluating the module made, so custom rules take part.
8314
+ */
8315
+ function schemaErrorsOf(schema, moduleFilePath, source) {
8316
+ var res = schema["executeValidate"](moduleFilePath, source);
8317
+ if (res === false) return [];
8318
+ var errors = [];
8319
+ for (var _i3 = 0, _Object$entries2 = Object.entries(res); _i3 < _Object$entries2.length; _i3++) {
8320
+ var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i3], 2),
8321
+ sourcePath = _Object$entries2$_i[0],
8322
+ list = _Object$entries2$_i[1];
8323
+ var _Internal$splitModule = Internal.splitModuleFilePathAndModulePath(sourcePath),
8324
+ _Internal$splitModule2 = _slicedToArray(_Internal$splitModule, 2),
8325
+ modulePath = _Internal$splitModule2[1];
8326
+ var path = modulePath ? Internal.createPatchPath(modulePath) : [];
8327
+ var _iterator = _createForOfIteratorHelper(list),
8328
+ _step;
8329
+ try {
8330
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
8331
+ var error = _step.value;
8332
+ if (error.fixes && error.fixes.length > 0) continue;
8333
+ errors.push({
8334
+ path: path,
8335
+ message: error.message
8336
+ });
8337
+ }
8338
+ } catch (err) {
8339
+ _iterator.e(err);
8340
+ } finally {
8341
+ _iterator.f();
8342
+ }
8343
+ }
8344
+ return errors;
8345
+ }
8346
+
8347
+ export { AA_LARGE, AA_TEXT, Api, BRAND_CONTRAST_PAIRS, BinaryFileRef, CodeOptions, ColorOptions, DEFAULT_ERROR_MESSAGE, DateOptions, ENCODE_DEFAULTS, ENCODE_MIME_TYPE_OF, FileOptions, HistoricalCommit, HistoricalModule, HistoricalPatchSet, HistoryError, ImageEncodeOption, ImageOptions, JSONValue, JSON_ENTRIES_BATCH_MAX, ModuleComparison, NEVER_ENCODED, ParentRef$1 as ParentRef, Patch, PatchBlock, PatchId, PatchJSON, PatchSets, PlanRefusalError, PublishProtocolError, RAMP_STEPS, RemirrorBr, RemirrorBulletList, RemirrorHeading, RemirrorImage, RemirrorJSON, RemirrorLinkMark, RemirrorListItem, RemirrorOrderedList, RemirrorParagraph, RemirrorText, RemirrorTextMark, RestoreVerdict, RichTextOptions, SCHEMA_SOURCE_FIXES, SerializedArraySchema, SerializedBooleanSchema, SerializedCodeSchema, SerializedColorSchema, SerializedDateSchema, SerializedDateTimeSchema, SerializedDiscriminatedUnionSchema, SerializedEnumSchema, SerializedFileSchema, SerializedImageSchema, SerializedKeyOfSchema, SerializedLiteralSchema, SerializedLocaleSchema, SerializedNumberSchema, SerializedObjectSchema, SerializedRecordSchema, SerializedRichTextSchema, SerializedRouteSchema, SerializedSchema, SerializedSettingsSchema, SerializedStringSchema, SerializedValViewSchema, SerializedVideoSchema, SharedValConfig, VAL_ENABLE_COOKIE_NAME, VAL_GREEN_RAMP, VAL_SESSION_COOKIE, VAL_STATE_COOKIE, VAL_STUDIO_HEADER, ValCommit, ValDeployment, VideoOptions, VideoStreamOption, accentRamp, buildDuplicatePatch, buildEmptyAtPathPatch, buildFileRefValue, buildImageGalleryPatch, buildRemoveImageGalleryEntryPatch, buildSearchIndex, chainHeadOf, checkCompatibility, chooseEncoded, concatModulePath, contrastRatio, createRegExpFromPattern, createSearchIndex, createValClient, declaredLocales, describeContainerAtPath, emptyOf, explainIncompatible, filterBlockingValidationErrors, filterRoutesByPatterns, findSimilar, fitWithin, flattenRichText, forEachRichTextImage, getErrorMessageFromUnknownJson, getFilenameFromRef, getInlineImgInfo, getKeyOfRecordAt, getRefParts, getRoutesOf, getRoutesWithModulePaths, getSourceAt, indexModule, isInsidePatchSetPath, isMimeTypeAccepted, isRemoteSchema, isSchemaSourceFixError, isSkippedSource, keyOfRecordPath, levenshtein, localeAt, memoizePerRequest, newestCommitSha, parseArtifacts, parseBuildTarget, parseCancel, parseDeclare, parseDiscard, parseJob, parseNewestCiRun, parsePress, parseProblems, parseProjectSource, parsePromote, parsePublishToken, parseRenew, parseRequestStatus, parseStatus, parseUpdateTarget, parseVerify, partitionValidationErrors, performSearch, relativeLuminance, remirrorToRichTextSource, removeModule, resolveEncodeSettings, resolvePairGround, resolveSchemaSourceFixForError, resolveSchemaSourceFixes, resolveSerializedSchemaAtPath, richTextImageSchema, richTextToRemirror, safeParsePatch, schemaErrorsOf, schemaTypesOfPath, sideFiles, sideSource, sourcePathOfChild, themeCustomProperties, toolNames, traverseSchemaSource, urlOf, validateRoutePatterns, withExtension };