@sitecore-content-sdk/core 2.1.3 → 2.1.4-canary.20260824045921

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.
@@ -3,6 +3,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getMetadata = getMetadata;
4
4
  const child_process_1 = require("child_process");
5
5
  const trackedScopes = ['@sitecore', '@sitecore-feaas', '@sitecore-content-sdk'];
6
+ // pnpm and yarn match name patterns as globs, in which '*' does not cross the scope separator,
7
+ // so both segments are wildcarded to cover every '@sitecore*' scope.
8
+ const TRACKED_SCOPE_GLOB = '"@sitecore*/*"';
9
+ const PNPM_DEPENDENCY_GROUPS = [
10
+ 'dependencies',
11
+ 'devDependencies',
12
+ 'optionalDependencies',
13
+ 'unsavedDependencies',
14
+ ];
15
+ // Matches the 'name@version' entries of the tree printed by `bun pm ls`, e.g '├── @scope/pkg@1.0.0'
16
+ const BUN_PACKAGE_ENTRY = /^[\s│├└─]*((?:@[^\s@/]+\/)?[^\s@/]+)@([^\s]+)$/;
17
+ // Dependency trees of an app can be sizeable, the 1MB default of execSync is not enough.
18
+ const MAX_OUTPUT_BUFFER = 10 * 1024 * 1024;
6
19
  /**
7
20
  * Get application metadata
8
21
  * @param {boolean} allowWorkspaces - Whether to allow workspaces in the metadata generation.
@@ -10,12 +23,17 @@ const trackedScopes = ['@sitecore', '@sitecore-feaas', '@sitecore-content-sdk'];
10
23
  */
11
24
  function getMetadata(allowWorkspaces = false) {
12
25
  const metadata = { packages: {} };
26
+ const packageManagement = getPackageManagement(allowWorkspaces);
27
+ const { query, parse } = packageManagement[detectPackageManager(packageManagement)];
13
28
  let queryResult = [];
14
29
  try {
15
- queryResult = JSON.parse((0, child_process_1.execSync)(`npm query [name*=@sitecore] --workspaces ${allowWorkspaces}`).toString());
30
+ queryResult = parse((0, child_process_1.execSync)(query, {
31
+ maxBuffer: MAX_OUTPUT_BUFFER,
32
+ stdio: ['ignore', 'pipe', 'pipe'],
33
+ }).toString());
16
34
  }
17
35
  catch (error) {
18
- console.error('Failed to retrieve sitecore packages using npm query', error);
36
+ console.error(`Failed to retrieve sitecore packages using '${query}'`, error);
19
37
  return metadata;
20
38
  }
21
39
  metadata.packages = getPackagesFromQueryResult(queryResult);
@@ -35,3 +53,226 @@ function getPackagesFromQueryResult(scPackages) {
35
53
  });
36
54
  return packages;
37
55
  }
56
+ /**
57
+ * Build the listing command and parser for each supported package manager.
58
+ * Yarn classic is a dedicated entry because its command differs from yarn berry.
59
+ * @param {boolean} allowWorkspaces whether packages of all workspaces should be included
60
+ * @returns {Record<string, PackagesQuery>} query and parser per package manager
61
+ * @internal
62
+ */
63
+ function getPackageManagement(allowWorkspaces) {
64
+ return {
65
+ pnpm: {
66
+ query: `pnpm list --depth Infinity --json ${allowWorkspaces ? '--recursive ' : ''}${TRACKED_SCOPE_GLOB}`,
67
+ parse: parsePnpmList,
68
+ },
69
+ npm: {
70
+ query: `npm query [name*=@sitecore] --workspaces ${allowWorkspaces}`,
71
+ parse: parseNpmQuery,
72
+ },
73
+ yarn: {
74
+ query: `yarn info --json --name-only --recursive ${allowWorkspaces ? '--all ' : ''}${TRACKED_SCOPE_GLOB}`,
75
+ parse: parseYarnInfo,
76
+ },
77
+ yarnClassic: {
78
+ query: `yarn list --json --depth 0 --pattern ${TRACKED_SCOPE_GLOB}`,
79
+ parse: parseYarnClassicList,
80
+ },
81
+ bun: {
82
+ // `bun pm ls` has no name filter and only recently gained JSON output, so the tree it
83
+ // prints is parsed instead, and filtered by scope afterwards.
84
+ query: 'bun pm ls --all',
85
+ parse: parseBunPackageList,
86
+ },
87
+ };
88
+ }
89
+ /**
90
+ * Detect the package manager that runs the current process. Package managers advertise themselves
91
+ * through the environment they set up for the commands they run, so nothing has to be read from
92
+ * disk - which matters because the app being built is not necessarily the project that declares
93
+ * the package manager (workspaces).
94
+ * @param {Record<string, PackagesQuery>} packageManagement supported package managers
95
+ * @returns {string} the detected package manager, npm when it could not be determined
96
+ * @internal
97
+ */
98
+ function detectPackageManager(packageManagement) {
99
+ const managerNames = Object.keys(packageManagement).sort((left, right) => right.length - left.length);
100
+ const { npm_config_user_agent: userAgent, npm_execpath: execPath } = process.env;
101
+ // e.g. 'pnpm/10.33.0 npm/? node/v22.11.0 win32 x64'
102
+ if (userAgent) {
103
+ const [descriptor] = userAgent.trim().split(/\s+/);
104
+ const separatorIndex = descriptor.lastIndexOf('/');
105
+ const name = (separatorIndex === -1 ? descriptor : descriptor.slice(0, separatorIndex)).toLowerCase();
106
+ const knownName = managerNames.find((candidate) => candidate === name);
107
+ if (knownName) {
108
+ const majorVersion = parseInt(descriptor.slice(separatorIndex + 1), 10);
109
+ return knownName === 'yarn' && majorVersion === 1 ? 'yarnClassic' : knownName;
110
+ }
111
+ }
112
+ // e.g. 'C:\\Users\\dev\\AppData\\Roaming\\npm\\node_modules\\pnpm\\bin\\pnpm.cjs', which does
113
+ // not carry a version
114
+ if (execPath) {
115
+ const executable = execPath.toLowerCase().split(/[\\/]/).pop();
116
+ const knownName = managerNames.find((candidate) => executable.includes(candidate));
117
+ if (knownName) {
118
+ return knownName;
119
+ }
120
+ }
121
+ return 'npm';
122
+ }
123
+ /**
124
+ * Parse the output of `npm query`, which is a JSON array of package manifests
125
+ * @param {string} output command output
126
+ * @returns {Package[]} installed packages
127
+ * @internal
128
+ */
129
+ function parseNpmQuery(output) {
130
+ const parsed = JSON.parse(output);
131
+ return Array.isArray(parsed)
132
+ ? parsed.filter((scPackage) => typeof (scPackage === null || scPackage === void 0 ? void 0 : scPackage.name) === 'string' && typeof (scPackage === null || scPackage === void 0 ? void 0 : scPackage.version) === 'string')
133
+ : [];
134
+ }
135
+ /**
136
+ * Parse the output of `pnpm list --json`, which is a dependency tree per project
137
+ * @param {string} output command output
138
+ * @returns {Package[]} installed packages
139
+ * @internal
140
+ */
141
+ function parsePnpmList(output) {
142
+ if (!output.trim()) {
143
+ return [];
144
+ }
145
+ const parsed = JSON.parse(output);
146
+ const projects = Array.isArray(parsed) ? parsed : [parsed];
147
+ const packages = [];
148
+ const visited = new Set();
149
+ const collect = (dependencies) => {
150
+ if (!dependencies) {
151
+ return;
152
+ }
153
+ Object.entries(dependencies).forEach(([name, node]) => {
154
+ var _a;
155
+ if (!node) {
156
+ return;
157
+ }
158
+ const key = `${name}@${(_a = node.version) !== null && _a !== void 0 ? _a : ''}`;
159
+ // the same package can be reached through many paths, walk it once
160
+ if (visited.has(key)) {
161
+ return;
162
+ }
163
+ visited.add(key);
164
+ if (node.version) {
165
+ packages.push({ name, version: node.version });
166
+ }
167
+ collect(node.dependencies);
168
+ });
169
+ };
170
+ projects.forEach((project) => PNPM_DEPENDENCY_GROUPS.forEach((group) => collect(project === null || project === void 0 ? void 0 : project[group])));
171
+ return packages;
172
+ }
173
+ /**
174
+ * Parse the output of `yarn info --json`, which is an NDJSON stream of package locators
175
+ * @param {string} output command output
176
+ * @returns {Package[]} installed packages
177
+ * @internal
178
+ */
179
+ function parseYarnInfo(output) {
180
+ return parseJsonLines(output).reduce((packages, entry) => {
181
+ const locator = typeof entry === 'string' ? entry : getRecordString(entry, 'value');
182
+ const scPackage = locator ? parsePackageLocator(locator) : undefined;
183
+ return scPackage ? [...packages, scPackage] : packages;
184
+ }, []);
185
+ }
186
+ /**
187
+ * Parse the output of `yarn list --json` (yarn classic), which is an NDJSON stream in which the
188
+ * 'tree' entry holds the hoisted dependency trees
189
+ * @param {string} output command output
190
+ * @returns {Package[]} installed packages
191
+ * @internal
192
+ */
193
+ function parseYarnClassicList(output) {
194
+ return parseJsonLines(output).reduce((packages, entry) => {
195
+ const data = isRecord(entry) && entry.type === 'tree' ? entry.data : undefined;
196
+ const trees = isRecord(data) && Array.isArray(data.trees) ? data.trees : undefined;
197
+ if (!trees) {
198
+ return packages;
199
+ }
200
+ return trees.reduce((treePackages, tree) => {
201
+ const name = getRecordString(tree, 'name');
202
+ const scPackage = name ? parsePackageLocator(name) : undefined;
203
+ return scPackage ? [...treePackages, scPackage] : treePackages;
204
+ }, packages);
205
+ }, []);
206
+ }
207
+ /**
208
+ * Parse the dependency tree printed by `bun pm ls`
209
+ * @param {string} output command output
210
+ * @returns {Package[]} installed packages
211
+ * @internal
212
+ */
213
+ function parseBunPackageList(output) {
214
+ return output.split(/\r?\n/).reduce((packages, line) => {
215
+ const match = BUN_PACKAGE_ENTRY.exec(line.trim());
216
+ return match ? [...packages, { name: match[1], version: match[2] }] : packages;
217
+ }, []);
218
+ }
219
+ /**
220
+ * Parse an NDJSON stream, skipping lines that are not valid JSON - package managers mix
221
+ * diagnostics into their output
222
+ * @param {string} output command output
223
+ * @returns {unknown[]} parsed entries
224
+ * @internal
225
+ */
226
+ function parseJsonLines(output) {
227
+ return output.split(/\r?\n/).reduce((entries, line) => {
228
+ const trimmed = line.trim();
229
+ if (!trimmed) {
230
+ return entries;
231
+ }
232
+ try {
233
+ return [...entries, JSON.parse(trimmed)];
234
+ }
235
+ catch (_a) {
236
+ return entries;
237
+ }
238
+ }, []);
239
+ }
240
+ /**
241
+ * Narrow an unknown value to a plain object record
242
+ * @param {unknown} value value to check
243
+ * @returns {value is Record<string, unknown>} whether the value is a non-null object
244
+ * @internal
245
+ */
246
+ function isRecord(value) {
247
+ return typeof value === 'object' && value !== null;
248
+ }
249
+ /**
250
+ * Read a string property from an unknown object
251
+ * @param {unknown} value object that may contain the property
252
+ * @param {string} key property name
253
+ * @returns {string | undefined} the string value, or undefined when it is missing or not a string
254
+ * @internal
255
+ */
256
+ function getRecordString(value, key) {
257
+ if (!isRecord(value)) {
258
+ return undefined;
259
+ }
260
+ const property = value[key];
261
+ return typeof property === 'string' ? property : undefined;
262
+ }
263
+ /**
264
+ * Split a package locator into name and version, e.g. '@scope/pkg@npm:1.0.0'. Yarn prefixes the
265
+ * reference with the protocol it was resolved with, which is not part of the version.
266
+ * @param {string} locator package locator
267
+ * @returns {Package | undefined} the package, or undefined when the locator could not be parsed
268
+ * @internal
269
+ */
270
+ function parsePackageLocator(locator) {
271
+ const separatorIndex = locator.lastIndexOf('@');
272
+ if (separatorIndex <= 0) {
273
+ return undefined;
274
+ }
275
+ const reference = locator.slice(separatorIndex + 1);
276
+ const version = reference.slice(reference.lastIndexOf(':') + 1);
277
+ return version ? { name: locator.slice(0, separatorIndex), version } : undefined;
278
+ }
@@ -1,5 +1,18 @@
1
1
  import { execSync } from 'child_process';
2
2
  const trackedScopes = ['@sitecore', '@sitecore-feaas', '@sitecore-content-sdk'];
3
+ // pnpm and yarn match name patterns as globs, in which '*' does not cross the scope separator,
4
+ // so both segments are wildcarded to cover every '@sitecore*' scope.
5
+ const TRACKED_SCOPE_GLOB = '"@sitecore*/*"';
6
+ const PNPM_DEPENDENCY_GROUPS = [
7
+ 'dependencies',
8
+ 'devDependencies',
9
+ 'optionalDependencies',
10
+ 'unsavedDependencies',
11
+ ];
12
+ // Matches the 'name@version' entries of the tree printed by `bun pm ls`, e.g '├── @scope/pkg@1.0.0'
13
+ const BUN_PACKAGE_ENTRY = /^[\s│├└─]*((?:@[^\s@/]+\/)?[^\s@/]+)@([^\s]+)$/;
14
+ // Dependency trees of an app can be sizeable, the 1MB default of execSync is not enough.
15
+ const MAX_OUTPUT_BUFFER = 10 * 1024 * 1024;
3
16
  /**
4
17
  * Get application metadata
5
18
  * @param {boolean} allowWorkspaces - Whether to allow workspaces in the metadata generation.
@@ -7,12 +20,17 @@ const trackedScopes = ['@sitecore', '@sitecore-feaas', '@sitecore-content-sdk'];
7
20
  */
8
21
  export function getMetadata(allowWorkspaces = false) {
9
22
  const metadata = { packages: {} };
23
+ const packageManagement = getPackageManagement(allowWorkspaces);
24
+ const { query, parse } = packageManagement[detectPackageManager(packageManagement)];
10
25
  let queryResult = [];
11
26
  try {
12
- queryResult = JSON.parse(execSync(`npm query [name*=@sitecore] --workspaces ${allowWorkspaces}`).toString());
27
+ queryResult = parse(execSync(query, {
28
+ maxBuffer: MAX_OUTPUT_BUFFER,
29
+ stdio: ['ignore', 'pipe', 'pipe'],
30
+ }).toString());
13
31
  }
14
32
  catch (error) {
15
- console.error('Failed to retrieve sitecore packages using npm query', error);
33
+ console.error(`Failed to retrieve sitecore packages using '${query}'`, error);
16
34
  return metadata;
17
35
  }
18
36
  metadata.packages = getPackagesFromQueryResult(queryResult);
@@ -32,3 +50,226 @@ function getPackagesFromQueryResult(scPackages) {
32
50
  });
33
51
  return packages;
34
52
  }
53
+ /**
54
+ * Build the listing command and parser for each supported package manager.
55
+ * Yarn classic is a dedicated entry because its command differs from yarn berry.
56
+ * @param {boolean} allowWorkspaces whether packages of all workspaces should be included
57
+ * @returns {Record<string, PackagesQuery>} query and parser per package manager
58
+ * @internal
59
+ */
60
+ function getPackageManagement(allowWorkspaces) {
61
+ return {
62
+ pnpm: {
63
+ query: `pnpm list --depth Infinity --json ${allowWorkspaces ? '--recursive ' : ''}${TRACKED_SCOPE_GLOB}`,
64
+ parse: parsePnpmList,
65
+ },
66
+ npm: {
67
+ query: `npm query [name*=@sitecore] --workspaces ${allowWorkspaces}`,
68
+ parse: parseNpmQuery,
69
+ },
70
+ yarn: {
71
+ query: `yarn info --json --name-only --recursive ${allowWorkspaces ? '--all ' : ''}${TRACKED_SCOPE_GLOB}`,
72
+ parse: parseYarnInfo,
73
+ },
74
+ yarnClassic: {
75
+ query: `yarn list --json --depth 0 --pattern ${TRACKED_SCOPE_GLOB}`,
76
+ parse: parseYarnClassicList,
77
+ },
78
+ bun: {
79
+ // `bun pm ls` has no name filter and only recently gained JSON output, so the tree it
80
+ // prints is parsed instead, and filtered by scope afterwards.
81
+ query: 'bun pm ls --all',
82
+ parse: parseBunPackageList,
83
+ },
84
+ };
85
+ }
86
+ /**
87
+ * Detect the package manager that runs the current process. Package managers advertise themselves
88
+ * through the environment they set up for the commands they run, so nothing has to be read from
89
+ * disk - which matters because the app being built is not necessarily the project that declares
90
+ * the package manager (workspaces).
91
+ * @param {Record<string, PackagesQuery>} packageManagement supported package managers
92
+ * @returns {string} the detected package manager, npm when it could not be determined
93
+ * @internal
94
+ */
95
+ function detectPackageManager(packageManagement) {
96
+ const managerNames = Object.keys(packageManagement).sort((left, right) => right.length - left.length);
97
+ const { npm_config_user_agent: userAgent, npm_execpath: execPath } = process.env;
98
+ // e.g. 'pnpm/10.33.0 npm/? node/v22.11.0 win32 x64'
99
+ if (userAgent) {
100
+ const [descriptor] = userAgent.trim().split(/\s+/);
101
+ const separatorIndex = descriptor.lastIndexOf('/');
102
+ const name = (separatorIndex === -1 ? descriptor : descriptor.slice(0, separatorIndex)).toLowerCase();
103
+ const knownName = managerNames.find((candidate) => candidate === name);
104
+ if (knownName) {
105
+ const majorVersion = parseInt(descriptor.slice(separatorIndex + 1), 10);
106
+ return knownName === 'yarn' && majorVersion === 1 ? 'yarnClassic' : knownName;
107
+ }
108
+ }
109
+ // e.g. 'C:\\Users\\dev\\AppData\\Roaming\\npm\\node_modules\\pnpm\\bin\\pnpm.cjs', which does
110
+ // not carry a version
111
+ if (execPath) {
112
+ const executable = execPath.toLowerCase().split(/[\\/]/).pop();
113
+ const knownName = managerNames.find((candidate) => executable.includes(candidate));
114
+ if (knownName) {
115
+ return knownName;
116
+ }
117
+ }
118
+ return 'npm';
119
+ }
120
+ /**
121
+ * Parse the output of `npm query`, which is a JSON array of package manifests
122
+ * @param {string} output command output
123
+ * @returns {Package[]} installed packages
124
+ * @internal
125
+ */
126
+ function parseNpmQuery(output) {
127
+ const parsed = JSON.parse(output);
128
+ return Array.isArray(parsed)
129
+ ? parsed.filter((scPackage) => typeof (scPackage === null || scPackage === void 0 ? void 0 : scPackage.name) === 'string' && typeof (scPackage === null || scPackage === void 0 ? void 0 : scPackage.version) === 'string')
130
+ : [];
131
+ }
132
+ /**
133
+ * Parse the output of `pnpm list --json`, which is a dependency tree per project
134
+ * @param {string} output command output
135
+ * @returns {Package[]} installed packages
136
+ * @internal
137
+ */
138
+ function parsePnpmList(output) {
139
+ if (!output.trim()) {
140
+ return [];
141
+ }
142
+ const parsed = JSON.parse(output);
143
+ const projects = Array.isArray(parsed) ? parsed : [parsed];
144
+ const packages = [];
145
+ const visited = new Set();
146
+ const collect = (dependencies) => {
147
+ if (!dependencies) {
148
+ return;
149
+ }
150
+ Object.entries(dependencies).forEach(([name, node]) => {
151
+ var _a;
152
+ if (!node) {
153
+ return;
154
+ }
155
+ const key = `${name}@${(_a = node.version) !== null && _a !== void 0 ? _a : ''}`;
156
+ // the same package can be reached through many paths, walk it once
157
+ if (visited.has(key)) {
158
+ return;
159
+ }
160
+ visited.add(key);
161
+ if (node.version) {
162
+ packages.push({ name, version: node.version });
163
+ }
164
+ collect(node.dependencies);
165
+ });
166
+ };
167
+ projects.forEach((project) => PNPM_DEPENDENCY_GROUPS.forEach((group) => collect(project === null || project === void 0 ? void 0 : project[group])));
168
+ return packages;
169
+ }
170
+ /**
171
+ * Parse the output of `yarn info --json`, which is an NDJSON stream of package locators
172
+ * @param {string} output command output
173
+ * @returns {Package[]} installed packages
174
+ * @internal
175
+ */
176
+ function parseYarnInfo(output) {
177
+ return parseJsonLines(output).reduce((packages, entry) => {
178
+ const locator = typeof entry === 'string' ? entry : getRecordString(entry, 'value');
179
+ const scPackage = locator ? parsePackageLocator(locator) : undefined;
180
+ return scPackage ? [...packages, scPackage] : packages;
181
+ }, []);
182
+ }
183
+ /**
184
+ * Parse the output of `yarn list --json` (yarn classic), which is an NDJSON stream in which the
185
+ * 'tree' entry holds the hoisted dependency trees
186
+ * @param {string} output command output
187
+ * @returns {Package[]} installed packages
188
+ * @internal
189
+ */
190
+ function parseYarnClassicList(output) {
191
+ return parseJsonLines(output).reduce((packages, entry) => {
192
+ const data = isRecord(entry) && entry.type === 'tree' ? entry.data : undefined;
193
+ const trees = isRecord(data) && Array.isArray(data.trees) ? data.trees : undefined;
194
+ if (!trees) {
195
+ return packages;
196
+ }
197
+ return trees.reduce((treePackages, tree) => {
198
+ const name = getRecordString(tree, 'name');
199
+ const scPackage = name ? parsePackageLocator(name) : undefined;
200
+ return scPackage ? [...treePackages, scPackage] : treePackages;
201
+ }, packages);
202
+ }, []);
203
+ }
204
+ /**
205
+ * Parse the dependency tree printed by `bun pm ls`
206
+ * @param {string} output command output
207
+ * @returns {Package[]} installed packages
208
+ * @internal
209
+ */
210
+ function parseBunPackageList(output) {
211
+ return output.split(/\r?\n/).reduce((packages, line) => {
212
+ const match = BUN_PACKAGE_ENTRY.exec(line.trim());
213
+ return match ? [...packages, { name: match[1], version: match[2] }] : packages;
214
+ }, []);
215
+ }
216
+ /**
217
+ * Parse an NDJSON stream, skipping lines that are not valid JSON - package managers mix
218
+ * diagnostics into their output
219
+ * @param {string} output command output
220
+ * @returns {unknown[]} parsed entries
221
+ * @internal
222
+ */
223
+ function parseJsonLines(output) {
224
+ return output.split(/\r?\n/).reduce((entries, line) => {
225
+ const trimmed = line.trim();
226
+ if (!trimmed) {
227
+ return entries;
228
+ }
229
+ try {
230
+ return [...entries, JSON.parse(trimmed)];
231
+ }
232
+ catch (_a) {
233
+ return entries;
234
+ }
235
+ }, []);
236
+ }
237
+ /**
238
+ * Narrow an unknown value to a plain object record
239
+ * @param {unknown} value value to check
240
+ * @returns {value is Record<string, unknown>} whether the value is a non-null object
241
+ * @internal
242
+ */
243
+ function isRecord(value) {
244
+ return typeof value === 'object' && value !== null;
245
+ }
246
+ /**
247
+ * Read a string property from an unknown object
248
+ * @param {unknown} value object that may contain the property
249
+ * @param {string} key property name
250
+ * @returns {string | undefined} the string value, or undefined when it is missing or not a string
251
+ * @internal
252
+ */
253
+ function getRecordString(value, key) {
254
+ if (!isRecord(value)) {
255
+ return undefined;
256
+ }
257
+ const property = value[key];
258
+ return typeof property === 'string' ? property : undefined;
259
+ }
260
+ /**
261
+ * Split a package locator into name and version, e.g. '@scope/pkg@npm:1.0.0'. Yarn prefixes the
262
+ * reference with the protocol it was resolved with, which is not part of the version.
263
+ * @param {string} locator package locator
264
+ * @returns {Package | undefined} the package, or undefined when the locator could not be parsed
265
+ * @internal
266
+ */
267
+ function parsePackageLocator(locator) {
268
+ const separatorIndex = locator.lastIndexOf('@');
269
+ if (separatorIndex <= 0) {
270
+ return undefined;
271
+ }
272
+ const reference = locator.slice(separatorIndex + 1);
273
+ const version = reference.slice(reference.lastIndexOf(':') + 1);
274
+ return version ? { name: locator.slice(0, separatorIndex), version } : undefined;
275
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sitecore-content-sdk/core",
3
- "version": "2.1.3",
3
+ "version": "2.1.4-canary.20260824045921",
4
4
  "main": "dist/cjs/index.js",
5
5
  "module": "dist/esm/index.js",
6
6
  "sideEffects": false,
@@ -1 +1 @@
1
- {"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../../src/tools/metadata/metadata.ts"],"names":[],"mappings":"AAOA;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;CACrC;AAID;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,eAAe,GAAE,OAAe,GAAG,QAAQ,CAgBtE"}
1
+ {"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../../src/tools/metadata/metadata.ts"],"names":[],"mappings":"AAyBA;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;CACrC;AAqBD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,eAAe,GAAE,OAAe,GAAG,QAAQ,CAqBtE"}