@cms0/cms0 0.2.17 → 0.2.19

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.
Files changed (49) hide show
  1. package/dist/cjs/descriptor-sidecar.cjs +20 -0
  2. package/dist/cjs/generated/schema-descriptor.cjs +3 -0
  3. package/dist/cjs/index.cjs +135 -29
  4. package/dist/cjs/libs/cli/browser-sidecar.cjs +56 -0
  5. package/dist/cjs/libs/cli/build.cjs +2 -2
  6. package/dist/cjs/libs/cli/cli.cjs +8 -3
  7. package/dist/cjs/libs/cli/config-loader.cjs +19 -33
  8. package/dist/cjs/libs/cli/descriptor-writer.cjs +21 -9
  9. package/dist/cjs/libs/cli/paths.cjs +7 -0
  10. package/dist/cjs/libs/cli/watcher.cjs +5 -3
  11. package/dist/cjs/provenance.cjs +80 -10
  12. package/dist/cjs/schema-descriptors.cjs +265 -2
  13. package/dist/esm/descriptor-sidecar.js +16 -0
  14. package/dist/esm/generated/schema-descriptor.js +3 -0
  15. package/dist/esm/index.js +134 -30
  16. package/dist/esm/libs/cli/browser-sidecar.js +51 -0
  17. package/dist/esm/libs/cli/build.js +2 -2
  18. package/dist/esm/libs/cli/cli.js +8 -3
  19. package/dist/esm/libs/cli/config-loader.js +20 -34
  20. package/dist/esm/libs/cli/descriptor-writer.js +21 -11
  21. package/dist/esm/libs/cli/paths.js +7 -1
  22. package/dist/esm/libs/cli/watcher.js +5 -3
  23. package/dist/esm/provenance.js +78 -10
  24. package/dist/esm/schema-descriptors.js +261 -1
  25. package/dist/types/descriptor-sidecar.d.ts +5 -0
  26. package/dist/types/descriptor-sidecar.d.ts.map +1 -0
  27. package/dist/types/generated/schema-descriptor.d.ts +3 -0
  28. package/dist/types/generated/schema-descriptor.d.ts.map +1 -1
  29. package/dist/types/index.d.ts +1 -1
  30. package/dist/types/index.d.ts.map +1 -1
  31. package/dist/types/libs/cli/browser-sidecar.d.ts +9 -0
  32. package/dist/types/libs/cli/browser-sidecar.d.ts.map +1 -0
  33. package/dist/types/libs/cli/build.d.ts +2 -1
  34. package/dist/types/libs/cli/build.d.ts.map +1 -1
  35. package/dist/types/libs/cli/cli.d.ts.map +1 -1
  36. package/dist/types/libs/cli/config-loader.d.ts.map +1 -1
  37. package/dist/types/libs/cli/descriptor-writer.d.ts +11 -2
  38. package/dist/types/libs/cli/descriptor-writer.d.ts.map +1 -1
  39. package/dist/types/libs/cli/paths.d.ts +5 -1
  40. package/dist/types/libs/cli/paths.d.ts.map +1 -1
  41. package/dist/types/libs/cli/types.d.ts +1 -0
  42. package/dist/types/libs/cli/types.d.ts.map +1 -1
  43. package/dist/types/libs/cli/watcher.d.ts +2 -1
  44. package/dist/types/libs/cli/watcher.d.ts.map +1 -1
  45. package/dist/types/provenance.d.ts +3 -0
  46. package/dist/types/provenance.d.ts.map +1 -1
  47. package/dist/types/schema-descriptors.d.ts +12 -1
  48. package/dist/types/schema-descriptors.d.ts.map +1 -1
  49. package/package.json +4 -3
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getCms0DescriptorSidecarPort = getCms0DescriptorSidecarPort;
4
+ exports.getCms0DescriptorSidecarUrl = getCms0DescriptorSidecarUrl;
5
+ exports.hashCms0SidecarSeed = hashCms0SidecarSeed;
6
+ function hashCms0SidecarSeed(seed) {
7
+ let hash = 5381;
8
+ for (let index = 0; index < seed.length; index += 1) {
9
+ hash = ((hash << 5) + hash + seed.charCodeAt(index)) >>> 0;
10
+ }
11
+ return hash >>> 0;
12
+ }
13
+ function getCms0DescriptorSidecarPort(baseUrl, apiKey) {
14
+ const seed = `${baseUrl?.trim() ?? ""}|${apiKey?.trim() ?? ""}`;
15
+ return 43129 + (hashCms0SidecarSeed(seed) % 1000);
16
+ }
17
+ function getCms0DescriptorSidecarUrl(baseUrl, apiKey) {
18
+ const port = getCms0DescriptorSidecarPort(baseUrl, apiKey);
19
+ return `http://127.0.0.1:${port}/schema-descriptor`;
20
+ }
@@ -5,4 +5,7 @@ exports.schemaDescriptor = void 0;
5
5
  exports.schemaDescriptor = {
6
6
  models: {},
7
7
  roots: {},
8
+ metadata: {
9
+ __cms0Fallback: true,
10
+ },
8
11
  };
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.toTwitter = exports.toOpenGraph = exports.toNextMetadata = exports.resolveLocalized = exports.unwrapCms0CanvasTransportValue = exports.restoreCms0CanvasTransportMetadata = exports.readCms0ProvenanceValueMeta = exports.readCms0LiveRoots = exports.registerCms0CollectionItemIdentity = exports.registerCms0LiveRoot = exports.readCms0CollectionItemIdentity = exports.readCms0CanvasTransportCollectionItemId = exports.enableCms0ProvenanceTracking = exports.captureCms0Provenance = exports.attachCms0ProvenanceRoot = exports.activateCms0CanvasTransport = void 0;
3
+ exports.toTwitter = exports.toOpenGraph = exports.toNextMetadata = exports.resolveLocalized = exports.unwrapCms0CanvasTransportValue = exports.restoreCms0CanvasTransportMetadata = exports.readCms0ProvenanceValueMeta = exports.readCms0LiveRoots = exports.registerCms0CollectionItemIdentity = exports.registerCms0LiveRoot = exports.readCms0CollectionItemIdentity = exports.readCms0CanvasTransportCollectionItemId = exports.enableCms0ProvenanceTracking = exports.dehydrateCms0CanvasVisibleValue = exports.dehydrateCms0CanvasTransportValue = exports.captureCms0Provenance = exports.attachCms0ProvenanceRoot = exports.activateCms0CanvasTransport = void 0;
4
4
  exports.createCmsClient = createCmsClient;
5
5
  exports.cms0 = cms0;
6
6
  const provenance_1 = require("@cms0/cms0/provenance");
@@ -552,7 +552,7 @@ async function readCanvasModelRefCollectionIdentities(path, descriptor, context)
552
552
  cache.set(cacheKey, pending);
553
553
  return pending;
554
554
  }
555
- async function normalizeModelRef(modelName, id, context, trail, isCollectionItem, inlineValue) {
555
+ async function normalizeModelRef(modelName, id, context, trail, isCollectionItem, inlineValue, projectionPathTokens = []) {
556
556
  if (!id)
557
557
  return null;
558
558
  if (!context.options.resolveModelRefs)
@@ -580,14 +580,29 @@ async function normalizeModelRef(modelName, id, context, trail, isCollectionItem
580
580
  const nextTrail = new Set(trail);
581
581
  nextTrail.add(nodeKey);
582
582
  const promise = (async () => {
583
+ const modelPath = `models/${modelName}/${id}`;
584
+ const resolvedModelPath = `_resolved/models/${encodeURIComponent(modelName)}/${encodeURIComponent(id)}`;
583
585
  const rawModel = inlineModel ??
584
- (await context.requestJson(`models/${modelName}/${id}`, {
585
- query: {
586
+ (await (async () => {
587
+ const query = {
586
588
  raw: 1,
587
589
  ...(context.options.locale ? { locale: context.options.locale } : {}),
588
- },
589
- }));
590
- return normalizeField(modelDescriptor, `models/${modelName}/${encodeURIComponent(id)}`, rawModel, context, nextTrail, isCollectionItem);
590
+ };
591
+ try {
592
+ return await context.requestJson(resolvedModelPath, {
593
+ query: {
594
+ ...query,
595
+ resolveModelRefs: 1,
596
+ },
597
+ });
598
+ }
599
+ catch {
600
+ return context.requestJson(modelPath, {
601
+ query,
602
+ });
603
+ }
604
+ })());
605
+ return normalizeField(modelDescriptor, `models/${modelName}/${encodeURIComponent(id)}`, rawModel, context, nextTrail, isCollectionItem, projectionPathTokens);
591
606
  })();
592
607
  context.modelCache.set(nodeKey, promise);
593
608
  context.sharedModelInflightCache.set(nodeKey, promise);
@@ -607,12 +622,16 @@ function missingModelRefValue(descriptor) {
607
622
  return undefined;
608
623
  return null;
609
624
  }
610
- async function normalizeObjectField(descriptor, path, raw, context, trail, isCollectionItem) {
625
+ async function normalizeObjectField(descriptor, path, raw, context, trail, isCollectionItem, projectionPathTokens = []) {
611
626
  const source = raw && typeof raw === "object" ? raw : {};
612
627
  const output = {};
613
628
  for (const [propertyName, propertyDescriptor] of Object.entries(descriptor.properties)) {
629
+ const childProjectionPathTokens = [...projectionPathTokens, propertyName];
630
+ if (!shouldTraverseProjectionPath(childProjectionPathTokens, context.options.includeProjectionPaths, context.options.excludeProjectionPaths)) {
631
+ continue;
632
+ }
614
633
  if (isScalarDescriptor(propertyDescriptor)) {
615
- output[propertyName] = await normalizeField(propertyDescriptor, `${path}/${propertyName}`, source[propertyName], context, trail, false);
634
+ output[propertyName] = await normalizeField(propertyDescriptor, `${path}/${propertyName}`, source[propertyName], context, trail, false, childProjectionPathTokens);
616
635
  continue;
617
636
  }
618
637
  if (isModelRefDescriptor(propertyDescriptor)) {
@@ -636,7 +655,7 @@ async function normalizeObjectField(descriptor, path, raw, context, trail, isCol
636
655
  }
637
656
  continue;
638
657
  }
639
- output[propertyName] = await normalizeModelRef(propertyDescriptor.model, refId, context, trail, false, inlineValue);
658
+ output[propertyName] = await normalizeModelRef(propertyDescriptor.model, refId, context, trail, false, inlineValue, childProjectionPathTokens);
640
659
  continue;
641
660
  }
642
661
  if (isArrayDescriptor(propertyDescriptor)) {
@@ -654,7 +673,7 @@ async function normalizeObjectField(descriptor, path, raw, context, trail, isCol
654
673
  ...(context.options.locale ? { locale: context.options.locale } : {}),
655
674
  },
656
675
  });
657
- const normalizedChild = await normalizeArrayField(propertyDescriptor, childPath, childRaw, context, trail, inlineChildRaw !== undefined);
676
+ const normalizedChild = await normalizeArrayField(propertyDescriptor, childPath, childRaw, context, trail, inlineChildRaw !== undefined, childProjectionPathTokens);
658
677
  output[propertyName] = coerceCustomTypeValue(propertyDescriptor, normalizedChild, {
659
678
  locale: context.options.locale,
660
679
  defaultLocale: context.options.defaultLocale,
@@ -677,7 +696,7 @@ async function normalizeObjectField(descriptor, path, raw, context, trail, isCol
677
696
  ...(context.options.locale ? { locale: context.options.locale } : {}),
678
697
  },
679
698
  });
680
- const normalizedChild = await normalizeObjectField(propertyDescriptor, childPath, childRaw, context, trail, false);
699
+ const normalizedChild = await normalizeObjectField(propertyDescriptor, childPath, childRaw, context, trail, false, childProjectionPathTokens);
681
700
  output[propertyName] = coerceCustomTypeValue(propertyDescriptor, normalizedChild, {
682
701
  locale: context.options.locale,
683
702
  defaultLocale: context.options.defaultLocale,
@@ -697,12 +716,12 @@ async function normalizeObjectField(descriptor, path, raw, context, trail, isCol
697
716
  }
698
717
  return maybeAttachAssetUrl(output, context.options.assetUrlBuilder);
699
718
  }
700
- async function normalizeArrayField(descriptor, path, raw, context, trail, inlineResolvedItems = false) {
719
+ async function normalizeArrayField(descriptor, path, raw, context, trail, inlineResolvedItems = false, projectionPathTokens = []) {
701
720
  const envelope = ensureCollectionEnvelope(raw, path);
702
721
  const itemDescriptor = descriptor.items;
703
722
  if (isScalarDescriptor(itemDescriptor)) {
704
723
  return mapWithConcurrency(envelope.items, context.options.modelNormalizationConcurrency, async (row) => {
705
- const normalizedValue = await normalizeField(itemDescriptor, path, row, context, trail, true);
724
+ const normalizedValue = await normalizeField(itemDescriptor, path, row, context, trail, true, projectionPathTokens);
706
725
  if (context.options.includeIdMode !== "all") {
707
726
  return normalizedValue;
708
727
  }
@@ -725,7 +744,7 @@ async function normalizeArrayField(descriptor, path, raw, context, trail, inline
725
744
  const refId = extractModelRefId(row, itemDescriptor.model, {
726
745
  allowObjectIdFallback: false,
727
746
  }) ?? (inlineModel ? extractId(inlineModel) : null);
728
- const normalized = await normalizeModelRef(itemDescriptor.model, refId, context, trail, true, row);
747
+ const normalized = await normalizeModelRef(itemDescriptor.model, refId, context, trail, true, row, projectionPathTokens);
729
748
  const collectionItemId = collectionIdentities?.[index]?.relationId ??
730
749
  (inlineResolvedItems ? null : extractId(row));
731
750
  if (!collectionItemId ||
@@ -748,12 +767,12 @@ async function normalizeArrayField(descriptor, path, raw, context, trail, inline
748
767
  const rowPath = rowId
749
768
  ? `${path}/${encodeURIComponent(rowId)}`
750
769
  : path;
751
- return normalizeObjectField(itemDescriptor, rowPath, row, context, trail, true);
770
+ return normalizeObjectField(itemDescriptor, rowPath, row, context, trail, true, projectionPathTokens);
752
771
  });
753
772
  }
754
773
  return envelope.items;
755
774
  }
756
- async function normalizeInlineField(descriptor, raw, context, trail, isCollectionItem) {
775
+ async function normalizeInlineField(descriptor, raw, context, trail, isCollectionItem, projectionPathTokens = []) {
757
776
  if (isPrimitiveDescriptor(descriptor)) {
758
777
  return coerceCustomTypeValue(descriptor, raw, {
759
778
  locale: context.options.locale,
@@ -771,7 +790,7 @@ async function normalizeInlineField(descriptor, raw, context, trail, isCollectio
771
790
  if (!decoded) {
772
791
  return null;
773
792
  }
774
- return normalizeInlineField(decoded.branchDescriptor, decoded.branchValue, context, trail, isCollectionItem);
793
+ return normalizeInlineField(decoded.branchDescriptor, decoded.branchValue, context, trail, isCollectionItem, projectionPathTokens);
775
794
  }
776
795
  if (isModelRefDescriptor(descriptor)) {
777
796
  const refId = extractModelRefId(raw, descriptor.model, {
@@ -780,11 +799,11 @@ async function normalizeInlineField(descriptor, raw, context, trail, isCollectio
780
799
  if (!refId) {
781
800
  return missingModelRefValue(descriptor);
782
801
  }
783
- return normalizeModelRef(descriptor.model, refId, context, trail, isCollectionItem, raw);
802
+ return normalizeModelRef(descriptor.model, refId, context, trail, isCollectionItem, raw, projectionPathTokens);
784
803
  }
785
804
  if (isArrayDescriptor(descriptor)) {
786
805
  const source = Array.isArray(raw) ? raw : [];
787
- const normalized = await mapWithConcurrency(source, context.options.modelNormalizationConcurrency, async (entry) => normalizeInlineField(descriptor.items, entry, context, trail, true));
806
+ const normalized = await mapWithConcurrency(source, context.options.modelNormalizationConcurrency, async (entry) => normalizeInlineField(descriptor.items, entry, context, trail, true, projectionPathTokens));
788
807
  return coerceCustomTypeValue(descriptor, normalized, {
789
808
  locale: context.options.locale,
790
809
  defaultLocale: context.options.defaultLocale,
@@ -797,7 +816,7 @@ async function normalizeInlineField(descriptor, raw, context, trail, isCollectio
797
816
  : {};
798
817
  const output = {};
799
818
  for (const [propertyName, propertyDescriptor] of Object.entries(descriptor.properties)) {
800
- output[propertyName] = await normalizeInlineField(propertyDescriptor, source[propertyName], context, trail, false);
819
+ output[propertyName] = await normalizeInlineField(propertyDescriptor, source[propertyName], context, trail, false, [...projectionPathTokens, propertyName]);
801
820
  }
802
821
  return coerceCustomTypeValue(descriptor, output, {
803
822
  locale: context.options.locale,
@@ -807,7 +826,7 @@ async function normalizeInlineField(descriptor, raw, context, trail, isCollectio
807
826
  }
808
827
  return raw;
809
828
  }
810
- async function normalizeField(descriptor, path, raw, context, trail, isCollectionItem) {
829
+ async function normalizeField(descriptor, path, raw, context, trail, isCollectionItem, projectionPathTokens = []) {
811
830
  if (isPrimitiveDescriptor(descriptor)) {
812
831
  const value = raw && typeof raw === "object" && "value" in raw
813
832
  ? raw.value
@@ -839,7 +858,7 @@ async function normalizeField(descriptor, path, raw, context, trail, isCollectio
839
858
  if (!decoded) {
840
859
  return null;
841
860
  }
842
- let normalized = await normalizeInlineField(decoded.branchDescriptor, decoded.branchValue, context, trail, isCollectionItem);
861
+ let normalized = await normalizeInlineField(decoded.branchDescriptor, decoded.branchValue, context, trail, isCollectionItem, projectionPathTokens);
843
862
  if (shouldIncludeObjectId(context.options.includeIdMode, isCollectionItem)) {
844
863
  const id = decoded.rowId ?? extractId(raw);
845
864
  normalized = attachIdForScalarDescriptor(descriptor, normalized, id);
@@ -860,7 +879,7 @@ async function normalizeField(descriptor, path, raw, context, trail, isCollectio
860
879
  return normalizeModelRef(descriptor.model, refId, context, trail, isCollectionItem, raw);
861
880
  }
862
881
  if (isArrayDescriptor(descriptor)) {
863
- const normalized = await normalizeArrayField(descriptor, path, raw, context, trail);
882
+ const normalized = await normalizeArrayField(descriptor, path, raw, context, trail, false, projectionPathTokens);
864
883
  return coerceCustomTypeValue(descriptor, normalized, {
865
884
  locale: context.options.locale,
866
885
  defaultLocale: context.options.defaultLocale,
@@ -868,7 +887,7 @@ async function normalizeField(descriptor, path, raw, context, trail, isCollectio
868
887
  });
869
888
  }
870
889
  if (isObjectDescriptor(descriptor)) {
871
- const normalized = await normalizeObjectField(descriptor, path, raw, context, trail, isCollectionItem);
890
+ const normalized = await normalizeObjectField(descriptor, path, raw, context, trail, isCollectionItem, projectionPathTokens);
872
891
  return coerceCustomTypeValue(descriptor, normalized, {
873
892
  locale: context.options.locale,
874
893
  defaultLocale: context.options.defaultLocale,
@@ -983,6 +1002,22 @@ function normalizeProjectionPaths(input) {
983
1002
  }
984
1003
  return Array.from(unique).map((path) => path.split("."));
985
1004
  }
1005
+ function isProjectionPathPrefix(prefix, value) {
1006
+ if (prefix.length > value.length)
1007
+ return false;
1008
+ return prefix.every((token, index) => value[index] === token);
1009
+ }
1010
+ function shouldTraverseProjectionPath(childTokens, includePaths, excludePaths) {
1011
+ if (includePaths.length > 0 &&
1012
+ !includePaths.some((pathTokens) => isProjectionPathPrefix(pathTokens, childTokens) ||
1013
+ isProjectionPathPrefix(childTokens, pathTokens))) {
1014
+ return false;
1015
+ }
1016
+ if (excludePaths.some((pathTokens) => isProjectionPathPrefix(pathTokens, childTokens))) {
1017
+ return false;
1018
+ }
1019
+ return true;
1020
+ }
986
1021
  function mergeProjectedValue(existing, incoming) {
987
1022
  if (incoming === undefined)
988
1023
  return existing;
@@ -1143,6 +1178,9 @@ async function runResource(resource, descriptor, baseUrl, apiKey, defaultLocale,
1143
1178
  const responseMode = options?.response ?? "normalized";
1144
1179
  const includeIdMode = resolveIncludeIdMode(options?.includeId, globalIncludeId);
1145
1180
  const resolveModelRefs = options?.resolveModelRefs !== false;
1181
+ const includeProjectionPaths = normalizeProjectionPaths(options?.fields);
1182
+ const excludeProjectionPaths = normalizeProjectionPaths(options?.exclude);
1183
+ const shouldValidateFullResult = includeProjectionPaths.length === 0 && excludeProjectionPaths.length === 0;
1146
1184
  const requestedLocale = options?.locale ??
1147
1185
  (typeof options?.query?.locale === "string"
1148
1186
  ? options.query.locale
@@ -1235,6 +1273,8 @@ async function runResource(resource, descriptor, baseUrl, apiKey, defaultLocale,
1235
1273
  defaultLocale,
1236
1274
  assetUrlBuilder,
1237
1275
  modelNormalizationConcurrency: DEFAULT_MODEL_NORMALIZATION_CONCURRENCY,
1276
+ includeProjectionPaths,
1277
+ excludeProjectionPaths,
1238
1278
  },
1239
1279
  };
1240
1280
  if (resource.isCollection && !byId) {
@@ -1250,17 +1290,23 @@ async function runResource(resource, descriptor, baseUrl, apiKey, defaultLocale,
1250
1290
  const normalizedItems = await normalizeArrayField(descriptorForCollection, resource.path, envelope, context, new Set());
1251
1291
  if (responseMode === "envelope") {
1252
1292
  const projectedItems = applyFieldProjection(normalizedItems, options?.fields, options?.exclude);
1253
- validateResult(resource, normalizedItems, descriptor, includeIdMode, zodSchemas, modelZodSchemas);
1293
+ if (shouldValidateFullResult) {
1294
+ validateResult(resource, normalizedItems, descriptor, includeIdMode, zodSchemas, modelZodSchemas);
1295
+ }
1254
1296
  return {
1255
1297
  items: attachResourceProvenanceWithOptions(resource, Array.isArray(projectedItems) ? projectedItems : normalizedItems, provenanceOptions),
1256
1298
  total: envelope.total,
1257
1299
  };
1258
1300
  }
1259
- validateResult(resource, normalizedItems, descriptor, includeIdMode, zodSchemas, modelZodSchemas);
1301
+ if (shouldValidateFullResult) {
1302
+ validateResult(resource, normalizedItems, descriptor, includeIdMode, zodSchemas, modelZodSchemas);
1303
+ }
1260
1304
  return attachResourceProvenanceWithOptions(resource, normalizedItems, provenanceOptions);
1261
1305
  }
1262
1306
  const normalized = await normalizeField(resource.descriptor, normalizePath, rawData, context, new Set(), false);
1263
- validateResult(resource, normalized, descriptor, includeIdMode, zodSchemas, modelZodSchemas);
1307
+ if (shouldValidateFullResult) {
1308
+ validateResult(resource, normalized, descriptor, includeIdMode, zodSchemas, modelZodSchemas);
1309
+ }
1264
1310
  return attachResourceProvenanceWithOptions(resource, applyFieldProjection(normalized, options?.fields, options?.exclude), provenanceOptions);
1265
1311
  }
1266
1312
  function createCmsClient(descriptor, config) {
@@ -1345,12 +1391,72 @@ function createCmsClient(descriptor, config) {
1345
1391
  return rootProxy;
1346
1392
  }
1347
1393
  function cms0(config) {
1348
- return createCmsClient(schema_descriptors_1.schemaDescriptor, config);
1394
+ if (typeof window !== "undefined") {
1395
+ return createLazyBrowserCmsClient(config);
1396
+ }
1397
+ return createCmsClient((0, schema_descriptors_1.getActiveSchemaDescriptor)(), config);
1398
+ }
1399
+ function createLazyBrowserCmsClient(config) {
1400
+ let clientPromise = null;
1401
+ const resolveClient = async () => {
1402
+ if (!clientPromise) {
1403
+ clientPromise = (0, schema_descriptors_1.resolveBrowserSchemaDescriptor)(config.apiConfig?.baseUrl, config.apiConfig?.key).then((descriptor) => createCmsClient(descriptor, config));
1404
+ }
1405
+ return clientPromise;
1406
+ };
1407
+ const buildModelAccessor = (property) => {
1408
+ const accessor = (async (options) => {
1409
+ const client = await resolveClient();
1410
+ return client.models[property](options);
1411
+ });
1412
+ accessor.byId = async (id, options) => {
1413
+ const client = await resolveClient();
1414
+ return client.models[property].byId(id, options);
1415
+ };
1416
+ return accessor;
1417
+ };
1418
+ const modelsProxy = new Proxy({}, {
1419
+ get(_target, property) {
1420
+ if (typeof property !== "string")
1421
+ return undefined;
1422
+ if (property === "then")
1423
+ return undefined;
1424
+ return buildModelAccessor(property);
1425
+ },
1426
+ });
1427
+ const clientMeta = {
1428
+ locales: config.locales ?? [],
1429
+ defaultLocale: config.defaultLocale,
1430
+ includeIdDefault: !!config.includeId,
1431
+ };
1432
+ const rootProxyTarget = {
1433
+ models: modelsProxy,
1434
+ meta: clientMeta,
1435
+ };
1436
+ const rootProxy = new Proxy(rootProxyTarget, {
1437
+ get(target, property, receiver) {
1438
+ if (typeof property !== "string") {
1439
+ return Reflect.get(target, property, receiver);
1440
+ }
1441
+ if (property === "then")
1442
+ return undefined;
1443
+ if (Reflect.has(target, property)) {
1444
+ return Reflect.get(target, property, receiver);
1445
+ }
1446
+ return async (options) => {
1447
+ const client = await resolveClient();
1448
+ return client[property](options);
1449
+ };
1450
+ },
1451
+ });
1452
+ return rootProxy;
1349
1453
  }
1350
1454
  var provenance_js_1 = require("./provenance.cjs");
1351
1455
  Object.defineProperty(exports, "activateCms0CanvasTransport", { enumerable: true, get: function () { return provenance_js_1.activateCms0CanvasTransport; } });
1352
1456
  Object.defineProperty(exports, "attachCms0ProvenanceRoot", { enumerable: true, get: function () { return provenance_js_1.attachCms0ProvenanceRoot; } });
1353
1457
  Object.defineProperty(exports, "captureCms0Provenance", { enumerable: true, get: function () { return provenance_js_1.captureCms0Provenance; } });
1458
+ Object.defineProperty(exports, "dehydrateCms0CanvasTransportValue", { enumerable: true, get: function () { return provenance_js_1.dehydrateCms0CanvasTransportValue; } });
1459
+ Object.defineProperty(exports, "dehydrateCms0CanvasVisibleValue", { enumerable: true, get: function () { return provenance_js_1.dehydrateCms0CanvasVisibleValue; } });
1354
1460
  Object.defineProperty(exports, "enableCms0ProvenanceTracking", { enumerable: true, get: function () { return provenance_js_1.enableCms0ProvenanceTracking; } });
1355
1461
  Object.defineProperty(exports, "readCms0CanvasTransportCollectionItemId", { enumerable: true, get: function () { return provenance_js_1.readCms0CanvasTransportCollectionItemId; } });
1356
1462
  Object.defineProperty(exports, "readCms0CollectionItemIdentity", { enumerable: true, get: function () { return provenance_js_1.readCms0CollectionItemIdentity; } });
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.startBrowserDescriptorSidecar = startBrowserDescriptorSidecar;
7
+ const node_http_1 = __importDefault(require("node:http"));
8
+ const descriptor_sidecar_js_1 = require("../../descriptor-sidecar.cjs");
9
+ function startBrowserDescriptorSidecar(resolved, initialDescriptor) {
10
+ const port = (0, descriptor_sidecar_js_1.getCms0DescriptorSidecarPort)(resolved.apiBaseUrl, resolved.apiKey);
11
+ let currentDescriptor = initialDescriptor;
12
+ const server = node_http_1.default.createServer((request, response) => {
13
+ const requestUrl = new URL(request.url ?? "/", `http://127.0.0.1:${port}`);
14
+ response.setHeader("Access-Control-Allow-Origin", "*");
15
+ response.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
16
+ response.setHeader("Access-Control-Allow-Headers", "Content-Type");
17
+ if (request.method === "OPTIONS") {
18
+ response.writeHead(204);
19
+ response.end();
20
+ return;
21
+ }
22
+ if (request.method !== "GET" || requestUrl.pathname !== "/schema-descriptor") {
23
+ response.writeHead(404, { "content-type": "application/json; charset=utf-8" });
24
+ response.end(JSON.stringify({ error: "Not found" }));
25
+ return;
26
+ }
27
+ response.writeHead(200, {
28
+ "content-type": "application/json; charset=utf-8",
29
+ "cache-control": "no-store",
30
+ });
31
+ response.end(JSON.stringify(currentDescriptor));
32
+ });
33
+ return new Promise((resolve, reject) => {
34
+ server.once("error", reject);
35
+ server.listen(port, "127.0.0.1", () => {
36
+ server.off("error", reject);
37
+ console.log(`cms0: browser descriptor sidecar listening on http://127.0.0.1:${port}/schema-descriptor`);
38
+ resolve({
39
+ updateDescriptor(descriptor) {
40
+ currentDescriptor = descriptor;
41
+ },
42
+ close() {
43
+ return new Promise((closeResolve, closeReject) => {
44
+ server.close((error) => {
45
+ if (error) {
46
+ closeReject(error);
47
+ return;
48
+ }
49
+ closeResolve();
50
+ });
51
+ });
52
+ },
53
+ });
54
+ });
55
+ });
56
+ }
@@ -5,9 +5,9 @@ exports.buildOnce = buildOnce;
5
5
  const descriptor_builder_alt_js_1 = require("./descriptor-builder-alt.cjs");
6
6
  const publisher_js_1 = require("./publisher.cjs");
7
7
  const descriptor_writer_js_1 = require("./descriptor-writer.cjs");
8
- function buildOnce(resolved) {
8
+ function buildOnce(resolved, browserTarget = "sidecar") {
9
9
  const descriptor = (0, descriptor_builder_alt_js_1.buildDescriptorAlt)(resolved);
10
- (0, descriptor_writer_js_1.writeDescriptorFiles)(descriptor);
10
+ (0, descriptor_writer_js_1.writeDescriptorFiles)(resolved, descriptor, browserTarget);
11
11
  (0, publisher_js_1.publishDescriptor)(resolved, descriptor);
12
12
  return descriptor;
13
13
  }
@@ -4,6 +4,7 @@ exports.runFromCli = runFromCli;
4
4
  // CLI entry point: parse arguments, load config, and trigger build/watch modes.
5
5
  const url_1 = require("url");
6
6
  const build_js_1 = require("./build.cjs");
7
+ const browser_sidecar_js_1 = require("./browser-sidecar.cjs");
7
8
  const config_loader_js_1 = require("./config-loader.cjs");
8
9
  const watcher_js_1 = require("./watcher.cjs");
9
10
  async function runFromCli() {
@@ -29,14 +30,18 @@ async function runFromCli() {
29
30
  const resolved = (0, config_loader_js_1.resolvePaths)(loaded.path, loaded.config);
30
31
  console.log("resolved: ", resolved);
31
32
  if (mode === "watch") {
32
- (0, watcher_js_1.startWatcher)(resolved);
33
+ const descriptor = (0, build_js_1.buildOnce)(resolved, "sidecar");
34
+ const sidecar = await (0, browser_sidecar_js_1.startBrowserDescriptorSidecar)(resolved, descriptor);
35
+ (0, watcher_js_1.startWatcher)(resolved, (nextDescriptor) => sidecar.updateDescriptor(nextDescriptor), "sidecar", false);
33
36
  return;
34
37
  }
35
38
  if (mode === "dev") {
36
- (0, watcher_js_1.startWatcher)(resolved);
39
+ const descriptor = (0, build_js_1.buildOnce)(resolved, "sidecar");
40
+ const sidecar = await (0, browser_sidecar_js_1.startBrowserDescriptorSidecar)(resolved, descriptor);
41
+ (0, watcher_js_1.startWatcher)(resolved, (nextDescriptor) => sidecar.updateDescriptor(nextDescriptor), "sidecar", false);
37
42
  return;
38
43
  }
39
- (0, build_js_1.buildOnce)(resolved);
44
+ (0, build_js_1.buildOnce)(resolved, "bundle");
40
45
  }
41
46
  // ESM/CJS-safe main check without import.meta syntax in the source so CJS builds succeed.
42
47
  const isDirectRun = (() => {
@@ -114,38 +114,20 @@ async function loadUserConfig(configPath) {
114
114
  return { path: resolvedPath, config: JSON.parse(json) };
115
115
  }
116
116
  if (ext === ".ts" || ext === ".mts" || ext === ".cts" || ext === ".tsx") {
117
- // If the enclosing package is ESM, use dynamic import instead of require.
118
117
  const pkgJsonPath = findNearestPackageJson(resolvedPath);
119
118
  const pkgType = pkgJsonPath ? readPackageType(pkgJsonPath) : undefined;
120
119
  const isEsmPkg = pkgType === "module";
121
- if (isEsmPkg) {
122
- const compiledHref = await transpileTsModuleToTemp(resolvedPath);
123
- try {
124
- const imported = (await importByHref(compiledHref));
125
- const config = imported?.default ?? imported?.config ?? imported ?? {};
126
- return { path: resolvedPath, config };
127
- }
128
- finally {
129
- cleanupTempModule(compiledHref);
130
- }
131
- }
132
- const previous = process.env.TS_NODE_COMPILER_OPTIONS;
133
- // register ts-node on demand so TypeScript configs can be required
134
- // eslint-disable-next-line @typescript-eslint/no-var-requires
135
- require("ts-node/register/transpile-only");
120
+ const compiledPath = await transpileTsModuleToTemp(resolvedPath, isEsmPkg ? "esm" : "cjs");
136
121
  try {
137
- // eslint-disable-next-line @typescript-eslint/no-var-requires
138
- const required = require(resolvedPath);
139
- const config = required?.default ?? required?.config ?? required ?? {};
122
+ const imported = isEsmPkg
123
+ ? (await importByHref((0, url_1.pathToFileURL)(compiledPath).href))
124
+ : // eslint-disable-next-line @typescript-eslint/no-var-requires
125
+ require(compiledPath);
126
+ const config = imported?.default ?? imported?.config ?? imported ?? {};
140
127
  return { path: resolvedPath, config };
141
128
  }
142
129
  finally {
143
- if (previous === undefined) {
144
- delete process.env.TS_NODE_COMPILER_OPTIONS;
145
- }
146
- else {
147
- process.env.TS_NODE_COMPILER_OPTIONS = previous;
148
- }
130
+ cleanupTempModule(compiledPath);
149
131
  }
150
132
  }
151
133
  const imported = (await importByHref((0, url_1.pathToFileURL)(resolvedPath).href));
@@ -162,6 +144,10 @@ function resolvePaths(cfgPath, config) {
162
144
  throw new Error("cms0: config.entry is required");
163
145
  }
164
146
  const baseDir = path_1.default.dirname(cfgPath);
147
+ const packageJsonPath = findNearestPackageJson(cfgPath);
148
+ const projectRoot = packageJsonPath
149
+ ? path_1.default.dirname(packageJsonPath)
150
+ : baseDir;
165
151
  const entryFile = path_1.default.resolve(baseDir, config.entry);
166
152
  const tsconfigPath = config.tsconfig
167
153
  ? path_1.default.resolve(baseDir, config.tsconfig)
@@ -171,6 +157,7 @@ function resolvePaths(cfgPath, config) {
171
157
  return {
172
158
  configPath: cfgPath,
173
159
  entryFile,
160
+ projectRoot,
174
161
  tsconfigPath,
175
162
  apiBaseUrl,
176
163
  apiKey,
@@ -190,12 +177,12 @@ function findTsConfig(entryFile) {
190
177
  }
191
178
  return undefined;
192
179
  }
193
- async function transpileTsModuleToTemp(tsPath) {
180
+ async function transpileTsModuleToTemp(tsPath, format) {
194
181
  const ts = await Promise.resolve().then(() => __importStar(require("typescript")));
195
182
  const source = fs_1.default.readFileSync(tsPath, "utf8");
196
183
  const transpiled = ts.transpileModule(source, {
197
184
  compilerOptions: {
198
- module: ts.ModuleKind.ESNext,
185
+ module: format === "esm" ? ts.ModuleKind.ESNext : ts.ModuleKind.CommonJS,
199
186
  target: ts.ScriptTarget.ES2022,
200
187
  esModuleInterop: true,
201
188
  },
@@ -203,16 +190,15 @@ async function transpileTsModuleToTemp(tsPath) {
203
190
  });
204
191
  const hash = crypto_1.default
205
192
  .createHash("sha1")
206
- .update(tsPath + source + Date.now().toString())
193
+ .update(tsPath + format + source + Date.now().toString())
207
194
  .digest("hex");
208
- const outFile = path_1.default.join(path_1.default.dirname(tsPath), `.cms0-config.${hash}.mjs`);
195
+ const outFile = path_1.default.join(path_1.default.dirname(tsPath), `.cms0-config.${hash}.${format === "esm" ? "mjs" : "cjs"}`);
209
196
  fs_1.default.writeFileSync(outFile, transpiled.outputText, "utf8");
210
- return (0, url_1.pathToFileURL)(outFile).href;
197
+ return outFile;
211
198
  }
212
- function cleanupTempModule(tempHref) {
199
+ function cleanupTempModule(tempPath) {
213
200
  try {
214
- const filePath = (0, url_1.fileURLToPath)(tempHref);
215
- fs_1.default.unlinkSync(filePath);
201
+ fs_1.default.unlinkSync(tempPath);
216
202
  }
217
203
  catch {
218
204
  // ignore cleanup failures
@@ -3,10 +3,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.FALLBACK_DESCRIPTOR = void 0;
6
7
  exports.writeDescriptorFiles = writeDescriptorFiles;
7
8
  const fs_1 = __importDefault(require("fs"));
8
9
  const path_1 = __importDefault(require("path"));
9
10
  const paths_js_1 = require("./paths.cjs");
11
+ const FALLBACK_DESCRIPTOR = {
12
+ models: {},
13
+ roots: {},
14
+ metadata: {
15
+ __cms0Fallback: true,
16
+ },
17
+ };
18
+ exports.FALLBACK_DESCRIPTOR = FALLBACK_DESCRIPTOR;
10
19
  function safeWrite(outputPath, output) {
11
20
  try {
12
21
  fs_1.default.mkdirSync(path_1.default.dirname(outputPath), { recursive: true });
@@ -21,19 +30,22 @@ function safeWrite(outputPath, output) {
21
30
  }
22
31
  }
23
32
  }
24
- function createSourceTsOutput(descriptor) {
25
- return `// Auto-generated schema descriptor\nexport const schemaDescriptor = ${JSON.stringify(descriptor, null, 2)} as const;\n`;
33
+ function createCjsOutput(descriptor) {
34
+ return `// Auto-generated schema descriptor\nexports.schemaDescriptor = ${JSON.stringify(descriptor, null, 2)};\n`;
35
+ }
36
+ function createJsonOutput(descriptor) {
37
+ return `${JSON.stringify(descriptor, null, 2)}\n`;
26
38
  }
27
39
  function createEsmOutput(descriptor) {
28
40
  return `// Auto-generated schema descriptor\nexport const schemaDescriptor = ${JSON.stringify(descriptor, null, 2)};\n`;
29
41
  }
30
- function createCjsOutput(descriptor) {
31
- return `// Auto-generated schema descriptor\nexports.schemaDescriptor = ${JSON.stringify(descriptor, null, 2)};\n`;
32
- }
33
- function writeDescriptorFiles(descriptor) {
34
- if (fs_1.default.existsSync(path_1.default.resolve(path_1.default.dirname(paths_js_1.descriptorOutputPaths.sourceTs), ".."))) {
35
- safeWrite(paths_js_1.descriptorOutputPaths.sourceTs, createSourceTsOutput(descriptor));
36
- }
42
+ function writeBundledDescriptorProjection(descriptor) {
37
43
  safeWrite(paths_js_1.descriptorOutputPaths.esmJs, createEsmOutput(descriptor));
38
44
  safeWrite(paths_js_1.descriptorOutputPaths.cjsJs, createCjsOutput(descriptor));
39
45
  }
46
+ function writeDescriptorFiles(resolved, descriptor, browserTarget = "sidecar") {
47
+ const localDescriptorOutputPaths = (0, paths_js_1.resolveLocalDescriptorOutputPaths)(resolved.projectRoot);
48
+ safeWrite(localDescriptorOutputPaths.json, createJsonOutput(descriptor));
49
+ safeWrite(localDescriptorOutputPaths.cjsJs, createCjsOutput(descriptor));
50
+ writeBundledDescriptorProjection(browserTarget === "bundle" ? descriptor : FALLBACK_DESCRIPTOR);
51
+ }
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.packageRoot = exports.descriptorOutputPaths = void 0;
7
+ exports.resolveLocalDescriptorOutputPaths = resolveLocalDescriptorOutputPaths;
7
8
  // Path utilities for locating package-relative outputs.
8
9
  const path_1 = __importDefault(require("path"));
9
10
  const node_fs_1 = __importDefault(require("node:fs"));
@@ -53,3 +54,9 @@ const descriptorOutputPaths = {
53
54
  cjsJs: path_1.default.resolve(packageRoot, "dist/cjs/generated/schema-descriptor.cjs"),
54
55
  };
55
56
  exports.descriptorOutputPaths = descriptorOutputPaths;
57
+ function resolveLocalDescriptorOutputPaths(projectRoot) {
58
+ return {
59
+ json: path_1.default.resolve(projectRoot, ".cms0/generated/schema-descriptor.json"),
60
+ cjsJs: path_1.default.resolve(projectRoot, ".cms0/generated/schema-descriptor.cjs"),
61
+ };
62
+ }