@sanity/client 6.7.1-canary.4 → 6.7.1-canary.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -656,6 +656,12 @@ function useContentSourceMap(resultSourceMap: ContentSourceMapping): unknown {
656
656
  useContentSourceMap(resultSourceMap)
657
657
  ```
658
658
 
659
+ #### Creating Studio edit intent links
660
+
661
+ In general
662
+
663
+ With arrays, and keyed array items.
664
+
659
665
  ### Listening to queries
660
666
 
661
667
  ```js
package/dist/csm.cjs CHANGED
@@ -68,11 +68,115 @@ function parseJsonPath(path) {
68
68
  }
69
69
  return parsed;
70
70
  }
71
- function createEditIntentLink(studioUrl, _ref, path) {
71
+ function resolveMapping(resultPath, csm) {
72
+ if (!(csm == null ? void 0 : csm.mappings)) {
73
+ return void 0;
74
+ }
75
+ const resultJsonPath = jsonPath(resultPath);
76
+ if (csm.mappings[resultJsonPath] !== void 0) {
77
+ return [csm.mappings[resultJsonPath], resultJsonPath, ""];
78
+ }
79
+ const mappings = Object.entries(csm.mappings).filter(_ref => {
80
+ let [key] = _ref;
81
+ return resultJsonPath.startsWith(key);
82
+ }).sort((_ref2, _ref3) => {
83
+ let [key1] = _ref2;
84
+ let [key2] = _ref3;
85
+ return key2.length - key1.length;
86
+ });
87
+ if (mappings.length == 0) {
88
+ return void 0;
89
+ }
90
+ const [matchedPath, mapping] = mappings[0];
91
+ const pathSuffix = resultJsonPath.substring(matchedPath.length);
92
+ return [mapping, matchedPath, pathSuffix];
93
+ }
94
+ function isArray(value) {
95
+ return value !== null && Array.isArray(value);
96
+ }
97
+ function isRecord(value) {
98
+ return typeof value === "object" && value !== null;
99
+ }
100
+ function walkMap(value, mappingFn) {
101
+ let path = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
102
+ if (isArray(value)) {
103
+ return value.map((v, idx) => {
104
+ if (isRecord(v)) {
105
+ const key = v["_key"];
106
+ if (typeof key === "string") {
107
+ return walkMap(v, mappingFn, path.concat({
108
+ key,
109
+ index: idx
110
+ }));
111
+ }
112
+ }
113
+ return walkMap(v, mappingFn, path.concat(idx));
114
+ });
115
+ }
116
+ if (isRecord(value)) {
117
+ return Object.fromEntries(Object.entries(value).map(_ref4 => {
118
+ let [k, v] = _ref4;
119
+ return [k, walkMap(v, mappingFn, path.concat(k))];
120
+ }));
121
+ }
122
+ return mappingFn(value, path);
123
+ }
124
+ const defaultUpdateFunction = changed => changed;
125
+ function applySourceDocuments(result, resultSourceMap, getCachedDocument) {
126
+ let updateFn = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : defaultUpdateFunction;
127
+ if (!resultSourceMap) return result;
128
+ return walkMap(result, (value, path) => {
129
+ var _a;
130
+ const resolveMappingResult = resolveMapping(path, resultSourceMap);
131
+ if (!resolveMappingResult) {
132
+ return value;
133
+ }
134
+ const [mapping,, pathSuffix] = resolveMappingResult;
135
+ if (mapping.type !== "value") {
136
+ return value;
137
+ }
138
+ if (mapping.source.type !== "documentValue") {
139
+ return value;
140
+ }
141
+ const sourceDocument = resultSourceMap.documents[mapping.source.document];
142
+ const sourcePath = resultSourceMap.paths[mapping.source.path];
143
+ if (sourceDocument) {
144
+ const cachedDocument = getCachedDocument(sourceDocument);
145
+ if (!cachedDocument) {
146
+ return value;
147
+ }
148
+ const parsedPath = parseJsonPath(sourcePath + pathSuffix);
149
+ const changedValue = cachedDocument ? (_a = getField(cachedDocument, parsedPath)) != null ? _a : value : value;
150
+ return value === changedValue ? value : updateFn(changedValue, {
151
+ cachedDocument,
152
+ previousValue: value,
153
+ sourceDocument,
154
+ sourcePath: parsedPath
155
+ });
156
+ }
157
+ return value;
158
+ });
159
+ }
160
+ function getField(obj, path) {
161
+ let value = obj;
162
+ for (const segment of path) {
163
+ if (typeof segment === "string") {
164
+ value = value[segment];
165
+ } else {
166
+ const match = typeof segment === "object" ? value.find(item => item._key === segment.key) : value[segment];
167
+ value = match || null;
168
+ }
169
+ if (value === null || value === void 0) {
170
+ break;
171
+ }
172
+ }
173
+ return value;
174
+ }
175
+ function createEditIntentLink(studioUrl, _ref5, path) {
72
176
  let {
73
177
  _id,
74
178
  _type
75
- } = _ref;
179
+ } = _ref5;
76
180
  const _studioUrl = studioUrl.replace(/\/$/, "");
77
181
  const _path = encodeJsonPathToUriComponent(path);
78
182
  return "".concat(_studioUrl, "/intent/edit/id=").concat(_id, ";type=").concat(_type, ";path=").concat(_path);
@@ -81,15 +185,6 @@ function encodeJsonPathToUriComponent(path) {
81
185
  const sourcePath = Array.isArray(path) ? path : parseJsonPath(path);
82
186
  return encodeURIComponent(sourcePath.map((key, i) => typeof key === "number" ? "[".concat(key, "]") : i > 0 ? ".".concat(key) : key).join(""));
83
187
  }
84
- function isRecord(value) {
85
- return typeof value === "object" && value !== null;
86
- }
87
- function isArray(value) {
88
- return value !== null && Array.isArray(value);
89
- }
90
- function encode(result, csm, encoder, options) {
91
- return encodeIntoResult(result, csm, encoder, options);
92
- }
93
188
  function encodeIntoResult(result, csm, encoder, options) {
94
189
  return walkMap(result, (value, path) => {
95
190
  if (typeof value !== "string") {
@@ -117,50 +212,10 @@ function encodeIntoResult(result, csm, encoder, options) {
117
212
  return encoder(value, sourceDocument, parseJsonPath(sourcePath + pathSuffix));
118
213
  });
119
214
  }
120
- function walkMap(value, mappingFn) {
121
- let path = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
122
- if (isArray(value)) {
123
- return value.map((v, idx) => {
124
- if (isRecord(v)) {
125
- const key = v["_key"];
126
- if (typeof key === "string") {
127
- return walkMap(v, mappingFn, path.concat({
128
- key,
129
- index: idx
130
- }));
131
- }
132
- }
133
- return walkMap(v, mappingFn, path.concat(idx));
134
- });
135
- }
136
- if (isRecord(value)) {
137
- return Object.fromEntries(Object.entries(value).map(_ref2 => {
138
- let [k, v] = _ref2;
139
- return [k, walkMap(v, mappingFn, path.concat(k))];
140
- }));
141
- }
142
- return mappingFn(value, path);
143
- }
144
- function resolveMapping(resultPath, csm) {
145
- const resultJsonPath = jsonPath(resultPath);
146
- if (csm.mappings[resultJsonPath] !== void 0) {
147
- return [csm.mappings[resultJsonPath], resultJsonPath, ""];
148
- }
149
- const mappings = Object.entries(csm.mappings).filter(_ref3 => {
150
- let [key] = _ref3;
151
- return resultJsonPath.startsWith(key);
152
- }).sort((_ref4, _ref5) => {
153
- let [key1] = _ref4;
154
- let [key2] = _ref5;
155
- return key2.length - key1.length;
156
- });
157
- if (mappings.length == 0) {
158
- return void 0;
159
- }
160
- const [matchedPath, mapping] = mappings[0];
161
- const pathSuffix = resultJsonPath.substring(matchedPath.length);
162
- return [mapping, matchedPath, pathSuffix];
215
+ function encode(result, csm, encoder, options) {
216
+ return encodeIntoResult(result, csm, encoder, options);
163
217
  }
218
+ exports.applySourceDocuments = applySourceDocuments;
164
219
  exports.createEditIntentLink = createEditIntentLink;
165
220
  exports.encode = encode;
166
221
  exports.encodeIntoResult = encodeIntoResult;
package/dist/csm.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"csm.cjs","sources":["../src/csm/jsonpath.ts","../src/csm/editIntent.ts","../src/csm/sourcemap.ts"],"sourcesContent":["import type {PathSegment} from './types'\n\nconst ESCAPE: Record<string, string> = {\n '\\f': '\\\\f',\n '\\n': '\\\\n',\n '\\r': '\\\\r',\n '\\t': '\\\\t',\n \"'\": \"\\\\'\",\n '\\\\': '\\\\\\\\',\n}\n\nconst UNESCAPE: Record<string, string> = {\n '\\\\f': '\\f',\n '\\\\n': '\\n',\n '\\\\r': '\\r',\n '\\\\t': '\\t',\n \"\\\\'\": \"'\",\n '\\\\\\\\': '\\\\',\n}\n\n/** @internal */\nexport function jsonPath(\n path: PathSegment[],\n opts?: {\n keyArraySelectors: boolean\n },\n): string {\n return `$${path\n .map((segment) => {\n if (typeof segment === 'string') {\n const escapedKey = segment.replace(/[\\f\\n\\r\\t'\\\\]/g, (match) => {\n return ESCAPE[match]\n })\n return `['${escapedKey}']`\n }\n\n if (typeof segment === 'number') {\n return `[${segment}]`\n }\n\n if (opts?.keyArraySelectors && segment.key !== '') {\n const escapedKey = segment.key.replace(/['\\\\]/g, (match) => {\n return ESCAPE[match]\n })\n return `[?(@._key=='${escapedKey}')]`\n }\n\n return `[${segment.index}]`\n })\n .join('')}`\n}\n\n/** @internal */\nexport function parseJsonPath(path: string): PathSegment[] {\n const parsed: PathSegment[] = []\n\n const parseRe = /\\['(.*?)'\\]|\\[(\\d+)\\]|\\[\\?\\(@\\._key=='(.*?)'\\)\\]/g\n let match: RegExpExecArray | null\n\n while ((match = parseRe.exec(path)) !== null) {\n if (match[1] !== undefined) {\n const key = match[1].replace(/\\\\(\\\\|f|n|r|t|')/g, (m) => {\n return UNESCAPE[m]\n })\n\n parsed.push(key)\n continue\n }\n\n if (match[2] !== undefined) {\n parsed.push(parseInt(match[2], 10))\n continue\n }\n\n if (match[3] !== undefined) {\n const key = match[3].replace(/\\\\(\\\\')/g, (m) => {\n return UNESCAPE[m]\n })\n\n parsed.push({\n key,\n index: -1,\n })\n continue\n }\n }\n\n return parsed\n}\n","import type {ContentSourceMapDocuments} from '../types'\nimport {parseJsonPath} from './jsonpath'\nimport type {PathSegment, StudioUrl} from './types'\n\n/** @public */\nexport type EditIntentLink = `/intent/edit/id=${string};type=${string};path=${string}`\n\n/** @public */\nexport function createEditIntentLink(\n studioUrl: StudioUrl,\n {_id, _type}: ContentSourceMapDocuments[number],\n path: string | PathSegment[],\n): `${StudioUrl}${EditIntentLink}` {\n const _studioUrl = studioUrl.replace(/\\/$/, '')\n const _path = encodeJsonPathToUriComponent(path)\n return `${_studioUrl}/intent/edit/id=${_id};type=${_type};path=${_path}`\n}\n\n/** @public */\nexport function encodeJsonPathToUriComponent(path: string | PathSegment[]): string {\n const sourcePath = Array.isArray(path) ? path : parseJsonPath(path)\n return encodeURIComponent(\n sourcePath\n .map((key, i) => (typeof key === 'number' ? `[${key}]` : i > 0 ? `.${key}` : key))\n .join(''),\n )\n}\n","import type {ContentSourceMap, ContentSourceMapDocuments, ContentSourceMapMapping} from '../types'\nimport {jsonPath, parseJsonPath} from './jsonpath'\nimport type {PathSegment} from './types'\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null\n}\n\nfunction isArray(value: unknown): value is Array<unknown> {\n return value !== null && Array.isArray(value)\n}\n\n/** @alpha */\nexport type Encoder<E> = (\n value: string,\n sourceDocument: ContentSourceMapDocuments[number],\n path: PathSegment[],\n) => E\n\n/** @alpha */\nexport function encode<R, E>(\n result: R,\n csm: ContentSourceMap,\n encoder: Encoder<E>,\n options?: {keyArraySelectors: boolean},\n): R {\n return encodeIntoResult(result, csm, encoder, options) as R\n}\n\n/** @alpha */\nexport function encodeIntoResult<R>(\n result: R,\n csm: ContentSourceMap,\n encoder: Encoder<unknown>,\n options?: {keyArraySelectors: boolean},\n): ReturnType<Encoder<unknown>> {\n return walkMap(result, (value, path) => {\n // Only map strings, we could extend this in the future to support other types like integers...\n if (typeof value !== 'string') {\n return value\n }\n\n const resolveMappingResult = resolveMapping(path, csm)\n if (!resolveMappingResult) {\n return value\n }\n\n const [mapping, matchedPath, pathSuffix] = resolveMappingResult\n if (mapping.type !== 'value') {\n return value\n }\n\n if (mapping.source.type !== 'documentValue') {\n return value\n }\n\n const sourceDocument = csm.documents[mapping.source.document!]\n const sourcePath = csm.paths[mapping.source.path]\n\n if (options?.keyArraySelectors) {\n const matchPathSegments = parseJsonPath(matchedPath)\n const sourcePathSegments = parseJsonPath(sourcePath)\n const fullSourceSegments = sourcePathSegments.concat(path.slice(matchPathSegments.length))\n\n return encoder(value, sourceDocument, fullSourceSegments)\n }\n\n return encoder(value, sourceDocument, parseJsonPath(sourcePath + pathSuffix))\n })\n}\n\n/** @alpha */\nexport type WalkMapFn = (value: unknown, path: PathSegment[]) => unknown\n\n/** generic way to walk a nested object or array and apply a mapping function to each value\n * @alpha\n */\nexport function walkMap(value: unknown, mappingFn: WalkMapFn, path: PathSegment[] = []): unknown {\n if (isArray(value)) {\n return value.map((v, idx) => {\n if (isRecord(v)) {\n const key = v['_key']\n if (typeof key === 'string') {\n return walkMap(v, mappingFn, path.concat({key, index: idx}))\n }\n }\n\n return walkMap(v, mappingFn, path.concat(idx))\n })\n }\n\n if (isRecord(value)) {\n return Object.fromEntries(\n Object.entries(value).map(([k, v]) => [k, walkMap(v, mappingFn, path.concat(k))]),\n )\n }\n\n return mappingFn(value, path)\n}\n\n/** @alpha */\nexport function resolveMapping(\n resultPath: PathSegment[],\n csm: ContentSourceMap,\n): [ContentSourceMapMapping, string, string] | undefined {\n const resultJsonPath = jsonPath(resultPath)\n\n if (csm.mappings[resultJsonPath] !== undefined) {\n return [csm.mappings[resultJsonPath], resultJsonPath, '']\n }\n\n const mappings = Object.entries(csm.mappings)\n .filter(([key]) => resultJsonPath.startsWith(key))\n .sort(([key1], [key2]) => key2.length - key1.length)\n\n if (mappings.length == 0) {\n return undefined\n }\n\n const [matchedPath, mapping] = mappings[0]\n const pathSuffix = resultJsonPath.substring(matchedPath.length)\n return [mapping, matchedPath, pathSuffix]\n}\n"],"names":["ESCAPE","UNESCAPE","jsonPath","path","opts","concat","map","segment","escapedKey","replace","match","keyArraySelectors","key","index","join","parseJsonPath","parsed","parseRe","exec","m","push","parseInt","createEditIntentLink","studioUrl","_ref","_id","_type","_studioUrl","_path","encodeJsonPathToUriComponent","sourcePath","Array","isArray","encodeURIComponent","i","isRecord","value","encode","result","csm","encoder","options","encodeIntoResult","walkMap","resolveMappingResult","resolveMapping","mapping","matchedPath","pathSuffix","type","source","sourceDocument","documents","document","paths","matchPathSegments","sourcePathSegments","fullSourceSegments","slice","length","mappingFn","arguments","undefined","v","idx","Object","fromEntries","entries","_ref2","k","resultPath","resultJsonPath","mappings","filter","_ref3","startsWith","sort","_ref4","_ref5","key1","key2","substring"],"mappings":";;;;;AAEA,MAAMA,MAAiC,GAAA;EACrC,IAAM,EAAA,KAAA;EACN,IAAM,EAAA,KAAA;EACN,IAAM,EAAA,KAAA;EACN,GAAM,EAAA,KAAA;EACN,GAAK,EAAA,KAAA;EACL,IAAM,EAAA;AACR,CAAA;AAEA,MAAMC,QAAmC,GAAA;EACvC,KAAO,EAAA,IAAA;EACP,KAAO,EAAA,IAAA;EACP,KAAO,EAAA,IAAA;EACP,KAAO,EAAA,GAAA;EACP,KAAO,EAAA,GAAA;EACP,MAAQ,EAAA;AACV,CAAA;AAGgB,SAAAC,QAAAA,CACdC,MACAC,IAGQ,EAAA;EACR,OAAO,GAAI,CAAAC,MAAA,CAAAF,IAAA,CACRG,GAAI,CAACC,OAAY,IAAA;IACZ,IAAA,OAAOA,YAAY,QAAU,EAAA;MAC/B,MAAMC,UAAa,GAAAD,OAAA,CAAQE,OAAQ,CAAA,gBAAA,EAAmBC,KAAU,IAAA;QAC9D,OAAOV,OAAOU,KAAK,CAAA;MAAA,CACpB,CAAA;MACD,OAAO,KAAKL,MAAU,CAAAG,UAAA,EAAA,IAAA,CAAA;IACxB;IAEI,IAAA,OAAOD,YAAY,QAAU,EAAA;MAC/B,OAAO,IAAIF,MAAO,CAAAE,OAAA,EAAA,GAAA,CAAA;IACpB;IAEA,IAAA,CAAIH,IAAM,IAAA,IAAA,GAAA,KAAA,CAAA,GAAAA,IAAA,CAAAO,iBAAA,KAAqBJ,OAAQ,CAAAK,GAAA,KAAQ,EAAI,EAAA;MACjD,MAAMJ,aAAaD,OAAQ,CAAAK,GAAA,CAAIH,OAAQ,CAAA,QAAA,EAAWC,KAAU,IAAA;QAC1D,OAAOV,OAAOU,KAAK,CAAA;MAAA,CACpB,CAAA;MACD,OAAO,eAAeL,MAAU,CAAAG,UAAA,EAAA,KAAA,CAAA;IAClC;IAEO,OAAA,GAAA,CAAIH,eAAQQ,KAAK,EAAA,GAAA,CAAA;EAAA,CACzB,CACA,CAAAC,IAAA,CAAK,EAAE,CAAA,CAAA;AACZ;AAGO,SAASC,cAAcZ,IAA6B,EAAA;EACzD,MAAMa,SAAwB,EAAC;EAE/B,MAAMC,OAAU,GAAA,mDAAA;EACZ,IAAAP,KAAA;EAEJ,OAAA,CAAQA,KAAQ,GAAAO,OAAA,CAAQC,IAAK,CAAAf,IAAI,OAAO,IAAM,EAAA;IACxC,IAAAO,KAAA,CAAM,CAAC,CAAA,KAAM,KAAW,CAAA,EAAA;MAC1B,MAAME,MAAMF,KAAM,CAAA,CAAC,EAAED,OAAQ,CAAA,mBAAA,EAAsBU,CAAM,IAAA;QACvD,OAAOlB,SAASkB,CAAC,CAAA;MAAA,CAClB,CAAA;MAEDH,MAAA,CAAOI,KAAKR,GAAG,CAAA;MACf;IACF;IAEI,IAAAF,KAAA,CAAM,CAAC,CAAA,KAAM,KAAW,CAAA,EAAA;MAC1BM,MAAA,CAAOI,KAAKC,QAAS,CAAAX,KAAA,CAAM,CAAC,CAAA,EAAG,EAAE,CAAC,CAAA;MAClC;IACF;IAEI,IAAAA,KAAA,CAAM,CAAC,CAAA,KAAM,KAAW,CAAA,EAAA;MAC1B,MAAME,MAAMF,KAAM,CAAA,CAAC,EAAED,OAAQ,CAAA,UAAA,EAAaU,CAAM,IAAA;QAC9C,OAAOlB,SAASkB,CAAC,CAAA;MAAA,CAClB,CAAA;MAEDH,MAAA,CAAOI,IAAK,CAAA;QACVR,GAAA;QACAC,KAAO,EAAA,CAAA;MAAA,CACR,CAAA;MACD;IACF;EACF;EAEO,OAAAG,MAAA;AACT;AChFO,SAASM,qBACdC,SACA,EAAAC,IAAA,EACArB,IACiC,EAAA;EAAA,IAFjC;IAACsB,GAAK;IAAAC;EAAA;EAGN,MAAMC,UAAa,GAAAJ,SAAA,CAAUd,OAAQ,CAAA,KAAA,EAAO,EAAE,CAAA;EACxC,MAAAmB,KAAA,GAAQC,6BAA6B1B,IAAI,CAAA;EAC/C,OAAO,GAAGE,MAAU,CAAAsB,UAAA,EAAA,kBAAA,CAAA,CAAmBtB,MAAG,CAAAoB,GAAA,EAAA,QAAA,CAAA,CAASpB,cAAK,QAAS,CAAA,CAAAA,MAAA,CAAAuB,KAAA,CAAA;AACnE;AAGO,SAASC,6BAA6B1B,IAAsC,EAAA;EACjF,MAAM2B,aAAaC,KAAM,CAAAC,OAAA,CAAQ7B,IAAI,CAAI,GAAAA,IAAA,GAAOY,cAAcZ,IAAI,CAAA;EAC3D,OAAA8B,kBAAA,CACLH,WACGxB,GAAI,CAAA,CAACM,KAAKsB,CAAO,KAAA,OAAOtB,QAAQ,QAAW,GAAA,GAAA,CAAIP,MAAG,CAAAO,GAAA,EAAA,GAAA,CAAA,GAAMsB,IAAI,CAAI,GAAA,GAAA,CAAI7B,cAAQO,GAAI,CAAA,CAChFE,KAAK,EAAE,CAAA,CACZ;AACF;ACtBA,SAASqB,SAASC,KAAkD,EAAA;EAC3D,OAAA,OAAOA,KAAU,KAAA,QAAA,IAAYA,KAAU,KAAA,IAAA;AAChD;AAEA,SAASJ,QAAQI,KAAyC,EAAA;EACxD,OAAOA,KAAU,KAAA,IAAA,IAAQL,KAAM,CAAAC,OAAA,CAAQI,KAAK,CAAA;AAC9C;AAUO,SAASC,MACdA,CAAAC,MAAA,EACAC,GACA,EAAAC,OAAA,EACAC,OACG,EAAA;EACH,OAAOC,gBAAiB,CAAAJ,MAAA,EAAQC,GAAK,EAAAC,OAAA,EAASC,OAAO,CAAA;AACvD;AAGO,SAASC,gBACdA,CAAAJ,MAAA,EACAC,GACA,EAAAC,OAAA,EACAC,OAC8B,EAAA;EAC9B,OAAOE,OAAQ,CAAAL,MAAA,EAAQ,CAACF,KAAA,EAAOjC,IAAS,KAAA;IAElC,IAAA,OAAOiC,UAAU,QAAU,EAAA;MACtB,OAAAA,KAAA;IACT;IAEM,MAAAQ,oBAAA,GAAuBC,cAAe,CAAA1C,IAAA,EAAMoC,GAAG,CAAA;IACrD,IAAI,CAACK,oBAAsB,EAAA;MAClB,OAAAR,KAAA;IACT;IAEA,MAAM,CAACU,OAAA,EAASC,WAAa,EAAAC,UAAU,CAAI,GAAAJ,oBAAA;IACvC,IAAAE,OAAA,CAAQG,SAAS,OAAS,EAAA;MACrB,OAAAb,KAAA;IACT;IAEI,IAAAU,OAAA,CAAQI,MAAO,CAAAD,IAAA,KAAS,eAAiB,EAAA;MACpC,OAAAb,KAAA;IACT;IAEA,MAAMe,cAAiB,GAAAZ,GAAA,CAAIa,SAAU,CAAAN,OAAA,CAAQI,OAAOG,QAAS,CAAA;IAC7D,MAAMvB,UAAa,GAAAS,GAAA,CAAIe,KAAM,CAAAR,OAAA,CAAQI,OAAO/C,IAAI,CAAA;IAEhD,IAAIsC,mCAAS9B,iBAAmB,EAAA;MACxB,MAAA4C,iBAAA,GAAoBxC,cAAcgC,WAAW,CAAA;MAC7C,MAAAS,kBAAA,GAAqBzC,cAAce,UAAU,CAAA;MACnD,MAAM2B,qBAAqBD,kBAAmB,CAAAnD,MAAA,CAAOF,KAAKuD,KAAM,CAAAH,iBAAA,CAAkBI,MAAM,CAAC,CAAA;MAElF,OAAAnB,OAAA,CAAQJ,KAAO,EAAAe,cAAA,EAAgBM,kBAAkB,CAAA;IAC1D;IAEA,OAAOjB,QAAQJ,KAAO,EAAAe,cAAA,EAAgBpC,aAAc,CAAAe,UAAA,GAAakB,UAAU,CAAC,CAAA;EAAA,CAC7E,CAAA;AACH;AAQO,SAASL,OAAQA,CAAAP,KAAA,EAAgBwB,SAAsB,EAAmC;EAAA,IAAnCzD,IAAA,GAAA0D,SAAA,CAAAF,MAAA,QAAAE,SAAA,QAAAC,SAAA,GAAAD,SAAA,MAAsB,EAAa;EAC3F,IAAA7B,OAAA,CAAQI,KAAK,CAAG,EAAA;IAClB,OAAOA,KAAM,CAAA9B,GAAA,CAAI,CAACyD,CAAA,EAAGC,GAAQ,KAAA;MACvB,IAAA7B,QAAA,CAAS4B,CAAC,CAAG,EAAA;QACT,MAAAnD,GAAA,GAAMmD,EAAE,MAAM,CAAA;QAChB,IAAA,OAAOnD,QAAQ,QAAU,EAAA;UACpB,OAAA+B,OAAA,CAAQoB,CAAG,EAAAH,SAAA,EAAWzD,IAAK,CAAAE,MAAA,CAAO;YAACO,GAAK;YAAAC,KAAA,EAAOmD;UAAI,CAAA,CAAC,CAAA;QAC7D;MACF;MAEA,OAAOrB,QAAQoB,CAAG,EAAAH,SAAA,EAAWzD,IAAK,CAAAE,MAAA,CAAO2D,GAAG,CAAC,CAAA;IAAA,CAC9C,CAAA;EACH;EAEI,IAAA7B,QAAA,CAASC,KAAK,CAAG,EAAA;IACnB,OAAO6B,MAAO,CAAAC,WAAA,CACZD,MAAA,CAAOE,QAAQ/B,KAAK,CAAA,CAAE9B,IAAI8D,KAAA;MAAA,IAAC,CAACC,GAAGN,CAAC,CAAA,GAAAK,KAAA;MAAA,OAAM,CAACC,CAAG,EAAA1B,OAAA,CAAQoB,GAAGH,SAAW,EAAAzD,IAAA,CAAKE,OAAOgE,CAAC,CAAC,CAAC,CAAC;IAAA,EAAA,CAClF;EACF;EAEO,OAAAT,SAAA,CAAUxB,OAAOjC,IAAI,CAAA;AAC9B;AAGgB,SAAA0C,cAAAA,CACdyB,YACA/B,GACuD,EAAA;EACjD,MAAAgC,cAAA,GAAiBrE,SAASoE,UAAU,CAAA;EAE1C,IAAI/B,GAAI,CAAAiC,QAAA,CAASD,cAAc,CAAA,KAAM,KAAW,CAAA,EAAA;IAC9C,OAAO,CAAChC,GAAI,CAAAiC,QAAA,CAASD,cAAc,CAAA,EAAGA,gBAAgB,EAAE,CAAA;EAC1D;EAEM,MAAAC,QAAA,GAAWP,MAAO,CAAAE,OAAA,CAAQ5B,GAAI,CAAAiC,QAAQ,CACzC,CAAAC,MAAA,CAAOC,KAAA;IAAA,IAAC,CAAC9D,GAAG,CAAA,GAAA8D,KAAA;IAAA,OAAMH,cAAe,CAAAI,UAAA,CAAW/D,GAAG,CAAC;EAAA,EAChD,CAAAgE,IAAA,CAAK,CAAAC,KAAA,EAAAC,KAAA;IAAA,IAAC,CAACC,IAAI,CAAA,GAAAF,KAAA;IAAA,IAAG,CAACG,IAAI,CAAM,GAAAF,KAAA;IAAA,OAAAE,IAAA,CAAKrB,MAAS,GAAAoB,IAAA,CAAKpB,MAAM;EAAA,EAAA;EAEjD,IAAAa,QAAA,CAASb,UAAU,CAAG,EAAA;IACjB,OAAA,KAAA,CAAA;EACT;EAEA,MAAM,CAACZ,WAAA,EAAaD,OAAO,CAAA,GAAI0B,SAAS,CAAC,CAAA;EACzC,MAAMxB,UAAa,GAAAuB,cAAA,CAAeU,SAAU,CAAAlC,WAAA,CAAYY,MAAM,CAAA;EACvD,OAAA,CAACb,OAAS,EAAAC,WAAA,EAAaC,UAAU,CAAA;AAC1C;;;;;;;;"}
1
+ {"version":3,"file":"csm.cjs","sources":["../src/csm/jsonpath.ts","../src/csm/resolveMapping.ts","../src/csm/isArray.ts","../src/csm/isRecord.ts","../src/csm/walkMap.ts","../src/csm/applySourceDocuments.ts","../src/csm/editIntent.ts","../src/csm/encodeIntoResult.ts","../src/csm/encode.ts"],"sourcesContent":["import type {PathSegment} from './types'\n\nconst ESCAPE: Record<string, string> = {\n '\\f': '\\\\f',\n '\\n': '\\\\n',\n '\\r': '\\\\r',\n '\\t': '\\\\t',\n \"'\": \"\\\\'\",\n '\\\\': '\\\\\\\\',\n}\n\nconst UNESCAPE: Record<string, string> = {\n '\\\\f': '\\f',\n '\\\\n': '\\n',\n '\\\\r': '\\r',\n '\\\\t': '\\t',\n \"\\\\'\": \"'\",\n '\\\\\\\\': '\\\\',\n}\n\n/**\n * @internal\n */\nexport function jsonPath(\n path: PathSegment[],\n opts?: {\n keyArraySelectors: boolean\n },\n): string {\n return `$${path\n .map((segment) => {\n if (typeof segment === 'string') {\n const escapedKey = segment.replace(/[\\f\\n\\r\\t'\\\\]/g, (match) => {\n return ESCAPE[match]\n })\n return `['${escapedKey}']`\n }\n\n if (typeof segment === 'number') {\n return `[${segment}]`\n }\n\n if (opts?.keyArraySelectors && segment.key !== '') {\n const escapedKey = segment.key.replace(/['\\\\]/g, (match) => {\n return ESCAPE[match]\n })\n return `[?(@._key=='${escapedKey}')]`\n }\n\n return `[${segment.index}]`\n })\n .join('')}`\n}\n\n/**\n * @internal\n */\nexport function parseJsonPath(path: string): PathSegment[] {\n const parsed: PathSegment[] = []\n\n const parseRe = /\\['(.*?)'\\]|\\[(\\d+)\\]|\\[\\?\\(@\\._key=='(.*?)'\\)\\]/g\n let match: RegExpExecArray | null\n\n while ((match = parseRe.exec(path)) !== null) {\n if (match[1] !== undefined) {\n const key = match[1].replace(/\\\\(\\\\|f|n|r|t|')/g, (m) => {\n return UNESCAPE[m]\n })\n\n parsed.push(key)\n continue\n }\n\n if (match[2] !== undefined) {\n parsed.push(parseInt(match[2], 10))\n continue\n }\n\n if (match[3] !== undefined) {\n const key = match[3].replace(/\\\\(\\\\')/g, (m) => {\n return UNESCAPE[m]\n })\n\n parsed.push({\n key,\n index: -1,\n })\n continue\n }\n }\n\n return parsed\n}\n","import {jsonPath} from './jsonpath'\nimport type {ContentSourceMap, ContentSourceMapMapping, PathSegment} from './types'\n\n/**\n * @alpha\n */\nexport function resolveMapping(\n resultPath: PathSegment[],\n csm?: ContentSourceMap,\n): [ContentSourceMapMapping, string, string] | undefined {\n if (!csm?.mappings) {\n return undefined\n }\n const resultJsonPath = jsonPath(resultPath)\n\n if (csm.mappings[resultJsonPath] !== undefined) {\n return [csm.mappings[resultJsonPath], resultJsonPath, '']\n }\n\n const mappings = Object.entries(csm.mappings)\n .filter(([key]) => resultJsonPath.startsWith(key))\n .sort(([key1], [key2]) => key2.length - key1.length)\n\n if (mappings.length == 0) {\n return undefined\n }\n\n const [matchedPath, mapping] = mappings[0]\n const pathSuffix = resultJsonPath.substring(matchedPath.length)\n return [mapping, matchedPath, pathSuffix]\n}\n","export function isArray(value: unknown): value is Array<unknown> {\n return value !== null && Array.isArray(value)\n}\n","export function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null\n}\n","import {isArray} from './isArray'\nimport {isRecord} from './isRecord'\nimport type {PathSegment} from './types'\n\n/**\n * @alpha\n */\nexport type WalkMapFn = (value: unknown, path: PathSegment[]) => unknown\n\n/**\n * generic way to walk a nested object or array and apply a mapping function to each value\n * @alpha\n */\nexport function walkMap(value: unknown, mappingFn: WalkMapFn, path: PathSegment[] = []): unknown {\n if (isArray(value)) {\n return value.map((v, idx) => {\n if (isRecord(v)) {\n const key = v['_key']\n if (typeof key === 'string') {\n return walkMap(v, mappingFn, path.concat({key, index: idx}))\n }\n }\n\n return walkMap(v, mappingFn, path.concat(idx))\n })\n }\n\n if (isRecord(value)) {\n return Object.fromEntries(\n Object.entries(value).map(([k, v]) => [k, walkMap(v, mappingFn, path.concat(k))]),\n )\n }\n\n return mappingFn(value, path)\n}\n","import {parseJsonPath} from './jsonpath'\nimport {resolveMapping} from './resolveMapping'\nimport type {\n Any,\n ContentSourceMap,\n ContentSourceMapDocuments,\n PathSegment,\n SanityDocument,\n} from './types'\nimport {walkMap} from './walkMap'\n\n/**\n * @public\n */\nexport type ApplySourceDocumentsUpdateFunction = <T = unknown>(\n changedValue: T,\n context: {\n cachedDocument: SanityDocument\n previousValue: T\n sourceDocument: ContentSourceMapDocuments[number]\n sourcePath: PathSegment[]\n },\n) => T\n\nconst defaultUpdateFunction = <T = unknown>(changed: T): T => changed\n\n/**\n * Optimistically applies source documents to a result, using the content source map to trace fields.\n * Can be used to apply mutations to documents being edited in a Studio, or any mutation on Content Lake, to a result with extremely low latency.\n * @public\n */\nexport function applySourceDocuments<Result = unknown>(\n result: Result,\n resultSourceMap: ContentSourceMap | undefined,\n getCachedDocument: (\n sourceDocument: ContentSourceMapDocuments[number],\n ) => SanityDocument | undefined,\n updateFn: ApplySourceDocumentsUpdateFunction = defaultUpdateFunction,\n): Result {\n if (!resultSourceMap) return result\n\n return walkMap(result, (value, path) => {\n const resolveMappingResult = resolveMapping(path, resultSourceMap)\n if (!resolveMappingResult) {\n return value\n }\n\n const [mapping, , pathSuffix] = resolveMappingResult\n if (mapping.type !== 'value') {\n return value\n }\n\n if (mapping.source.type !== 'documentValue') {\n return value\n }\n\n const sourceDocument = resultSourceMap.documents[mapping.source.document]\n const sourcePath = resultSourceMap.paths[mapping.source.path]\n\n if (sourceDocument) {\n const cachedDocument = getCachedDocument(sourceDocument)\n if (!cachedDocument) {\n return value\n }\n\n const parsedPath = parseJsonPath(sourcePath + pathSuffix)\n const changedValue = cachedDocument ? getField(cachedDocument, parsedPath) ?? value : value\n return value === changedValue\n ? value\n : updateFn<Result[keyof Result]>(changedValue, {\n cachedDocument,\n previousValue: value as Result[keyof Result],\n sourceDocument,\n sourcePath: parsedPath,\n })\n }\n\n return value\n }) as Result\n}\n\nfunction getField(obj: SanityDocument, path: PathSegment[]): Any {\n let value = obj as SanityDocument | SanityDocument[keyof SanityDocument]\n for (const segment of path) {\n if (typeof segment === 'string') {\n value = value[segment]\n } else {\n const match =\n typeof segment === 'object'\n ? value.find((item: SanityDocument[keyof SanityDocument]) => item._key === segment.key)\n : value[segment]\n value = match || null\n }\n if (value === null || value === undefined) {\n break\n }\n }\n return value\n}\n","import type {ContentSourceMapDocuments} from '../types'\nimport {parseJsonPath} from './jsonpath'\nimport type {PathSegment, StudioUrl} from './types'\n\n/** @public */\nexport type EditIntentLink = `/intent/edit/id=${string};type=${string};path=${string}`\n\n/** @public */\nexport function createEditIntentLink(\n studioUrl: StudioUrl,\n {_id, _type}: ContentSourceMapDocuments[number],\n path: string | PathSegment[],\n): `${StudioUrl}${EditIntentLink}` {\n const _studioUrl = studioUrl.replace(/\\/$/, '')\n const _path = encodeJsonPathToUriComponent(path)\n return `${_studioUrl}/intent/edit/id=${_id};type=${_type};path=${_path}`\n}\n\n/** @public */\nexport function encodeJsonPathToUriComponent(path: string | PathSegment[]): string {\n const sourcePath = Array.isArray(path) ? path : parseJsonPath(path)\n return encodeURIComponent(\n sourcePath\n .map((key, i) => (typeof key === 'number' ? `[${key}]` : i > 0 ? `.${key}` : key))\n .join(''),\n )\n}\n","import {Encoder} from './encode'\nimport {parseJsonPath} from './jsonpath'\nimport {resolveMapping} from './resolveMapping'\nimport type {ContentSourceMap} from './types'\nimport {walkMap} from './walkMap'\n\n/**\n * @alpha\n */\nexport function encodeIntoResult<R>(\n result: R,\n csm: ContentSourceMap,\n encoder: Encoder<unknown>,\n options?: {keyArraySelectors: boolean},\n): ReturnType<Encoder<unknown>> {\n return walkMap(result, (value, path) => {\n // Only map strings, we could extend this in the future to support other types like integers...\n if (typeof value !== 'string') {\n return value\n }\n\n const resolveMappingResult = resolveMapping(path, csm)\n if (!resolveMappingResult) {\n return value\n }\n\n const [mapping, matchedPath, pathSuffix] = resolveMappingResult\n if (mapping.type !== 'value') {\n return value\n }\n\n if (mapping.source.type !== 'documentValue') {\n return value\n }\n\n const sourceDocument = csm.documents[mapping.source.document!]\n const sourcePath = csm.paths[mapping.source.path]\n\n if (options?.keyArraySelectors) {\n const matchPathSegments = parseJsonPath(matchedPath)\n const sourcePathSegments = parseJsonPath(sourcePath)\n const fullSourceSegments = sourcePathSegments.concat(path.slice(matchPathSegments.length))\n\n return encoder(value, sourceDocument, fullSourceSegments)\n }\n\n return encoder(value, sourceDocument, parseJsonPath(sourcePath + pathSuffix))\n })\n}\n","import {encodeIntoResult} from './encodeIntoResult'\nimport type {ContentSourceMap, ContentSourceMapDocuments, PathSegment} from './types'\n\n/**\n * @alpha\n */\nexport type Encoder<E> = (\n value: string,\n sourceDocument: ContentSourceMapDocuments[number],\n path: PathSegment[],\n) => E\n\n/**\n * @alpha\n */\nexport function encode<R, E>(\n result: R,\n csm: ContentSourceMap,\n encoder: Encoder<E>,\n options?: {keyArraySelectors: boolean},\n): R {\n return encodeIntoResult(result, csm, encoder, options) as R\n}\n"],"names":["ESCAPE","UNESCAPE","jsonPath","path","opts","concat","map","segment","escapedKey","replace","match","keyArraySelectors","key","index","join","parseJsonPath","parsed","parseRe","exec","m","push","parseInt","resolveMapping","resultPath","csm","mappings","resultJsonPath","Object","entries","filter","_ref","startsWith","sort","_ref2","_ref3","key1","key2","length","matchedPath","mapping","pathSuffix","substring","isArray","value","Array","isRecord","walkMap","mappingFn","arguments","undefined","v","idx","fromEntries","_ref4","k","defaultUpdateFunction","changed","applySourceDocuments","result","resultSourceMap","getCachedDocument","updateFn","_a","resolveMappingResult","type","source","sourceDocument","documents","document","sourcePath","paths","cachedDocument","parsedPath","changedValue","getField","previousValue","obj","find","item","_key","createEditIntentLink","studioUrl","_ref5","_id","_type","_studioUrl","_path","encodeJsonPathToUriComponent","encodeURIComponent","i","encodeIntoResult","encoder","options","matchPathSegments","sourcePathSegments","fullSourceSegments","slice","encode"],"mappings":"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"}
package/dist/csm.d.ts CHANGED
@@ -1,5 +1,38 @@
1
1
  /// <reference types="node" />
2
2
 
3
+ /**
4
+ * Used to tag types that is set to `any` as a temporary measure, but should be replaced with proper typings in the future
5
+ * @internal
6
+ */
7
+ export declare type Any = any
8
+
9
+ /**
10
+ * Optimistically applies source documents to a result, using the content source map to trace fields.
11
+ * Can be used to apply mutations to documents being edited in a Studio, or any mutation on Content Lake, to a result with extremely low latency.
12
+ * @public
13
+ */
14
+ export declare function applySourceDocuments<Result = unknown>(
15
+ result: Result,
16
+ resultSourceMap: ContentSourceMap | undefined,
17
+ getCachedDocument: (
18
+ sourceDocument: ContentSourceMapDocuments[number],
19
+ ) => SanityDocument | undefined,
20
+ updateFn?: ApplySourceDocumentsUpdateFunction,
21
+ ): Result
22
+
23
+ /**
24
+ * @public
25
+ */
26
+ export declare type ApplySourceDocumentsUpdateFunction = <T = unknown>(
27
+ changedValue: T,
28
+ context: {
29
+ cachedDocument: SanityDocument
30
+ previousValue: T
31
+ sourceDocument: ContentSourceMapDocuments[number]
32
+ sourcePath: PathSegment[]
33
+ },
34
+ ) => T
35
+
3
36
  /** @public */
4
37
  export declare interface ContentSourceMap {
5
38
  mappings: ContentSourceMapMappings
@@ -92,7 +125,9 @@ export declare function createEditIntentLink(
92
125
  /** @public */
93
126
  export declare type EditIntentLink = `/intent/edit/id=${string};type=${string};path=${string}`
94
127
 
95
- /** @alpha */
128
+ /**
129
+ * @alpha
130
+ */
96
131
  export declare function encode<R, E>(
97
132
  result: R,
98
133
  csm: ContentSourceMap,
@@ -102,7 +137,9 @@ export declare function encode<R, E>(
102
137
  },
103
138
  ): R
104
139
 
105
- /** @alpha */
140
+ /**
141
+ * @alpha
142
+ */
106
143
  export declare function encodeIntoResult<R>(
107
144
  result: R,
108
145
  csm: ContentSourceMap,
@@ -115,14 +152,18 @@ export declare function encodeIntoResult<R>(
115
152
  /** @public */
116
153
  export declare function encodeJsonPathToUriComponent(path: string | PathSegment[]): string
117
154
 
118
- /** @alpha */
155
+ /**
156
+ * @alpha
157
+ */
119
158
  export declare type Encoder<E> = (
120
159
  value: string,
121
160
  sourceDocument: ContentSourceMapDocuments[number],
122
161
  path: PathSegment[],
123
162
  ) => E
124
163
 
125
- /** @internal */
164
+ /**
165
+ * @internal
166
+ */
126
167
  export declare function jsonPath(
127
168
  path: PathSegment[],
128
169
  opts?: {
@@ -136,18 +177,37 @@ export declare type KeyedSegment = {
136
177
  index: number
137
178
  }
138
179
 
139
- /** @internal */
180
+ /**
181
+ * @internal
182
+ */
140
183
  export declare function parseJsonPath(path: string): PathSegment[]
141
184
 
142
185
  /** @public */
143
186
  export declare type PathSegment = string | number | KeyedSegment
144
187
 
145
- /** @alpha */
188
+ /**
189
+ * @alpha
190
+ */
146
191
  export declare function resolveMapping(
147
192
  resultPath: PathSegment[],
148
- csm: ContentSourceMap,
193
+ csm?: ContentSourceMap,
149
194
  ): [ContentSourceMapMapping, string, string] | undefined
150
195
 
196
+ /** @internal */
197
+ export declare type SanityDocument<T extends Record<string, Any> = Record<string, Any>> = {
198
+ [P in keyof T]: T[P]
199
+ } & {
200
+ _id: string
201
+ _rev: string
202
+ _type: string
203
+ _createdAt: string
204
+ _updatedAt: string
205
+ /**
206
+ * Present when `perspective` is set to `previewDrafts`
207
+ */
208
+ _originalId?: string
209
+ }
210
+
151
211
  /** @public */
152
212
  export declare type StudioUrl =
153
213
  | `/${string}`
@@ -155,12 +215,15 @@ export declare type StudioUrl =
155
215
  | `https://${string}`
156
216
  | string
157
217
 
158
- /** generic way to walk a nested object or array and apply a mapping function to each value
218
+ /**
219
+ * generic way to walk a nested object or array and apply a mapping function to each value
159
220
  * @alpha
160
221
  */
161
222
  export declare function walkMap(value: unknown, mappingFn: WalkMapFn, path?: PathSegment[]): unknown
162
223
 
163
- /** @alpha */
224
+ /**
225
+ * @alpha
226
+ */
164
227
  export declare type WalkMapFn = (value: unknown, path: PathSegment[]) => unknown
165
228
 
166
229
  export {}
package/dist/csm.js CHANGED
@@ -63,11 +63,115 @@ function parseJsonPath(path) {
63
63
  }
64
64
  return parsed;
65
65
  }
66
- function createEditIntentLink(studioUrl, _ref, path) {
66
+ function resolveMapping(resultPath, csm) {
67
+ if (!(csm == null ? void 0 : csm.mappings)) {
68
+ return void 0;
69
+ }
70
+ const resultJsonPath = jsonPath(resultPath);
71
+ if (csm.mappings[resultJsonPath] !== void 0) {
72
+ return [csm.mappings[resultJsonPath], resultJsonPath, ""];
73
+ }
74
+ const mappings = Object.entries(csm.mappings).filter(_ref => {
75
+ let [key] = _ref;
76
+ return resultJsonPath.startsWith(key);
77
+ }).sort((_ref2, _ref3) => {
78
+ let [key1] = _ref2;
79
+ let [key2] = _ref3;
80
+ return key2.length - key1.length;
81
+ });
82
+ if (mappings.length == 0) {
83
+ return void 0;
84
+ }
85
+ const [matchedPath, mapping] = mappings[0];
86
+ const pathSuffix = resultJsonPath.substring(matchedPath.length);
87
+ return [mapping, matchedPath, pathSuffix];
88
+ }
89
+ function isArray(value) {
90
+ return value !== null && Array.isArray(value);
91
+ }
92
+ function isRecord(value) {
93
+ return typeof value === "object" && value !== null;
94
+ }
95
+ function walkMap(value, mappingFn) {
96
+ let path = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
97
+ if (isArray(value)) {
98
+ return value.map((v, idx) => {
99
+ if (isRecord(v)) {
100
+ const key = v["_key"];
101
+ if (typeof key === "string") {
102
+ return walkMap(v, mappingFn, path.concat({
103
+ key,
104
+ index: idx
105
+ }));
106
+ }
107
+ }
108
+ return walkMap(v, mappingFn, path.concat(idx));
109
+ });
110
+ }
111
+ if (isRecord(value)) {
112
+ return Object.fromEntries(Object.entries(value).map(_ref4 => {
113
+ let [k, v] = _ref4;
114
+ return [k, walkMap(v, mappingFn, path.concat(k))];
115
+ }));
116
+ }
117
+ return mappingFn(value, path);
118
+ }
119
+ const defaultUpdateFunction = changed => changed;
120
+ function applySourceDocuments(result, resultSourceMap, getCachedDocument) {
121
+ let updateFn = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : defaultUpdateFunction;
122
+ if (!resultSourceMap) return result;
123
+ return walkMap(result, (value, path) => {
124
+ var _a;
125
+ const resolveMappingResult = resolveMapping(path, resultSourceMap);
126
+ if (!resolveMappingResult) {
127
+ return value;
128
+ }
129
+ const [mapping,, pathSuffix] = resolveMappingResult;
130
+ if (mapping.type !== "value") {
131
+ return value;
132
+ }
133
+ if (mapping.source.type !== "documentValue") {
134
+ return value;
135
+ }
136
+ const sourceDocument = resultSourceMap.documents[mapping.source.document];
137
+ const sourcePath = resultSourceMap.paths[mapping.source.path];
138
+ if (sourceDocument) {
139
+ const cachedDocument = getCachedDocument(sourceDocument);
140
+ if (!cachedDocument) {
141
+ return value;
142
+ }
143
+ const parsedPath = parseJsonPath(sourcePath + pathSuffix);
144
+ const changedValue = cachedDocument ? (_a = getField(cachedDocument, parsedPath)) != null ? _a : value : value;
145
+ return value === changedValue ? value : updateFn(changedValue, {
146
+ cachedDocument,
147
+ previousValue: value,
148
+ sourceDocument,
149
+ sourcePath: parsedPath
150
+ });
151
+ }
152
+ return value;
153
+ });
154
+ }
155
+ function getField(obj, path) {
156
+ let value = obj;
157
+ for (const segment of path) {
158
+ if (typeof segment === "string") {
159
+ value = value[segment];
160
+ } else {
161
+ const match = typeof segment === "object" ? value.find(item => item._key === segment.key) : value[segment];
162
+ value = match || null;
163
+ }
164
+ if (value === null || value === void 0) {
165
+ break;
166
+ }
167
+ }
168
+ return value;
169
+ }
170
+ function createEditIntentLink(studioUrl, _ref5, path) {
67
171
  let {
68
172
  _id,
69
173
  _type
70
- } = _ref;
174
+ } = _ref5;
71
175
  const _studioUrl = studioUrl.replace(/\/$/, "");
72
176
  const _path = encodeJsonPathToUriComponent(path);
73
177
  return "".concat(_studioUrl, "/intent/edit/id=").concat(_id, ";type=").concat(_type, ";path=").concat(_path);
@@ -76,15 +180,6 @@ function encodeJsonPathToUriComponent(path) {
76
180
  const sourcePath = Array.isArray(path) ? path : parseJsonPath(path);
77
181
  return encodeURIComponent(sourcePath.map((key, i) => typeof key === "number" ? "[".concat(key, "]") : i > 0 ? ".".concat(key) : key).join(""));
78
182
  }
79
- function isRecord(value) {
80
- return typeof value === "object" && value !== null;
81
- }
82
- function isArray(value) {
83
- return value !== null && Array.isArray(value);
84
- }
85
- function encode(result, csm, encoder, options) {
86
- return encodeIntoResult(result, csm, encoder, options);
87
- }
88
183
  function encodeIntoResult(result, csm, encoder, options) {
89
184
  return walkMap(result, (value, path) => {
90
185
  if (typeof value !== "string") {
@@ -112,49 +207,8 @@ function encodeIntoResult(result, csm, encoder, options) {
112
207
  return encoder(value, sourceDocument, parseJsonPath(sourcePath + pathSuffix));
113
208
  });
114
209
  }
115
- function walkMap(value, mappingFn) {
116
- let path = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
117
- if (isArray(value)) {
118
- return value.map((v, idx) => {
119
- if (isRecord(v)) {
120
- const key = v["_key"];
121
- if (typeof key === "string") {
122
- return walkMap(v, mappingFn, path.concat({
123
- key,
124
- index: idx
125
- }));
126
- }
127
- }
128
- return walkMap(v, mappingFn, path.concat(idx));
129
- });
130
- }
131
- if (isRecord(value)) {
132
- return Object.fromEntries(Object.entries(value).map(_ref2 => {
133
- let [k, v] = _ref2;
134
- return [k, walkMap(v, mappingFn, path.concat(k))];
135
- }));
136
- }
137
- return mappingFn(value, path);
138
- }
139
- function resolveMapping(resultPath, csm) {
140
- const resultJsonPath = jsonPath(resultPath);
141
- if (csm.mappings[resultJsonPath] !== void 0) {
142
- return [csm.mappings[resultJsonPath], resultJsonPath, ""];
143
- }
144
- const mappings = Object.entries(csm.mappings).filter(_ref3 => {
145
- let [key] = _ref3;
146
- return resultJsonPath.startsWith(key);
147
- }).sort((_ref4, _ref5) => {
148
- let [key1] = _ref4;
149
- let [key2] = _ref5;
150
- return key2.length - key1.length;
151
- });
152
- if (mappings.length == 0) {
153
- return void 0;
154
- }
155
- const [matchedPath, mapping] = mappings[0];
156
- const pathSuffix = resultJsonPath.substring(matchedPath.length);
157
- return [mapping, matchedPath, pathSuffix];
210
+ function encode(result, csm, encoder, options) {
211
+ return encodeIntoResult(result, csm, encoder, options);
158
212
  }
159
- export { createEditIntentLink, encode, encodeIntoResult, encodeJsonPathToUriComponent, jsonPath, parseJsonPath, resolveMapping, walkMap };
213
+ export { applySourceDocuments, createEditIntentLink, encode, encodeIntoResult, encodeJsonPathToUriComponent, jsonPath, parseJsonPath, resolveMapping, walkMap };
160
214
  //# sourceMappingURL=csm.js.map