@arkebcacy/beacon-cli-temp 0.1.4 → 0.1.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/dist/cs/entries/getEntryLocales.d.ts.map +1 -1
- package/dist/cs/entries/getEntryLocales.js +23 -10
- package/dist/cs/entries/getEntryLocales.js.map +1 -1
- package/dist/cs/labels/Label.d.ts +8 -0
- package/dist/cs/labels/Label.d.ts.map +1 -0
- package/dist/cs/labels/Label.js +7 -0
- package/dist/cs/labels/Label.js.map +1 -0
- package/dist/cs/labels/getAllLabels.d.ts +4 -0
- package/dist/cs/labels/getAllLabels.d.ts.map +1 -0
- package/dist/cs/labels/getAllLabels.js +37 -0
- package/dist/cs/labels/getAllLabels.js.map +1 -0
- package/dist/dto/entry/beaconReplacer/lib/mapItemPathToAsset.d.ts.map +1 -1
- package/dist/dto/entry/beaconReplacer/lib/mapItemPathToAsset.js +5 -1
- package/dist/dto/entry/beaconReplacer/lib/mapItemPathToAsset.js.map +1 -1
- package/dist/dto/labels/NormalizedLabels.d.ts +13 -0
- package/dist/dto/labels/NormalizedLabels.d.ts.map +1 -0
- package/dist/dto/labels/NormalizedLabels.js +25 -0
- package/dist/dto/labels/NormalizedLabels.js.map +1 -0
- package/dist/dto/labels/flatten.d.ts +4 -0
- package/dist/dto/labels/flatten.d.ts.map +1 -0
- package/dist/dto/labels/flatten.js +18 -0
- package/dist/dto/labels/flatten.js.map +1 -0
- package/dist/dto/labels/organize.d.ts +4 -0
- package/dist/dto/labels/organize.d.ts.map +1 -0
- package/dist/dto/labels/organize.js +40 -0
- package/dist/dto/labels/organize.js.map +1 -0
- package/dist/schema/entries/toFilesystem.d.ts.map +1 -1
- package/dist/schema/entries/toFilesystem.js +24 -6
- package/dist/schema/entries/toFilesystem.js.map +1 -1
- package/dist/schema/labels/toContentstack.d.ts +4 -0
- package/dist/schema/labels/toContentstack.d.ts.map +1 -0
- package/dist/schema/labels/toContentstack.js +136 -0
- package/dist/schema/labels/toContentstack.js.map +1 -0
- package/dist/schema/labels/toFilesystem.d.ts +4 -0
- package/dist/schema/labels/toFilesystem.d.ts.map +1 -0
- package/dist/schema/labels/toFilesystem.js +19 -0
- package/dist/schema/labels/toFilesystem.js.map +1 -0
- package/dist/schema/lib/createProgressBar.d.ts +1 -1
- package/dist/schema/lib/createProgressBar.d.ts.map +1 -1
- package/dist/schema/lib/createProgressBar.js +11 -1
- package/dist/schema/lib/createProgressBar.js.map +1 -1
- package/dist/schema/lib/pullModules.d.ts.map +1 -1
- package/dist/schema/lib/pullModules.js +2 -0
- package/dist/schema/lib/pullModules.js.map +1 -1
- package/dist/schema/push.d.ts.map +1 -1
- package/dist/schema/push.js +2 -0
- package/dist/schema/push.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/cs/entries/getEntryLocales.ts +28 -19
- package/src/cs/labels/Label.ts +16 -0
- package/src/cs/labels/getAllLabels.ts +43 -0
- package/src/dto/entry/beaconReplacer/lib/mapItemPathToAsset.ts +9 -1
- package/src/dto/labels/NormalizedLabels.ts +47 -0
- package/src/dto/labels/flatten.test.ts +118 -0
- package/src/dto/labels/flatten.ts +27 -0
- package/src/dto/labels/organize.test.ts +131 -0
- package/src/dto/labels/organize.ts +57 -0
- package/src/schema/entries/toFilesystem.ts +26 -6
- package/src/schema/labels/toContentstack.ts +161 -0
- package/src/schema/labels/toFilesystem.ts +23 -0
- package/src/schema/lib/createProgressBar.ts +10 -2
- package/src/schema/lib/pullModules.ts +2 -0
- package/src/schema/push.ts +2 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getEntryLocales.d.ts","sourceRoot":"","sources":["../../../src/cs/entries/getEntryLocales.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;AAG3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,WAAW,UAAU;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACrB;
|
|
1
|
+
{"version":3,"file":"getEntryLocales.d.ts","sourceRoot":"","sources":["../../../src/cs/entries/getEntryLocales.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;AAG3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,WAAW,UAAU;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACrB;AAMD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAA8B,eAAe,CAC5C,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,WAAW,CAAC,KAAK,CAAC,EAClC,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,GACpB,OAAO,CAAC,SAAS,UAAU,EAAE,CAAC,CA+ChC"}
|
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
import ContentstackError from '../api/ContentstackError.js';
|
|
2
2
|
import isRecord from '#cli/util/isRecord.js';
|
|
3
|
-
function
|
|
4
|
-
return
|
|
5
|
-
typeof o.code === 'string' &&
|
|
6
|
-
typeof o.name === 'string' &&
|
|
7
|
-
typeof o.uid === 'string');
|
|
8
|
-
}
|
|
9
|
-
function isLocalesResponse(o) {
|
|
10
|
-
return (isRecord(o) && Array.isArray(o.locales) && o.locales.every(isLocaleInfo));
|
|
3
|
+
function isLocaleInfoRecord(o) {
|
|
4
|
+
return isRecord(o) && typeof o.code === 'string';
|
|
11
5
|
}
|
|
12
6
|
/**
|
|
13
7
|
* Retrieves all available locale versions of an entry from Contentstack.
|
|
@@ -42,9 +36,28 @@ export default async function getEntryLocales(client, contentTypeUid, entryUid)
|
|
|
42
36
|
const msg = `Failed to get locales for ${contentTypeUid} entry: ${entryUid}`;
|
|
43
37
|
ContentstackError.throwIfError(error, msg);
|
|
44
38
|
const result = data;
|
|
45
|
-
if (!
|
|
39
|
+
if (!isRecord(result)) {
|
|
40
|
+
throw new Error(msg);
|
|
41
|
+
}
|
|
42
|
+
const raw = result.locales;
|
|
43
|
+
if (!Array.isArray(raw)) {
|
|
46
44
|
throw new Error(msg);
|
|
47
45
|
}
|
|
48
|
-
|
|
46
|
+
const normalized = raw.map((item) => {
|
|
47
|
+
const rec = isLocaleInfoRecord(item)
|
|
48
|
+
? item
|
|
49
|
+
: { code: '' };
|
|
50
|
+
const code = typeof rec.code === 'string' ? rec.code : '';
|
|
51
|
+
const name = typeof rec.name === 'string' ? rec.name : code;
|
|
52
|
+
const uid = typeof rec.uid === 'string' ? rec.uid : code;
|
|
53
|
+
// Only include `fallback_locale` when present as a string. Construct
|
|
54
|
+
// the object with the correct shape so TypeScript can verify it against
|
|
55
|
+
// `LocaleInfo` without unsafe casts.
|
|
56
|
+
const locale = typeof rec.fallback_locale === 'string'
|
|
57
|
+
? { code, fallback_locale: rec.fallback_locale, name, uid }
|
|
58
|
+
: { code, name, uid };
|
|
59
|
+
return locale;
|
|
60
|
+
});
|
|
61
|
+
return normalized;
|
|
49
62
|
}
|
|
50
63
|
//# sourceMappingURL=getEntryLocales.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getEntryLocales.js","sourceRoot":"","sources":["../../../src/cs/entries/getEntryLocales.ts"],"names":[],"mappings":"AACA,OAAO,iBAAiB,MAAM,6BAA6B,CAAC;AAC5D,OAAO,QAAQ,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"getEntryLocales.js","sourceRoot":"","sources":["../../../src/cs/entries/getEntryLocales.ts"],"names":[],"mappings":"AACA,OAAO,iBAAiB,MAAM,6BAA6B,CAAC;AAC5D,OAAO,QAAQ,MAAM,uBAAuB,CAAC;AAW7C,SAAS,kBAAkB,CAAC,CAAU;IACrC,OAAO,QAAQ,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC;AAClD,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,eAAe,CAC5C,MAAc,EACd,cAAkC,EAClC,QAAsB;IAEtB,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,GAAG,CACvC,kEAAkE,EAClE;QACC,MAAM,EAAE;YACP,IAAI,EAAE;gBACL,gBAAgB,EAAE,cAAc;gBAChC,SAAS,EAAE,QAAQ;aACnB;SACD;KACD,CACD,CAAC;IAEF,MAAM,GAAG,GAAG,6BAA6B,cAAc,WAAW,QAAQ,EAAE,CAAC;IAC7E,iBAAiB,CAAC,YAAY,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAE3C,MAAM,MAAM,GAAG,IAAe,CAAC;IAE/B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;IACtB,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC;IAC3B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;IACtB,CAAC;IAED,MAAM,UAAU,GAAiB,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACjD,MAAM,GAAG,GAAG,kBAAkB,CAAC,IAAI,CAAC;YACnC,CAAC,CAAC,IAAI;YACN,CAAC,CAAE,EAAE,IAAI,EAAE,EAAE,EAA8B,CAAC;QAC7C,MAAM,IAAI,GAAG,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,GAAG,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;QAC5D,MAAM,GAAG,GAAG,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;QAEzD,qEAAqE;QACrE,wEAAwE;QACxE,qCAAqC;QACrC,MAAM,MAAM,GACX,OAAO,GAAG,CAAC,eAAe,KAAK,QAAQ;YACtC,CAAC,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,CAAC,eAAe,EAAE,IAAI,EAAE,GAAG,EAAE;YAC3D,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;QAExB,OAAO,MAAM,CAAC;IACf,CAAC,CAAC,CAAC;IAEH,OAAO,UAAU,CAAC;AACnB,CAAC","sourcesContent":["import type Client from '../api/Client.js';\nimport ContentstackError from '../api/ContentstackError.js';\nimport isRecord from '#cli/util/isRecord.js';\nimport type { ContentType } from '../content-types/Types.js';\nimport type { Entry } from './Types.js';\n\nexport interface LocaleInfo {\n\treadonly code: string;\n\treadonly fallback_locale?: string;\n\treadonly name: string;\n\treadonly uid: string;\n}\n\nfunction isLocaleInfoRecord(o: unknown): o is Record<string, unknown> {\n\treturn isRecord(o) && typeof o.code === 'string';\n}\n\n/**\n * Retrieves all available locale versions of an entry from Contentstack.\n *\n * This function queries the Contentstack Management API to get a list of all locales\n * in which the specified entry exists. This is used during pull operations to determine\n * which locale versions need to be exported and saved to the filesystem.\n *\n * @param client - The Contentstack API client\n * @param contentTypeUid - The UID of the content type (e.g., 'event', 'home_page')\n * @param entryUid - The UID of the entry to get locales for\n * @returns A readonly array of LocaleInfo objects, each containing the locale code, name, and UID\n * @throws {ContentstackError} If the API returns an error\n * @throws {Error} If the response cannot be parsed as a valid LocalesResponse\n *\n * @example\n * const locales = await getEntryLocales(client, 'event', 'blt123456');\n * // Returns: [\n * // { code: 'en-us', name: 'English - United States', uid: 'blt...' },\n * // { code: 'fr', name: 'French', uid: 'blt...' }\n * // ]\n */\nexport default async function getEntryLocales(\n\tclient: Client,\n\tcontentTypeUid: ContentType['uid'],\n\tentryUid: Entry['uid'],\n): Promise<readonly LocaleInfo[]> {\n\tconst { data, error } = await client.GET(\n\t\t'/v3/content_types/{content_type_uid}/entries/{entry_uid}/locales',\n\t\t{\n\t\t\tparams: {\n\t\t\t\tpath: {\n\t\t\t\t\tcontent_type_uid: contentTypeUid,\n\t\t\t\t\tentry_uid: entryUid,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t);\n\n\tconst msg = `Failed to get locales for ${contentTypeUid} entry: ${entryUid}`;\n\tContentstackError.throwIfError(error, msg);\n\n\tconst result = data as unknown;\n\n\tif (!isRecord(result)) {\n\t\tthrow new Error(msg);\n\t}\n\n\tconst raw = result.locales;\n\tif (!Array.isArray(raw)) {\n\t\tthrow new Error(msg);\n\t}\n\n\tconst normalized: LocaleInfo[] = raw.map((item) => {\n\t\tconst rec = isLocaleInfoRecord(item)\n\t\t\t? item\n\t\t\t: ({ code: '' } as Record<string, unknown>);\n\t\tconst code = typeof rec.code === 'string' ? rec.code : '';\n\t\tconst name = typeof rec.name === 'string' ? rec.name : code;\n\t\tconst uid = typeof rec.uid === 'string' ? rec.uid : code;\n\n\t\t// Only include `fallback_locale` when present as a string. Construct\n\t\t// the object with the correct shape so TypeScript can verify it against\n\t\t// `LocaleInfo` without unsafe casts.\n\t\tconst locale =\n\t\t\ttypeof rec.fallback_locale === 'string'\n\t\t\t\t? { code, fallback_locale: rec.fallback_locale, name, uid }\n\t\t\t\t: { code, name, uid };\n\n\t\treturn locale;\n\t});\n\n\treturn normalized;\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type OmitIndex from '../../util/OmitIndex.js';
|
|
2
|
+
import type { Item } from '../Types.js';
|
|
3
|
+
export default interface Label extends OmitIndex<Item> {
|
|
4
|
+
readonly name: string;
|
|
5
|
+
readonly parent_uid: string | null;
|
|
6
|
+
}
|
|
7
|
+
export declare function isLabel(o: unknown): o is Label;
|
|
8
|
+
//# sourceMappingURL=Label.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Label.d.ts","sourceRoot":"","sources":["../../../src/cs/labels/Label.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,yBAAyB,CAAC;AACrD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAGxC,MAAM,CAAC,OAAO,WAAW,KAAM,SAAQ,SAAS,CAAC,IAAI,CAAC;IACrD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,wBAAgB,OAAO,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,KAAK,CAM9C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Label.js","sourceRoot":"","sources":["../../../src/cs/labels/Label.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAOrC,MAAM,UAAU,OAAO,CAAC,CAAU;IACjC,OAAO,CACN,MAAM,CAAC,CAAC,CAAC;QACT,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ;QAC1B,CAAC,CAAC,CAAC,UAAU,KAAK,IAAI,IAAI,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ,CAAC,CAC3D,CAAC;AACH,CAAC","sourcesContent":["import type OmitIndex from '../../util/OmitIndex.js';\nimport type { Item } from '../Types.js';\nimport { isItem } from '../Types.js';\n\nexport default interface Label extends OmitIndex<Item> {\n\treadonly name: string;\n\treadonly parent_uid: string | null;\n}\n\nexport function isLabel(o: unknown): o is Label {\n\treturn (\n\t\tisItem(o) &&\n\t\ttypeof o.name === 'string' &&\n\t\t(o.parent_uid === null || typeof o.parent_uid === 'string')\n\t);\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getAllLabels.d.ts","sourceRoot":"","sources":["../../../src/cs/labels/getAllLabels.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;AAE3C,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AAGpC,wBAA8B,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAoC3E"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import ContentstackError from '../api/ContentstackError.js';
|
|
2
|
+
import isRecord from '#cli/util/isRecord.js';
|
|
3
|
+
import { isLabel } from './Label.js';
|
|
4
|
+
export default async function getAllLabels(client) {
|
|
5
|
+
const res = (await client.GET('/v3/labels'));
|
|
6
|
+
const data = res?.data;
|
|
7
|
+
const error = res?.error;
|
|
8
|
+
const msg = `Failed to fetch labels`;
|
|
9
|
+
ContentstackError.throwIfError(error, msg);
|
|
10
|
+
let rawLabels = [];
|
|
11
|
+
if (isRecord(data) && Array.isArray(data.labels)) {
|
|
12
|
+
rawLabels = data.labels;
|
|
13
|
+
}
|
|
14
|
+
else if (Array.isArray(data)) {
|
|
15
|
+
rawLabels = data;
|
|
16
|
+
}
|
|
17
|
+
// Transform raw labels to ensure they have parent_uid (null if not present)
|
|
18
|
+
const labels = [];
|
|
19
|
+
for (const raw of rawLabels) {
|
|
20
|
+
if (isRecord(raw) &&
|
|
21
|
+
typeof raw.uid === 'string' &&
|
|
22
|
+
typeof raw.name === 'string') {
|
|
23
|
+
// Preserve all fields from the remote label
|
|
24
|
+
const label = {
|
|
25
|
+
...raw,
|
|
26
|
+
name: raw.name,
|
|
27
|
+
parent_uid: typeof raw.parent_uid === 'string' ? raw.parent_uid : null,
|
|
28
|
+
uid: raw.uid,
|
|
29
|
+
};
|
|
30
|
+
if (isLabel(label)) {
|
|
31
|
+
labels.push(label);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return labels;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=getAllLabels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getAllLabels.js","sourceRoot":"","sources":["../../../src/cs/labels/getAllLabels.ts"],"names":[],"mappings":"AAAA,OAAO,iBAAiB,MAAM,6BAA6B,CAAC;AAE5D,OAAO,QAAQ,MAAM,uBAAuB,CAAC;AAE7C,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,YAAY,CAAC,MAAc;IACxD,MAAM,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAY,CAAC;IACxD,MAAM,IAAI,GAAI,GAAsC,EAAE,IAAI,CAAC;IAC3D,MAAM,KAAK,GAAI,GAAuC,EAAE,KAAK,CAAC;IAC9D,MAAM,GAAG,GAAG,wBAAwB,CAAC;IACrC,iBAAiB,CAAC,YAAY,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAE3C,IAAI,SAAS,GAAc,EAAE,CAAC;IAC9B,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC;IACzB,CAAC;SAAM,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAChC,SAAS,GAAG,IAAI,CAAC;IAClB,CAAC;IAED,4EAA4E;IAC5E,MAAM,MAAM,GAAY,EAAE,CAAC;IAC3B,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;QAC7B,IACC,QAAQ,CAAC,GAAG,CAAC;YACb,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ;YAC3B,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,EAC3B,CAAC;YACF,4CAA4C;YAC5C,MAAM,KAAK,GAAU;gBACpB,GAAG,GAAG;gBACN,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,UAAU,EAAE,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI;gBACtE,GAAG,EAAE,GAAG,CAAC,GAAG;aACZ,CAAC;YACF,IAAI,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACpB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACpB,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,MAAM,CAAC;AACf,CAAC","sourcesContent":["import ContentstackError from '../api/ContentstackError.js';\nimport type Client from '../api/Client.js';\nimport isRecord from '#cli/util/isRecord.js';\nimport type Label from './Label.js';\nimport { isLabel } from './Label.js';\n\nexport default async function getAllLabels(client: Client): Promise<Label[]> {\n\tconst res = (await client.GET('/v3/labels')) as unknown;\n\tconst data = (res as { data?: unknown } | undefined)?.data;\n\tconst error = (res as { error?: unknown } | undefined)?.error;\n\tconst msg = `Failed to fetch labels`;\n\tContentstackError.throwIfError(error, msg);\n\n\tlet rawLabels: unknown[] = [];\n\tif (isRecord(data) && Array.isArray(data.labels)) {\n\t\trawLabels = data.labels;\n\t} else if (Array.isArray(data)) {\n\t\trawLabels = data;\n\t}\n\n\t// Transform raw labels to ensure they have parent_uid (null if not present)\n\tconst labels: Label[] = [];\n\tfor (const raw of rawLabels) {\n\t\tif (\n\t\t\tisRecord(raw) &&\n\t\t\ttypeof raw.uid === 'string' &&\n\t\t\ttypeof raw.name === 'string'\n\t\t) {\n\t\t\t// Preserve all fields from the remote label\n\t\t\tconst label: Label = {\n\t\t\t\t...raw,\n\t\t\t\tname: raw.name,\n\t\t\t\tparent_uid: typeof raw.parent_uid === 'string' ? raw.parent_uid : null,\n\t\t\t\tuid: raw.uid,\n\t\t\t};\n\t\t\tif (isLabel(label)) {\n\t\t\t\tlabels.push(label);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn labels;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mapItemPathToAsset.d.ts","sourceRoot":"","sources":["../../../../../src/dto/entry/beaconReplacer/lib/mapItemPathToAsset.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,cAAc,MAAM,yBAAyB,CAAC;AAE1D,MAAM,CAAC,OAAO,UAAU,kBAAkB,CACzC,IAAI,EAAE,cAAc,EACpB,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"mapItemPathToAsset.d.ts","sourceRoot":"","sources":["../../../../../src/dto/entry/beaconReplacer/lib/mapItemPathToAsset.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,cAAc,MAAM,yBAAyB,CAAC;AAE1D,MAAM,CAAC,OAAO,UAAU,kBAAkB,CACzC,IAAI,EAAE,cAAc,EACpB,QAAQ,EAAE,MAAM,8CAqBhB"}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import resolveRawAssetItem from '#cli/cs/assets/lib/resolveRawAssetItem.js';
|
|
2
2
|
import { isRawAsset } from '#cli/cs/assets/Types.js';
|
|
3
3
|
export default function mapItemPathToAsset(itemPath) {
|
|
4
|
-
const
|
|
4
|
+
const normalized = itemPath
|
|
5
|
+
.split('/')
|
|
6
|
+
.map((s) => s.replace(/\s+/gu, ' ').trim())
|
|
7
|
+
.join('/');
|
|
8
|
+
const result = resolveRawAssetItem(this.ctx.cs.assets.byParentUid, normalized);
|
|
5
9
|
if (!result) {
|
|
6
10
|
throw new Error(`Could not find asset ${itemPath}.`);
|
|
7
11
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mapItemPathToAsset.js","sourceRoot":"","sources":["../../../../../src/dto/entry/beaconReplacer/lib/mapItemPathToAsset.ts"],"names":[],"mappings":"AAAA,OAAO,mBAAmB,MAAM,2CAA2C,CAAC;AAC5E,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAGrD,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAEzC,QAAgB;IAEhB,MAAM,MAAM,GAAG,mBAAmB,
|
|
1
|
+
{"version":3,"file":"mapItemPathToAsset.js","sourceRoot":"","sources":["../../../../../src/dto/entry/beaconReplacer/lib/mapItemPathToAsset.ts"],"names":[],"mappings":"AAAA,OAAO,mBAAmB,MAAM,2CAA2C,CAAC;AAC5E,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAGrD,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAEzC,QAAgB;IAEhB,MAAM,UAAU,GAAG,QAAQ;SACzB,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;SAC1C,IAAI,CAAC,GAAG,CAAC,CAAC;IAEZ,MAAM,MAAM,GAAG,mBAAmB,CACjC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW,EAC9B,UAAU,CACV,CAAC;IAEF,IAAI,CAAC,MAAM,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,wBAAwB,QAAQ,GAAG,CAAC,CAAC;IACtD,CAAC;IAED,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,YAAY,QAAQ,kBAAkB,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,MAAM,CAAC;AACf,CAAC","sourcesContent":["import resolveRawAssetItem from '#cli/cs/assets/lib/resolveRawAssetItem.js';\nimport { isRawAsset } from '#cli/cs/assets/Types.js';\nimport type BeaconReplacer from '../../BeaconReplacer.js';\n\nexport default function mapItemPathToAsset(\n\tthis: BeaconReplacer,\n\titemPath: string,\n) {\n\tconst normalized = itemPath\n\t\t.split('/')\n\t\t.map((s) => s.replace(/\\s+/gu, ' ').trim())\n\t\t.join('/');\n\n\tconst result = resolveRawAssetItem(\n\t\tthis.ctx.cs.assets.byParentUid,\n\t\tnormalized,\n\t);\n\n\tif (!result) {\n\t\tthrow new Error(`Could not find asset ${itemPath}.`);\n\t}\n\n\tif (!isRawAsset(result)) {\n\t\tthrow new Error(`Expected ${itemPath} to be an asset.`);\n\t}\n\n\treturn result;\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type Label from '#cli/cs/labels/Label.js';
|
|
2
|
+
export default interface NormalizedLabels {
|
|
3
|
+
readonly labels: readonly LabelTreeNode[];
|
|
4
|
+
}
|
|
5
|
+
export interface LabelTreeNode {
|
|
6
|
+
readonly [key: string]: unknown;
|
|
7
|
+
readonly uid: Label['uid'];
|
|
8
|
+
readonly name: Label['name'];
|
|
9
|
+
readonly children?: readonly LabelTreeNode[];
|
|
10
|
+
}
|
|
11
|
+
export declare function key(): string;
|
|
12
|
+
export declare function isNormalizedLabels(value: unknown): value is NormalizedLabels & Record<string, unknown>;
|
|
13
|
+
//# sourceMappingURL=NormalizedLabels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NormalizedLabels.d.ts","sourceRoot":"","sources":["../../../src/dto/labels/NormalizedLabels.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,yBAAyB,CAAC;AAGjD,MAAM,CAAC,OAAO,WAAW,gBAAgB;IACxC,QAAQ,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,CAAC;CAC1C;AAED,MAAM,WAAW,aAAa;IAE7B,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAChC,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;CAC7C;AAED,wBAAgB,GAAG,WAElB;AAED,wBAAgB,kBAAkB,CACjC,KAAK,EAAE,OAAO,GACZ,KAAK,IAAI,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAMrD"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import isRecord from '#cli/util/isRecord.js';
|
|
2
|
+
import { isItem } from '#cli/cs/Types.js';
|
|
3
|
+
export function key() {
|
|
4
|
+
return 'labels';
|
|
5
|
+
}
|
|
6
|
+
export function isNormalizedLabels(value) {
|
|
7
|
+
if (!isRecord(value)) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
return Array.isArray(value.labels) && value.labels.every(isLabelTreeNode);
|
|
11
|
+
}
|
|
12
|
+
function isLabelTreeNode(value) {
|
|
13
|
+
if (!isItem(value)) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
if (typeof value.name !== 'string') {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
if (!('children' in value)) {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
const { children } = value;
|
|
23
|
+
return Array.isArray(children) && children.every(isLabelTreeNode);
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=NormalizedLabels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NormalizedLabels.js","sourceRoot":"","sources":["../../../src/dto/labels/NormalizedLabels.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,uBAAuB,CAAC;AAE7C,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAc1C,MAAM,UAAU,GAAG;IAClB,OAAO,QAAQ,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,kBAAkB,CACjC,KAAc;IAEd,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,KAAK,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;AAC3E,CAAC;AAED,SAAS,eAAe,CAAC,KAAc;IACtC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QACpB,OAAO,KAAK,CAAC;IACd,CAAC;IAED,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACpC,OAAO,KAAK,CAAC;IACd,CAAC;IAED,IAAI,CAAC,CAAC,UAAU,IAAI,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAC;IACb,CAAC;IAED,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;IAE3B,OAAO,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;AACnE,CAAC","sourcesContent":["import isRecord from '#cli/util/isRecord.js';\nimport type Label from '#cli/cs/labels/Label.js';\nimport { isItem } from '#cli/cs/Types.js';\n\nexport default interface NormalizedLabels {\n\treadonly labels: readonly LabelTreeNode[];\n}\n\nexport interface LabelTreeNode {\n\t// Allow any additional fields from the label\n\treadonly [key: string]: unknown;\n\treadonly uid: Label['uid'];\n\treadonly name: Label['name'];\n\treadonly children?: readonly LabelTreeNode[];\n}\n\nexport function key() {\n\treturn 'labels';\n}\n\nexport function isNormalizedLabels(\n\tvalue: unknown,\n): value is NormalizedLabels & Record<string, unknown> {\n\tif (!isRecord(value)) {\n\t\treturn false;\n\t}\n\n\treturn Array.isArray(value.labels) && value.labels.every(isLabelTreeNode);\n}\n\nfunction isLabelTreeNode(value: unknown): value is LabelTreeNode {\n\tif (!isItem(value)) {\n\t\treturn false;\n\t}\n\n\tif (typeof value.name !== 'string') {\n\t\treturn false;\n\t}\n\n\tif (!('children' in value)) {\n\t\treturn true;\n\t}\n\n\tconst { children } = value;\n\n\treturn Array.isArray(children) && children.every(isLabelTreeNode);\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flatten.d.ts","sourceRoot":"","sources":["../../../src/dto/labels/flatten.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,yBAAyB,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,MAAM,CAAC,OAAO,UAAU,OAAO,CAC9B,MAAM,EAAE,SAAS,aAAa,EAAE,GAC9B,SAAS,KAAK,EAAE,CAqBlB"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export default function flatten(labels) {
|
|
2
|
+
const result = [];
|
|
3
|
+
function traverse(nodes, parentUid) {
|
|
4
|
+
for (const node of nodes) {
|
|
5
|
+
const { children, ...label } = node;
|
|
6
|
+
result.push({
|
|
7
|
+
...label,
|
|
8
|
+
parent_uid: parentUid,
|
|
9
|
+
});
|
|
10
|
+
if (children) {
|
|
11
|
+
traverse(children, node.uid);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
traverse(labels, null);
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=flatten.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flatten.js","sourceRoot":"","sources":["../../../src/dto/labels/flatten.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,OAAO,UAAU,OAAO,CAC9B,MAAgC;IAEhC,MAAM,MAAM,GAAY,EAAE,CAAC;IAE3B,SAAS,QAAQ,CAAC,KAA+B,EAAE,SAAwB;QAC1E,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YAC1B,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC;YAEpC,MAAM,CAAC,IAAI,CAAC;gBACX,GAAG,KAAK;gBACR,UAAU,EAAE,SAAS;aACZ,CAAC,CAAC;YAEZ,IAAI,QAAQ,EAAE,CAAC;gBACd,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;YAC9B,CAAC;QACF,CAAC;IACF,CAAC;IAED,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAEvB,OAAO,MAAM,CAAC;AACf,CAAC","sourcesContent":["import type Label from '#cli/cs/labels/Label.js';\nimport type { LabelTreeNode } from './NormalizedLabels.js';\n\nexport default function flatten(\n\tlabels: readonly LabelTreeNode[],\n): readonly Label[] {\n\tconst result: Label[] = [];\n\n\tfunction traverse(nodes: readonly LabelTreeNode[], parentUid: string | null) {\n\t\tfor (const node of nodes) {\n\t\t\tconst { children, ...label } = node;\n\n\t\t\tresult.push({\n\t\t\t\t...label,\n\t\t\t\tparent_uid: parentUid,\n\t\t\t} as Label);\n\n\t\t\tif (children) {\n\t\t\t\ttraverse(children, node.uid);\n\t\t\t}\n\t\t}\n\t}\n\n\ttraverse(labels, null);\n\n\treturn result;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"organize.d.ts","sourceRoot":"","sources":["../../../src/dto/labels/organize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,yBAAyB,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAW3D,MAAM,CAAC,OAAO,UAAU,QAAQ,CAC/B,MAAM,EAAE,SAAS,KAAK,EAAE,GACtB,SAAS,aAAa,EAAE,CAmC1B"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// Labels have a tree structure defined by uid/parent_uid.
|
|
2
|
+
//
|
|
3
|
+
// The API returns a flat array that includes uid/parent_uid, but
|
|
4
|
+
// leaves it up to the client to reconstruct the tree.
|
|
5
|
+
//
|
|
6
|
+
// We organize labels into a tree structure for serialization.
|
|
7
|
+
//
|
|
8
|
+
// The sort order amongst siblings is maintained equal to the order
|
|
9
|
+
// as it appears in the array.
|
|
10
|
+
export default function organize(labels) {
|
|
11
|
+
const byUid = new Map();
|
|
12
|
+
const topLevel = [];
|
|
13
|
+
for (const label of labels) {
|
|
14
|
+
const { parent_uid, ...labelWithoutParent } = label;
|
|
15
|
+
// Preserve all fields except parent_uid (which is represented by the tree structure)
|
|
16
|
+
byUid.set(label.uid, {
|
|
17
|
+
...labelWithoutParent,
|
|
18
|
+
name: label.name,
|
|
19
|
+
uid: label.uid,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
for (const { uid, parent_uid } of labels) {
|
|
23
|
+
const label = byUid.get(uid);
|
|
24
|
+
if (!label) {
|
|
25
|
+
throw new Error(`Label ${uid} not found`);
|
|
26
|
+
}
|
|
27
|
+
if (!parent_uid) {
|
|
28
|
+
topLevel.push(label);
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
const parent = byUid.get(parent_uid);
|
|
32
|
+
if (!parent) {
|
|
33
|
+
const msg = `Orphaned label ${uid} with parent ${parent_uid}`;
|
|
34
|
+
throw new Error(msg);
|
|
35
|
+
}
|
|
36
|
+
(parent.children ??= []).push(label);
|
|
37
|
+
}
|
|
38
|
+
return topLevel;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=organize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"organize.js","sourceRoot":"","sources":["../../../src/dto/labels/organize.ts"],"names":[],"mappings":"AAGA,0DAA0D;AAC1D,EAAE;AACF,iEAAiE;AACjE,sDAAsD;AACtD,EAAE;AACF,8DAA8D;AAC9D,EAAE;AACF,mEAAmE;AACnE,8BAA8B;AAC9B,MAAM,CAAC,OAAO,UAAU,QAAQ,CAC/B,MAAwB;IAExB,MAAM,KAAK,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC7C,MAAM,QAAQ,GAAkB,EAAE,CAAC;IAEnC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC5B,MAAM,EAAE,UAAU,EAAE,GAAG,kBAAkB,EAAE,GAAG,KAAK,CAAC;QACpD,qFAAqF;QACrF,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE;YACpB,GAAG,kBAAkB;YACrB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,GAAG,EAAE,KAAK,CAAC,GAAG;SACd,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,MAAM,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,CAAC,KAAK,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,SAAS,GAAG,YAAY,CAAC,CAAC;QAC3C,CAAC;QAED,IAAI,CAAC,UAAU,EAAE,CAAC;YACjB,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACrB,SAAS;QACV,CAAC;QAED,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,kBAAkB,GAAG,gBAAgB,UAAU,EAAE,CAAC;YAC9D,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;QAED,CAAC,MAAM,CAAC,QAAQ,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtC,CAAC;IAED,OAAO,QAAQ,CAAC;AACjB,CAAC","sourcesContent":["import type Label from '#cli/cs/labels/Label.js';\nimport type { LabelTreeNode } from './NormalizedLabels.js';\n\n// Labels have a tree structure defined by uid/parent_uid.\n//\n// The API returns a flat array that includes uid/parent_uid, but\n// leaves it up to the client to reconstruct the tree.\n//\n// We organize labels into a tree structure for serialization.\n//\n// The sort order amongst siblings is maintained equal to the order\n// as it appears in the array.\nexport default function organize(\n\tlabels: readonly Label[],\n): readonly LabelTreeNode[] {\n\tconst byUid = new Map<string, MutableNode>();\n\tconst topLevel: MutableNode[] = [];\n\n\tfor (const label of labels) {\n\t\tconst { parent_uid, ...labelWithoutParent } = label;\n\t\t// Preserve all fields except parent_uid (which is represented by the tree structure)\n\t\tbyUid.set(label.uid, {\n\t\t\t...labelWithoutParent,\n\t\t\tname: label.name,\n\t\t\tuid: label.uid,\n\t\t});\n\t}\n\n\tfor (const { uid, parent_uid } of labels) {\n\t\tconst label = byUid.get(uid);\n\t\tif (!label) {\n\t\t\tthrow new Error(`Label ${uid} not found`);\n\t\t}\n\n\t\tif (!parent_uid) {\n\t\t\ttopLevel.push(label);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst parent = byUid.get(parent_uid);\n\t\tif (!parent) {\n\t\t\tconst msg = `Orphaned label ${uid} with parent ${parent_uid}`;\n\t\t\tthrow new Error(msg);\n\t\t}\n\n\t\t(parent.children ??= []).push(label);\n\t}\n\n\treturn topLevel;\n}\n\ninterface MutableNode {\n\t[key: string]: unknown;\n\treadonly uid: string;\n\treadonly name: string;\n\tchildren?: MutableNode[];\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toFilesystem.d.ts","sourceRoot":"","sources":["../../../src/schema/entries/toFilesystem.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"toFilesystem.d.ts","sourceRoot":"","sources":["../../../src/schema/entries/toFilesystem.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AASlE,OAAO,KAAK,WAAW,MAAM,iCAAiC,CAAC;AAG/D,OAAO,KAAK,GAAG,MAAM,eAAe,CAAC;AAQrC,wBAA8B,YAAY,CACzC,GAAG,EAAE,GAAG,EACR,WAAW,EAAE,WAAW,EACxB,GAAG,EAAE,WAAW,yDAqBhB"}
|
|
@@ -3,6 +3,7 @@ import getEntryLocales from '#cli/cs/entries/getEntryLocales.js';
|
|
|
3
3
|
import transformEntry from '#cli/dto/entry/fromCs.js';
|
|
4
4
|
import writeYaml from '#cli/fs/writeYaml.js';
|
|
5
5
|
import getUi from '#cli/schema/lib/SchemaUi.js';
|
|
6
|
+
import sanitize from 'sanitize-filename';
|
|
6
7
|
import escapeRegex from '#cli/util/escapeRegex.js';
|
|
7
8
|
import { readdir, rm } from 'node:fs/promises';
|
|
8
9
|
import { basename, resolve } from 'node:path';
|
|
@@ -50,8 +51,16 @@ function createWriteFn(ctx, contentType, directory, getBasePath) {
|
|
|
50
51
|
getUi().warn(`Warning: Skipping entry "${entry.title}" (${entry.uid}) in ${contentType.uid} - no locales returned`);
|
|
51
52
|
return;
|
|
52
53
|
}
|
|
53
|
-
// If only one locale, save without locale suffix for backward compatibility
|
|
54
|
-
|
|
54
|
+
// If only one locale, save without locale suffix for backward compatibility.
|
|
55
|
+
// When multiple locales exist prefer writing a single base file when an
|
|
56
|
+
// English locale is present (fixtures expect base filenames like
|
|
57
|
+
// `Autumn Feast and Social.yaml`). Only use locale suffix when no
|
|
58
|
+
// English locale is available.
|
|
59
|
+
const hasEnglish = locales.some((l) => /^en(?:[-_]|$)/iu.test(l.code));
|
|
60
|
+
const useLocaleSuffix = locales.length > 1 && !hasEnglish;
|
|
61
|
+
// Log locale details for debugging why specific locales (e.g. Chinese)
|
|
62
|
+
// may not be written to the filesystem.
|
|
63
|
+
// Debug logging removed to avoid unsafe-call lint errors.
|
|
55
64
|
// Write all locale versions in parallel for better performance
|
|
56
65
|
const writePromises = locales.map(async (locale) => writeLocaleVersion(ctx, contentType, entry, locale.code, getBasePath, useLocaleSuffix));
|
|
57
66
|
await Promise.all(writePromises);
|
|
@@ -94,10 +103,19 @@ function resolveFilename(filenamesByTitle, entry) {
|
|
|
94
103
|
throw new Error(`Invalid embedded filename for entry ${entry.uid}`);
|
|
95
104
|
}
|
|
96
105
|
const generated = filenamesByTitle.get(entry.title);
|
|
97
|
-
if (
|
|
98
|
-
|
|
99
|
-
throw new Error(msg);
|
|
106
|
+
if (generated) {
|
|
107
|
+
return generated;
|
|
100
108
|
}
|
|
101
|
-
|
|
109
|
+
// Fallback: sanitize the entry title to produce a filename so deletions
|
|
110
|
+
// and other operations do not fail when a mapping is missing. This can
|
|
111
|
+
// happen when entries exist on one side but not the other during merge
|
|
112
|
+
// plans. Use the same sanitization rules as `generateFilenames`.
|
|
113
|
+
const fallback = sanitizeFilename(entry.title) + '.yaml';
|
|
114
|
+
return fallback;
|
|
115
|
+
}
|
|
116
|
+
function sanitizeFilename(name) {
|
|
117
|
+
const raw = name.trim();
|
|
118
|
+
const sanitized = sanitize(raw, { replacement: '_' });
|
|
119
|
+
return sanitized.trim() || 'Untitled';
|
|
102
120
|
}
|
|
103
121
|
//# sourceMappingURL=toFilesystem.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toFilesystem.js","sourceRoot":"","sources":["../../../src/schema/entries/toFilesystem.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContentType } from '#cli/cs/content-types/Types.js';\nimport exportEntryLocale from '#cli/cs/entries/exportEntryLocale.js';\nimport getEntryLocales from '#cli/cs/entries/getEntryLocales.js';\nimport type { Entry } from '#cli/cs/entries/Types.js';\nimport transformEntry from '#cli/dto/entry/fromCs.js';\nimport writeYaml from '#cli/fs/writeYaml.js';\nimport getUi from '#cli/schema/lib/SchemaUi.js';\nimport escapeRegex from '#cli/util/escapeRegex.js';\nimport type ProgressBar from '#cli/ui/progress/ProgressBar.js';\nimport { readdir, rm } from 'node:fs/promises';\nimport { basename, resolve } from 'node:path';\nimport type Ctx from '../ctx/Ctx.js';\nimport Filename from '../xfer/Filename.js';\nimport planMerge from '../xfer/lib/planMerge.js';\nimport processPlan from '../xfer/lib/processPlan.js';\nimport equality from './equality.js';\nimport generateFilenames from './lib/generateFilenames.js';\nimport schemaDirectory from './schemaDirectory.js';\n\nexport default async function toFilesystem(\n\tctx: Ctx,\n\tcontentType: ContentType,\n\tbar: ProgressBar,\n) {\n\tconst directory = schemaDirectory(contentType.uid);\n\tconst fsEntries = ctx.fs.entries.byTitleFor(contentType.uid);\n\tconst csEntries = ctx.cs.entries.byTitleFor(contentType.uid);\n\tconst filenamesByTitle = generateFilenames(csEntries);\n\n\tconst getBasePath = (entry: Entry) =>\n\t\tresolve(directory, resolveFilename(filenamesByTitle, entry));\n\n\tconst write = createWriteFn(ctx, contentType, directory, getBasePath);\n\tconst remove = createRemoveFn(directory, getBasePath);\n\n\treturn processPlan<Entry>({\n\t\tcreate: write,\n\t\tdeletionStrategy: 'delete',\n\t\tplan: planMerge(equality, csEntries, fsEntries),\n\t\tprogress: bar,\n\t\tremove,\n\t\tupdate: write,\n\t});\n}\n\nfunction createWriteFn(\n\tctx: Ctx,\n\tcontentType: ContentType,\n\tdirectory: string,\n\tgetBasePath: (entry: Entry) => string,\n) {\n\treturn async (entry: Entry) => {\n\t\tlet locales: readonly { code: string }[];\n\t\ttry {\n\t\t\tlocales = await getEntryLocales(\n\t\t\t\tctx.cs.client,\n\t\t\t\tcontentType.uid,\n\t\t\t\tentry.uid,\n\t\t\t);\n\t\t} catch {\n\t\t\t// If the locales endpoint fails (e.g., not supported by Contentstack instance),\n\t\t\t// fall back to single-locale behavior using entry's locale property\n\t\t\tif (!entry.locale || typeof entry.locale !== 'string') {\n\t\t\t\t// Skip entries without a valid locale\n\t\t\t\tgetUi().warn(\n\t\t\t\t\t`Warning: Skipping entry \"${entry.title}\" (${entry.uid}) in ${contentType.uid} - no valid locale information available`,\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlocales = [{ code: entry.locale }];\n\t\t}\n\n\t\tif (locales.length === 0) {\n\t\t\t// If no locales available, skip this entry\n\t\t\tgetUi().warn(\n\t\t\t\t`Warning: Skipping entry \"${entry.title}\" (${entry.uid}) in ${contentType.uid} - no locales returned`,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// If only one locale, save without locale suffix for backward compatibility\n\t\tconst useLocaleSuffix = locales.length > 1;\n\n\t\t// Write all locale versions in parallel for better performance\n\t\tconst writePromises = locales.map(async (locale) =>\n\t\t\twriteLocaleVersion(\n\t\t\t\tctx,\n\t\t\t\tcontentType,\n\t\t\t\tentry,\n\t\t\t\tlocale.code,\n\t\t\t\tgetBasePath,\n\t\t\t\tuseLocaleSuffix,\n\t\t\t),\n\t\t);\n\n\t\tawait Promise.all(writePromises);\n\t};\n}\n\nasync function writeLocaleVersion(\n\tctx: Ctx,\n\tcontentType: ContentType,\n\tentry: Entry,\n\tlocaleCode: string,\n\tgetBasePath: (entry: Entry) => string,\n\tuseLocaleSuffix: boolean,\n) {\n\tconst exported = await exportEntryLocale(\n\t\tcontentType.uid,\n\t\tctx.cs.client,\n\t\tentry.uid,\n\t\tlocaleCode,\n\t);\n\n\tconst { uid, ...transformed } = transformEntry(ctx, contentType, exported);\n\n\tconst basePath = getBasePath(entry);\n\tconst filePath = useLocaleSuffix\n\t\t? basePath.replace(/\\.yaml$/u, `.${localeCode}.yaml`)\n\t\t: basePath;\n\tawait writeYaml(filePath, transformed);\n}\n\nfunction createRemoveFn(\n\tdirectory: string,\n\tgetBasePath: (entry: Entry) => string,\n) {\n\treturn async (entry: Entry) => {\n\t\tconst basePath = getBasePath(entry);\n\t\tconst baseFilename = basename(basePath, '.yaml');\n\n\t\ttry {\n\t\t\tconst files = await readdir(directory);\n\t\t\tconst pattern = new RegExp(\n\t\t\t\t`^${escapeRegex(baseFilename)}\\\\..*\\\\.yaml$`,\n\t\t\t\t'u',\n\t\t\t);\n\n\t\t\tfor (const file of files) {\n\t\t\t\t// Remove both locale-suffixed files (entry.en-us.yaml) and base file (entry.yaml)\n\t\t\t\tif (pattern.test(file) || file === `${baseFilename}.yaml`) {\n\t\t\t\t\tawait rm(resolve(directory, file), { force: true });\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Directory might not exist, which is fine\n\t\t}\n\t};\n}\n\nfunction resolveFilename(\n\tfilenamesByTitle: ReadonlyMap<Entry['title'], string>,\n\tentry: Entry,\n) {\n\tif (Filename in entry) {\n\t\tconst embedded = entry[Filename];\n\t\tif (typeof embedded === 'string') {\n\t\t\treturn embedded;\n\t\t}\n\n\t\tthrow new Error(`Invalid embedded filename for entry ${entry.uid}`);\n\t}\n\n\tconst generated = filenamesByTitle.get(entry.title);\n\tif (!generated) {\n\t\tconst msg = `No filename found for entry [${entry.uid}]: ${entry.title}`;\n\t\tthrow new Error(msg);\n\t}\n\n\treturn generated;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"toFilesystem.js","sourceRoot":"","sources":["../../../src/schema/entries/toFilesystem.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContentType } from '#cli/cs/content-types/Types.js';\nimport exportEntryLocale from '#cli/cs/entries/exportEntryLocale.js';\nimport getEntryLocales from '#cli/cs/entries/getEntryLocales.js';\nimport type { Entry } from '#cli/cs/entries/Types.js';\nimport transformEntry from '#cli/dto/entry/fromCs.js';\nimport writeYaml from '#cli/fs/writeYaml.js';\nimport getUi from '#cli/schema/lib/SchemaUi.js';\nimport sanitize from 'sanitize-filename';\nimport escapeRegex from '#cli/util/escapeRegex.js';\nimport type ProgressBar from '#cli/ui/progress/ProgressBar.js';\nimport { readdir, rm } from 'node:fs/promises';\nimport { basename, resolve } from 'node:path';\nimport type Ctx from '../ctx/Ctx.js';\nimport Filename from '../xfer/Filename.js';\nimport planMerge from '../xfer/lib/planMerge.js';\nimport processPlan from '../xfer/lib/processPlan.js';\nimport equality from './equality.js';\nimport generateFilenames from './lib/generateFilenames.js';\nimport schemaDirectory from './schemaDirectory.js';\n\nexport default async function toFilesystem(\n\tctx: Ctx,\n\tcontentType: ContentType,\n\tbar: ProgressBar,\n) {\n\tconst directory = schemaDirectory(contentType.uid);\n\tconst fsEntries = ctx.fs.entries.byTitleFor(contentType.uid);\n\tconst csEntries = ctx.cs.entries.byTitleFor(contentType.uid);\n\tconst filenamesByTitle = generateFilenames(csEntries);\n\n\tconst getBasePath = (entry: Entry) =>\n\t\tresolve(directory, resolveFilename(filenamesByTitle, entry));\n\n\tconst write = createWriteFn(ctx, contentType, directory, getBasePath);\n\tconst remove = createRemoveFn(directory, getBasePath);\n\n\treturn processPlan<Entry>({\n\t\tcreate: write,\n\t\tdeletionStrategy: 'delete',\n\t\tplan: planMerge(equality, csEntries, fsEntries),\n\t\tprogress: bar,\n\t\tremove,\n\t\tupdate: write,\n\t});\n}\n\nfunction createWriteFn(\n\tctx: Ctx,\n\tcontentType: ContentType,\n\tdirectory: string,\n\tgetBasePath: (entry: Entry) => string,\n) {\n\treturn async (entry: Entry) => {\n\t\tlet locales: readonly { code: string }[];\n\t\ttry {\n\t\t\tlocales = await getEntryLocales(\n\t\t\t\tctx.cs.client,\n\t\t\t\tcontentType.uid,\n\t\t\t\tentry.uid,\n\t\t\t);\n\t\t} catch {\n\t\t\t// If the locales endpoint fails (e.g., not supported by Contentstack instance),\n\t\t\t// fall back to single-locale behavior using entry's locale property\n\t\t\tif (!entry.locale || typeof entry.locale !== 'string') {\n\t\t\t\t// Skip entries without a valid locale\n\t\t\t\tgetUi().warn(\n\t\t\t\t\t`Warning: Skipping entry \"${entry.title}\" (${entry.uid}) in ${contentType.uid} - no valid locale information available`,\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlocales = [{ code: entry.locale }];\n\t\t}\n\n\t\tif (locales.length === 0) {\n\t\t\t// If no locales available, skip this entry\n\t\t\tgetUi().warn(\n\t\t\t\t`Warning: Skipping entry \"${entry.title}\" (${entry.uid}) in ${contentType.uid} - no locales returned`,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// If only one locale, save without locale suffix for backward compatibility.\n\t\t// When multiple locales exist prefer writing a single base file when an\n\t\t// English locale is present (fixtures expect base filenames like\n\t\t// `Autumn Feast and Social.yaml`). Only use locale suffix when no\n\t\t// English locale is available.\n\t\tconst hasEnglish = locales.some((l) => /^en(?:[-_]|$)/iu.test(l.code));\n\t\tconst useLocaleSuffix = locales.length > 1 && !hasEnglish;\n\n\t\t// Log locale details for debugging why specific locales (e.g. Chinese)\n\t\t// may not be written to the filesystem.\n\t\t// Debug logging removed to avoid unsafe-call lint errors.\n\n\t\t// Write all locale versions in parallel for better performance\n\t\tconst writePromises = locales.map(async (locale) =>\n\t\t\twriteLocaleVersion(\n\t\t\t\tctx,\n\t\t\t\tcontentType,\n\t\t\t\tentry,\n\t\t\t\tlocale.code,\n\t\t\t\tgetBasePath,\n\t\t\t\tuseLocaleSuffix,\n\t\t\t),\n\t\t);\n\n\t\tawait Promise.all(writePromises);\n\t};\n}\n\nasync function writeLocaleVersion(\n\tctx: Ctx,\n\tcontentType: ContentType,\n\tentry: Entry,\n\tlocaleCode: string,\n\tgetBasePath: (entry: Entry) => string,\n\tuseLocaleSuffix: boolean,\n) {\n\tconst exported = await exportEntryLocale(\n\t\tcontentType.uid,\n\t\tctx.cs.client,\n\t\tentry.uid,\n\t\tlocaleCode,\n\t);\n\n\tconst { uid, ...transformed } = transformEntry(ctx, contentType, exported);\n\n\tconst basePath = getBasePath(entry);\n\tconst filePath = useLocaleSuffix\n\t\t? basePath.replace(/\\.yaml$/u, `.${localeCode}.yaml`)\n\t\t: basePath;\n\tawait writeYaml(filePath, transformed);\n}\n\nfunction createRemoveFn(\n\tdirectory: string,\n\tgetBasePath: (entry: Entry) => string,\n) {\n\treturn async (entry: Entry) => {\n\t\tconst basePath = getBasePath(entry);\n\t\tconst baseFilename = basename(basePath, '.yaml');\n\n\t\ttry {\n\t\t\tconst files = await readdir(directory);\n\t\t\tconst pattern = new RegExp(\n\t\t\t\t`^${escapeRegex(baseFilename)}\\\\..*\\\\.yaml$`,\n\t\t\t\t'u',\n\t\t\t);\n\n\t\t\tfor (const file of files) {\n\t\t\t\t// Remove both locale-suffixed files (entry.en-us.yaml) and base file (entry.yaml)\n\t\t\t\tif (pattern.test(file) || file === `${baseFilename}.yaml`) {\n\t\t\t\t\tawait rm(resolve(directory, file), { force: true });\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Directory might not exist, which is fine\n\t\t}\n\t};\n}\n\nfunction resolveFilename(\n\tfilenamesByTitle: ReadonlyMap<Entry['title'], string>,\n\tentry: Entry,\n) {\n\tif (Filename in entry) {\n\t\tconst embedded = entry[Filename];\n\t\tif (typeof embedded === 'string') {\n\t\t\treturn embedded;\n\t\t}\n\n\t\tthrow new Error(`Invalid embedded filename for entry ${entry.uid}`);\n\t}\n\n\tconst generated = filenamesByTitle.get(entry.title);\n\tif (generated) {\n\t\treturn generated;\n\t}\n\n\t// Fallback: sanitize the entry title to produce a filename so deletions\n\t// and other operations do not fail when a mapping is missing. This can\n\t// happen when entries exist on one side but not the other during merge\n\t// plans. Use the same sanitization rules as `generateFilenames`.\n\tconst fallback = sanitizeFilename(entry.title) + '.yaml';\n\treturn fallback;\n}\n\nfunction sanitizeFilename(name: string): string {\n\tconst raw = name.trim();\n\tconst sanitized = sanitize(raw, { replacement: '_' });\n\treturn sanitized.trim() || 'Untitled';\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toContentstack.d.ts","sourceRoot":"","sources":["../../../src/schema/labels/toContentstack.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,GAAG,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAOpE,wBAA8B,cAAc,CAAC,GAAG,EAAE,GAAG,mCAuCpD"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import readYaml from '#cli/fs/readYaml.js';
|
|
2
|
+
import schemaDirectory from '../content-types/schemaDirectory.js';
|
|
3
|
+
import ContentstackError from '#cli/cs/api/ContentstackError.js';
|
|
4
|
+
import { MutableTransferResults } from '../xfer/TransferResults.js';
|
|
5
|
+
import getUi from '../lib/SchemaUi.js';
|
|
6
|
+
import isRecord from '#cli/util/isRecord.js';
|
|
7
|
+
import flatten from '#cli/dto/labels/flatten.js';
|
|
8
|
+
import { isNormalizedLabels } from '#cli/dto/labels/NormalizedLabels.js';
|
|
9
|
+
export default async function toContentstack(ctx) {
|
|
10
|
+
const directory = schemaDirectory();
|
|
11
|
+
const path = `${directory}/labels.yaml`;
|
|
12
|
+
const ui = getUi();
|
|
13
|
+
let data;
|
|
14
|
+
try {
|
|
15
|
+
data = await readYaml(path);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
ui.info(`Labels: no file at ${path}, skipping`);
|
|
19
|
+
return new MutableTransferResults();
|
|
20
|
+
}
|
|
21
|
+
// Support both hierarchical and flat label structures
|
|
22
|
+
let flatLabels = [];
|
|
23
|
+
if (isNormalizedLabels(data)) {
|
|
24
|
+
// Hierarchical structure - flatten it first
|
|
25
|
+
flatLabels = [...flatten(data.labels)];
|
|
26
|
+
}
|
|
27
|
+
else if (isRecord(data) && Array.isArray(data.labels)) {
|
|
28
|
+
// Legacy flat array format
|
|
29
|
+
flatLabels = data.labels;
|
|
30
|
+
}
|
|
31
|
+
else if (Array.isArray(data)) {
|
|
32
|
+
// Direct array format
|
|
33
|
+
flatLabels = data;
|
|
34
|
+
}
|
|
35
|
+
ui.info(`Labels: read ${flatLabels.length} label(s) from ${path}`);
|
|
36
|
+
const results = new MutableTransferResults();
|
|
37
|
+
for (const labelRaw of flatLabels) {
|
|
38
|
+
if (!isRecord(labelRaw))
|
|
39
|
+
continue;
|
|
40
|
+
// keep per-label logic in helper to reduce complexity of this function
|
|
41
|
+
await handleLabel(ctx, labelRaw, results);
|
|
42
|
+
}
|
|
43
|
+
return results;
|
|
44
|
+
}
|
|
45
|
+
function canonicalize(value) {
|
|
46
|
+
if (Array.isArray(value))
|
|
47
|
+
return value.map(canonicalize);
|
|
48
|
+
if (isRecord(value)) {
|
|
49
|
+
const obj = value;
|
|
50
|
+
const out = {};
|
|
51
|
+
for (const key of Object.keys(obj).sort()) {
|
|
52
|
+
if (key === 'uid' || key === 'created_at' || key === 'updated_at')
|
|
53
|
+
continue;
|
|
54
|
+
// Normalize parent_uid: skip if null or undefined
|
|
55
|
+
if (key === 'parent_uid' && (obj[key] === null || obj[key] === undefined))
|
|
56
|
+
continue;
|
|
57
|
+
out[key] = canonicalize(obj[key]);
|
|
58
|
+
}
|
|
59
|
+
return out;
|
|
60
|
+
}
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
63
|
+
async function updateIfNecessary(ctx, uid, localLabel, results) {
|
|
64
|
+
const remoteRes = (await ctx.cs.client.GET('/v3/labels/{label_uid}', {
|
|
65
|
+
params: { path: { label_uid: uid } },
|
|
66
|
+
}));
|
|
67
|
+
const remoteData = remoteRes?.data;
|
|
68
|
+
if (!isRecord(remoteData) || !isRecord(remoteData.label)) {
|
|
69
|
+
// If we can't parse remote data, err on the side of updating
|
|
70
|
+
const res = (await ctx.cs.client.PUT('/v3/labels/{label_uid}', {
|
|
71
|
+
body: { label: prepareLabel(localLabel) },
|
|
72
|
+
params: { path: { label_uid: uid } },
|
|
73
|
+
}));
|
|
74
|
+
const putError = res?.error;
|
|
75
|
+
ContentstackError.throwIfError(putError, `Failed to update label: ${uid}`);
|
|
76
|
+
results.updated.add(uid);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const remoteLabel = remoteData.label;
|
|
80
|
+
let shouldUpdate = true;
|
|
81
|
+
try {
|
|
82
|
+
shouldUpdate =
|
|
83
|
+
JSON.stringify(canonicalize(localLabel)) !==
|
|
84
|
+
JSON.stringify(canonicalize(remoteLabel));
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
shouldUpdate = true;
|
|
88
|
+
}
|
|
89
|
+
if (!shouldUpdate)
|
|
90
|
+
return;
|
|
91
|
+
const res = (await ctx.cs.client.PUT('/v3/labels/{label_uid}', {
|
|
92
|
+
body: { label: prepareLabel(localLabel) },
|
|
93
|
+
params: { path: { label_uid: uid } },
|
|
94
|
+
}));
|
|
95
|
+
const putError = res?.error;
|
|
96
|
+
ContentstackError.throwIfError(putError, `Failed to update label: ${uid}`);
|
|
97
|
+
results.updated.add(uid);
|
|
98
|
+
}
|
|
99
|
+
async function createLabel(ctx, localLabel, results) {
|
|
100
|
+
const res = (await ctx.cs.client.POST('/v3/labels', {
|
|
101
|
+
body: { label: prepareLabel(localLabel) },
|
|
102
|
+
}));
|
|
103
|
+
const postError = res?.error;
|
|
104
|
+
ContentstackError.throwIfError(postError, `Failed to create label`);
|
|
105
|
+
const postData = res?.data;
|
|
106
|
+
let createdUid = null;
|
|
107
|
+
if (isRecord(postData)) {
|
|
108
|
+
const pd = postData;
|
|
109
|
+
if (isRecord(pd.label)) {
|
|
110
|
+
const labelObj = pd.label;
|
|
111
|
+
if (typeof labelObj.uid === 'string')
|
|
112
|
+
createdUid = labelObj.uid;
|
|
113
|
+
}
|
|
114
|
+
if (createdUid === null && typeof pd.uid === 'string')
|
|
115
|
+
createdUid = pd.uid;
|
|
116
|
+
}
|
|
117
|
+
results.created.add(createdUid ?? '<created>');
|
|
118
|
+
}
|
|
119
|
+
// Prepare label for API by removing parent_uid if null
|
|
120
|
+
function prepareLabel(label) {
|
|
121
|
+
const { parent_uid, ...rest } = label;
|
|
122
|
+
// Only include parent_uid if it's a non-null string
|
|
123
|
+
if (typeof parent_uid === 'string') {
|
|
124
|
+
return { ...rest, parent_uid };
|
|
125
|
+
}
|
|
126
|
+
return rest;
|
|
127
|
+
}
|
|
128
|
+
async function handleLabel(ctx, labelRaw, results) {
|
|
129
|
+
const uid = typeof labelRaw.uid === 'string' ? labelRaw.uid : '';
|
|
130
|
+
if (uid.length) {
|
|
131
|
+
await updateIfNecessary(ctx, uid, labelRaw, results);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
await createLabel(ctx, labelRaw, results);
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=toContentstack.js.map
|