@arkebcacy/beacon-cli-temp 0.1.5 → 0.1.7
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/labels/Label.d.ts +8 -0
- package/dist/cs/labels/Label.d.ts.map +1 -0
- package/dist/cs/labels/Label.js +5 -0
- package/dist/cs/labels/Label.js.map +1 -0
- package/dist/cs/labels/getAllLabels.d.ts +2 -1
- package/dist/cs/labels/getAllLabels.d.ts.map +1 -1
- package/dist/cs/labels/getAllLabels.js +24 -4
- package/dist/cs/labels/getAllLabels.js.map +1 -1
- package/dist/cs/locales/addLocale.d.ts +11 -0
- package/dist/cs/locales/addLocale.d.ts.map +1 -0
- package/dist/cs/locales/addLocale.js +36 -0
- package/dist/cs/locales/addLocale.js.map +1 -0
- package/dist/cs/locales/ensureLocaleExists.d.ts +11 -0
- package/dist/cs/locales/ensureLocaleExists.d.ts.map +1 -0
- package/dist/cs/locales/ensureLocaleExists.js +38 -0
- package/dist/cs/locales/ensureLocaleExists.js.map +1 -0
- package/dist/cs/locales/getLocales.d.ts +12 -0
- package/dist/cs/locales/getLocales.d.ts.map +1 -0
- package/dist/cs/locales/getLocales.js +23 -0
- package/dist/cs/locales/getLocales.js.map +1 -0
- 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 +41 -0
- package/dist/dto/labels/organize.js.map +1 -0
- package/dist/schema/entries/toContentstack.d.ts.map +1 -1
- package/dist/schema/entries/toContentstack.js +30 -5
- package/dist/schema/entries/toContentstack.js.map +1 -1
- package/dist/schema/entries/toFilesystem.js +23 -10
- package/dist/schema/entries/toFilesystem.js.map +1 -1
- package/dist/schema/labels/lib/labelHelpers.d.ts +3 -0
- package/dist/schema/labels/lib/labelHelpers.d.ts.map +1 -0
- package/dist/schema/labels/lib/labelHelpers.js +34 -0
- package/dist/schema/labels/lib/labelHelpers.js.map +1 -0
- package/dist/schema/labels/lib/labelOperations.d.ts +6 -0
- package/dist/schema/labels/lib/labelOperations.d.ts.map +1 -0
- package/dist/schema/labels/lib/labelOperations.js +57 -0
- package/dist/schema/labels/lib/labelOperations.js.map +1 -0
- package/dist/schema/labels/toContentstack.d.ts.map +1 -1
- package/dist/schema/labels/toContentstack.js +145 -85
- package/dist/schema/labels/toContentstack.js.map +1 -1
- package/dist/schema/labels/toFilesystem.d.ts.map +1 -1
- package/dist/schema/labels/toFilesystem.js +10 -8
- package/dist/schema/labels/toFilesystem.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/cs/labels/Label.ts +12 -0
- package/src/cs/labels/getAllLabels.ts +30 -5
- package/src/cs/locales/addLocale.ts +59 -0
- package/src/cs/locales/ensureLocaleExists.ts +51 -0
- package/src/cs/locales/getLocales.ts +38 -0
- 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 +58 -0
- package/src/schema/entries/toContentstack.ts +75 -6
- package/src/schema/entries/toFilesystem.ts +29 -14
- package/src/schema/labels/lib/labelHelpers.ts +36 -0
- package/src/schema/labels/lib/labelOperations.ts +74 -0
- package/src/schema/labels/toContentstack.ts +208 -91
- package/src/schema/labels/toFilesystem.ts +15 -9
|
@@ -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: readonly string[];
|
|
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,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,wBAAgB,OAAO,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,KAAK,CAE9C"}
|
|
@@ -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,MAAM,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AAC3E,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: readonly string[];\n}\n\nexport function isLabel(o: unknown): o is Label {\n\treturn isItem(o) && typeof o.name === 'string' && Array.isArray(o.parent);\n}\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type Client from '../api/Client.js';
|
|
2
|
-
|
|
2
|
+
import type Label from './Label.js';
|
|
3
|
+
export default function getAllLabels(client: Client): Promise<Label[]>;
|
|
3
4
|
//# sourceMappingURL=getAllLabels.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getAllLabels.d.ts","sourceRoot":"","sources":["../../../src/cs/labels/getAllLabels.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;
|
|
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"}
|
|
@@ -1,17 +1,37 @@
|
|
|
1
1
|
import ContentstackError from '../api/ContentstackError.js';
|
|
2
2
|
import isRecord from '#cli/util/isRecord.js';
|
|
3
|
+
import { isLabel } from './Label.js';
|
|
3
4
|
export default async function getAllLabels(client) {
|
|
4
5
|
const res = (await client.GET('/v3/labels'));
|
|
5
6
|
const data = res?.data;
|
|
6
7
|
const error = res?.error;
|
|
7
8
|
const msg = `Failed to fetch labels`;
|
|
8
9
|
ContentstackError.throwIfError(error, msg);
|
|
10
|
+
let rawLabels = [];
|
|
9
11
|
if (isRecord(data) && Array.isArray(data.labels)) {
|
|
10
|
-
|
|
12
|
+
rawLabels = data.labels;
|
|
11
13
|
}
|
|
12
|
-
if (Array.isArray(data)) {
|
|
13
|
-
|
|
14
|
+
else if (Array.isArray(data)) {
|
|
15
|
+
rawLabels = data;
|
|
14
16
|
}
|
|
15
|
-
|
|
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: Array.isArray(raw.parent) ? raw.parent : [],
|
|
28
|
+
uid: raw.uid,
|
|
29
|
+
};
|
|
30
|
+
if (isLabel(label)) {
|
|
31
|
+
labels.push(label);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return labels;
|
|
16
36
|
}
|
|
17
37
|
//# sourceMappingURL=getAllLabels.js.map
|
|
@@ -1 +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,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;
|
|
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,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;gBACnD,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: Array.isArray(raw.parent) ? raw.parent : [],\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"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type Client from '../api/Client.js';
|
|
2
|
+
import type { Locale } from './getLocales.js';
|
|
3
|
+
/**
|
|
4
|
+
* Adds a new locale to the stack.
|
|
5
|
+
* @param client - Contentstack API client
|
|
6
|
+
* @param code - Locale code (e.g., 'zh-cn', 'zh-chs')
|
|
7
|
+
* @param name - Display name for the locale (e.g., 'Chinese - China')
|
|
8
|
+
* @param fallbackLocale - Optional fallback locale code
|
|
9
|
+
*/
|
|
10
|
+
export declare function addLocale(client: Client, code: string, name?: string, fallbackLocale?: string): Promise<Locale>;
|
|
11
|
+
//# sourceMappingURL=addLocale.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"addLocale.d.ts","sourceRoot":"","sources":["../../../src/cs/locales/addLocale.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;AAG3C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAU9C;;;;;;GAMG;AACH,wBAAsB,SAAS,CAC9B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,EACb,cAAc,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,MAAM,CAAC,CAiCjB"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import ContentstackError from '../api/ContentstackError.js';
|
|
2
|
+
import isRecord from '#cli/util/isRecord.js';
|
|
3
|
+
/**
|
|
4
|
+
* Adds a new locale to the stack.
|
|
5
|
+
* @param client - Contentstack API client
|
|
6
|
+
* @param code - Locale code (e.g., 'zh-cn', 'zh-chs')
|
|
7
|
+
* @param name - Display name for the locale (e.g., 'Chinese - China')
|
|
8
|
+
* @param fallbackLocale - Optional fallback locale code
|
|
9
|
+
*/
|
|
10
|
+
export async function addLocale(client, code, name, fallbackLocale) {
|
|
11
|
+
const requestBody = {
|
|
12
|
+
locale: {
|
|
13
|
+
code,
|
|
14
|
+
...(fallbackLocale !== undefined && { fallback_locale: fallbackLocale }),
|
|
15
|
+
...(name !== undefined && { name }),
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
const response = await client.POST('/v3/locales', {
|
|
19
|
+
body: requestBody,
|
|
20
|
+
});
|
|
21
|
+
const msg = `Failed to add locale '${code}'`;
|
|
22
|
+
ContentstackError.throwIfError(response.error, msg);
|
|
23
|
+
if (!response.response.ok) {
|
|
24
|
+
throw new Error(msg);
|
|
25
|
+
}
|
|
26
|
+
const { data } = response;
|
|
27
|
+
if (!isRecord(data)) {
|
|
28
|
+
throw new TypeError(msg);
|
|
29
|
+
}
|
|
30
|
+
const { locale } = data;
|
|
31
|
+
if (!isRecord(locale)) {
|
|
32
|
+
throw new TypeError(msg);
|
|
33
|
+
}
|
|
34
|
+
return locale;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=addLocale.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"addLocale.js","sourceRoot":"","sources":["../../../src/cs/locales/addLocale.ts"],"names":[],"mappings":"AACA,OAAO,iBAAiB,MAAM,6BAA6B,CAAC;AAC5D,OAAO,QAAQ,MAAM,uBAAuB,CAAC;AAW7C;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC9B,MAAc,EACd,IAAY,EACZ,IAAa,EACb,cAAuB;IAEvB,MAAM,WAAW,GAAqB;QACrC,MAAM,EAAE;YACP,IAAI;YACJ,GAAG,CAAC,cAAc,KAAK,SAAS,IAAI,EAAE,eAAe,EAAE,cAAc,EAAE,CAAC;YACxE,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,EAAE,IAAI,EAAE,CAAC;SACnC;KACD,CAAC;IAEF,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE;QACjD,IAAI,EAAE,WAAoB;KAC1B,CAAC,CAAC;IAEH,MAAM,GAAG,GAAG,yBAAyB,IAAI,GAAG,CAAC;IAC7C,iBAAiB,CAAC,YAAY,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAEpD,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;IACtB,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC;IAE1B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IAED,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAExB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IAED,OAAO,MAAgB,CAAC;AACzB,CAAC","sourcesContent":["import type Client from '../api/Client.js';\nimport ContentstackError from '../api/ContentstackError.js';\nimport isRecord from '#cli/util/isRecord.js';\nimport type { Locale } from './getLocales.js';\n\ninterface AddLocaleRequest {\n\treadonly locale: {\n\t\treadonly code: string;\n\t\treadonly fallback_locale?: string;\n\t\treadonly name?: string;\n\t};\n}\n\n/**\n * Adds a new locale to the stack.\n * @param client - Contentstack API client\n * @param code - Locale code (e.g., 'zh-cn', 'zh-chs')\n * @param name - Display name for the locale (e.g., 'Chinese - China')\n * @param fallbackLocale - Optional fallback locale code\n */\nexport async function addLocale(\n\tclient: Client,\n\tcode: string,\n\tname?: string,\n\tfallbackLocale?: string,\n): Promise<Locale> {\n\tconst requestBody: AddLocaleRequest = {\n\t\tlocale: {\n\t\t\tcode,\n\t\t\t...(fallbackLocale !== undefined && { fallback_locale: fallbackLocale }),\n\t\t\t...(name !== undefined && { name }),\n\t\t},\n\t};\n\n\tconst response = await client.POST('/v3/locales', {\n\t\tbody: requestBody as never,\n\t});\n\n\tconst msg = `Failed to add locale '${code}'`;\n\tContentstackError.throwIfError(response.error, msg);\n\n\tif (!response.response.ok) {\n\t\tthrow new Error(msg);\n\t}\n\n\tconst { data } = response;\n\n\tif (!isRecord(data)) {\n\t\tthrow new TypeError(msg);\n\t}\n\n\tconst { locale } = data;\n\n\tif (!isRecord(locale)) {\n\t\tthrow new TypeError(msg);\n\t}\n\n\treturn locale as Locale;\n}\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type Client from '../api/Client.js';
|
|
2
|
+
import type { Locale } from './getLocales.js';
|
|
3
|
+
/**
|
|
4
|
+
* Ensures a locale exists in the target stack. If it doesn't exist, creates it.
|
|
5
|
+
* @param client - Contentstack API client
|
|
6
|
+
* @param localeCode - Locale code to ensure exists (e.g., 'zh-cn')
|
|
7
|
+
* @param fallbackLocale - Optional fallback locale code (defaults to 'en-us')
|
|
8
|
+
* @returns The locale object (either existing or newly created)
|
|
9
|
+
*/
|
|
10
|
+
export declare function ensureLocaleExists(client: Client, localeCode: string, fallbackLocale?: string): Promise<Locale>;
|
|
11
|
+
//# sourceMappingURL=ensureLocaleExists.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ensureLocaleExists.d.ts","sourceRoot":"","sources":["../../../src/cs/locales/ensureLocaleExists.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;AAG3C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAE9C;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACvC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,cAAc,SAAU,GACtB,OAAO,CAAC,MAAM,CAAC,CAgBjB"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { addLocale } from './addLocale.js';
|
|
2
|
+
import { getLocales } from './getLocales.js';
|
|
3
|
+
/**
|
|
4
|
+
* Ensures a locale exists in the target stack. If it doesn't exist, creates it.
|
|
5
|
+
* @param client - Contentstack API client
|
|
6
|
+
* @param localeCode - Locale code to ensure exists (e.g., 'zh-cn')
|
|
7
|
+
* @param fallbackLocale - Optional fallback locale code (defaults to 'en-us')
|
|
8
|
+
* @returns The locale object (either existing or newly created)
|
|
9
|
+
*/
|
|
10
|
+
export async function ensureLocaleExists(client, localeCode, fallbackLocale = 'en-us') {
|
|
11
|
+
const existingLocales = await getLocales(client);
|
|
12
|
+
const existing = existingLocales.find((loc) => loc.code === localeCode);
|
|
13
|
+
if (existing !== undefined) {
|
|
14
|
+
return existing;
|
|
15
|
+
}
|
|
16
|
+
// Locale doesn't exist - create it
|
|
17
|
+
// Derive a reasonable display name from the locale code
|
|
18
|
+
const name = deriveLocaleName(localeCode);
|
|
19
|
+
const newLocale = await addLocale(client, localeCode, name, fallbackLocale);
|
|
20
|
+
return newLocale;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Derives a human-readable name from a locale code.
|
|
24
|
+
* This is a basic implementation that can be expanded as needed.
|
|
25
|
+
*/
|
|
26
|
+
function deriveLocaleName(code) {
|
|
27
|
+
const nameMap = {
|
|
28
|
+
'en-us': 'English - United States',
|
|
29
|
+
'zh-chs': 'Chinese (simplified)',
|
|
30
|
+
'zh-cht': 'Chinese (traditional)',
|
|
31
|
+
'zh-cn': 'Chinese - China',
|
|
32
|
+
'zh-hans': 'Chinese (simplified)',
|
|
33
|
+
'zh-hant': 'Chinese (traditional)',
|
|
34
|
+
'zh-tw': 'Chinese - Taiwan',
|
|
35
|
+
};
|
|
36
|
+
return nameMap[code.toLowerCase()] ?? code.toUpperCase();
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=ensureLocaleExists.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ensureLocaleExists.js","sourceRoot":"","sources":["../../../src/cs/locales/ensureLocaleExists.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACvC,MAAc,EACd,UAAkB,EAClB,cAAc,GAAG,OAAO;IAExB,MAAM,eAAe,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;IAExE,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO,QAAQ,CAAC;IACjB,CAAC;IAED,mCAAmC;IAEnC,wDAAwD;IACxD,MAAM,IAAI,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAE1C,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;IAE5E,OAAO,SAAS,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,SAAS,gBAAgB,CAAC,IAAY;IACrC,MAAM,OAAO,GAA2B;QACvC,OAAO,EAAE,yBAAyB;QAClC,QAAQ,EAAE,sBAAsB;QAChC,QAAQ,EAAE,uBAAuB;QACjC,OAAO,EAAE,iBAAiB;QAC1B,SAAS,EAAE,sBAAsB;QACjC,SAAS,EAAE,uBAAuB;QAClC,OAAO,EAAE,kBAAkB;KAC3B,CAAC;IAEF,OAAO,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;AAC1D,CAAC","sourcesContent":["import type Client from '../api/Client.js';\nimport { addLocale } from './addLocale.js';\nimport { getLocales } from './getLocales.js';\nimport type { Locale } from './getLocales.js';\n\n/**\n * Ensures a locale exists in the target stack. If it doesn't exist, creates it.\n * @param client - Contentstack API client\n * @param localeCode - Locale code to ensure exists (e.g., 'zh-cn')\n * @param fallbackLocale - Optional fallback locale code (defaults to 'en-us')\n * @returns The locale object (either existing or newly created)\n */\nexport async function ensureLocaleExists(\n\tclient: Client,\n\tlocaleCode: string,\n\tfallbackLocale = 'en-us',\n): Promise<Locale> {\n\tconst existingLocales = await getLocales(client);\n\tconst existing = existingLocales.find((loc) => loc.code === localeCode);\n\n\tif (existing !== undefined) {\n\t\treturn existing;\n\t}\n\n\t// Locale doesn't exist - create it\n\n\t// Derive a reasonable display name from the locale code\n\tconst name = deriveLocaleName(localeCode);\n\n\tconst newLocale = await addLocale(client, localeCode, name, fallbackLocale);\n\n\treturn newLocale;\n}\n\n/**\n * Derives a human-readable name from a locale code.\n * This is a basic implementation that can be expanded as needed.\n */\nfunction deriveLocaleName(code: string): string {\n\tconst nameMap: Record<string, string> = {\n\t\t'en-us': 'English - United States',\n\t\t'zh-chs': 'Chinese (simplified)',\n\t\t'zh-cht': 'Chinese (traditional)',\n\t\t'zh-cn': 'Chinese - China',\n\t\t'zh-hans': 'Chinese (simplified)',\n\t\t'zh-hant': 'Chinese (traditional)',\n\t\t'zh-tw': 'Chinese - Taiwan',\n\t};\n\n\treturn nameMap[code.toLowerCase()] ?? code.toUpperCase();\n}\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type Client from '../api/Client.js';
|
|
2
|
+
export interface Locale {
|
|
3
|
+
readonly code: string;
|
|
4
|
+
readonly fallback_locale?: string;
|
|
5
|
+
readonly name: string;
|
|
6
|
+
readonly uid: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Fetches all locales configured for a stack.
|
|
10
|
+
*/
|
|
11
|
+
export declare function getLocales(client: Client): Promise<readonly Locale[]>;
|
|
12
|
+
//# sourceMappingURL=getLocales.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getLocales.d.ts","sourceRoot":"","sources":["../../../src/cs/locales/getLocales.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;AAI3C,MAAM,WAAW,MAAM;IACtB,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;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAuB3E"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import ContentstackError from '../api/ContentstackError.js';
|
|
2
|
+
import isRecord from '#cli/util/isRecord.js';
|
|
3
|
+
/**
|
|
4
|
+
* Fetches all locales configured for a stack.
|
|
5
|
+
*/
|
|
6
|
+
export async function getLocales(client) {
|
|
7
|
+
const response = await client.GET('/v3/locales', {});
|
|
8
|
+
const msg = 'Failed to fetch locales';
|
|
9
|
+
ContentstackError.throwIfError(response.error, msg);
|
|
10
|
+
if (!response.response.ok) {
|
|
11
|
+
throw new Error(msg);
|
|
12
|
+
}
|
|
13
|
+
const { data } = response;
|
|
14
|
+
if (!isRecord(data)) {
|
|
15
|
+
throw new TypeError(msg);
|
|
16
|
+
}
|
|
17
|
+
const { locales } = data;
|
|
18
|
+
if (!Array.isArray(locales)) {
|
|
19
|
+
throw new TypeError(msg);
|
|
20
|
+
}
|
|
21
|
+
return locales;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=getLocales.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getLocales.js","sourceRoot":"","sources":["../../../src/cs/locales/getLocales.ts"],"names":[],"mappings":"AACA,OAAO,iBAAiB,MAAM,6BAA6B,CAAC;AAC5D,OAAO,QAAQ,MAAM,uBAAuB,CAAC;AAS7C;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAc;IAC9C,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;IAErD,MAAM,GAAG,GAAG,yBAAyB,CAAC;IACtC,iBAAiB,CAAC,YAAY,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAEpD,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;IACtB,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC;IAE1B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IAED,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAEzB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IAED,OAAO,OAAmB,CAAC;AAC5B,CAAC","sourcesContent":["import type Client from '../api/Client.js';\nimport ContentstackError from '../api/ContentstackError.js';\nimport isRecord from '#cli/util/isRecord.js';\n\nexport interface Locale {\n\treadonly code: string;\n\treadonly fallback_locale?: string;\n\treadonly name: string;\n\treadonly uid: string;\n}\n\n/**\n * Fetches all locales configured for a stack.\n */\nexport async function getLocales(client: Client): Promise<readonly Locale[]> {\n\tconst response = await client.GET('/v3/locales', {});\n\n\tconst msg = 'Failed to fetch locales';\n\tContentstackError.throwIfError(response.error, msg);\n\n\tif (!response.response.ok) {\n\t\tthrow new Error(msg);\n\t}\n\n\tconst { data } = response;\n\n\tif (!isRecord(data)) {\n\t\tthrow new TypeError(msg);\n\t}\n\n\tconst { locales } = data;\n\n\tif (!Array.isArray(locales)) {\n\t\tthrow new TypeError(msg);\n\t}\n\n\treturn locales as Locale[];\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: parentUid ? [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,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE;aAC3B,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: parentUid ? [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,CAoC1B"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Labels have a tree structure defined by uid/parent array.
|
|
2
|
+
//
|
|
3
|
+
// The API returns a flat array that includes uid/parent, where parent is an array
|
|
4
|
+
// containing the parent UID (or empty array for top-level labels).
|
|
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, ...labelWithoutParent } = label;
|
|
15
|
+
// Preserve all fields except parent (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 label of labels) {
|
|
23
|
+
const node = byUid.get(label.uid);
|
|
24
|
+
if (!node) {
|
|
25
|
+
throw new Error(`Label ${label.uid} not found`);
|
|
26
|
+
}
|
|
27
|
+
const parentUid = label.parent.length > 0 ? label.parent[0] : null;
|
|
28
|
+
if (!parentUid) {
|
|
29
|
+
topLevel.push(node);
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
const parent = byUid.get(parentUid);
|
|
33
|
+
if (!parent) {
|
|
34
|
+
const msg = `Orphaned label ${label.uid} with parent ${parentUid}`;
|
|
35
|
+
throw new Error(msg);
|
|
36
|
+
}
|
|
37
|
+
(parent.children ??= []).push(node);
|
|
38
|
+
}
|
|
39
|
+
return topLevel;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=organize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"organize.js","sourceRoot":"","sources":["../../../src/dto/labels/organize.ts"],"names":[],"mappings":"AAGA,4DAA4D;AAC5D,EAAE;AACF,kFAAkF;AAClF,mEAAmE;AACnE,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,MAAM,EAAE,GAAG,kBAAkB,EAAE,GAAG,KAAK,CAAC;QAChD,iFAAiF;QACjF,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,KAAK,IAAI,MAAM,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,SAAS,KAAK,CAAC,GAAG,YAAY,CAAC,CAAC;QACjD,CAAC;QAED,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACnE,IAAI,CAAC,SAAS,EAAE,CAAC;YAChB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACpB,SAAS;QACV,CAAC;QAED,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACpC,IAAI,CAAC,MAAM,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,kBAAkB,KAAK,CAAC,GAAG,gBAAgB,SAAS,EAAE,CAAC;YACnE,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;QAED,CAAC,MAAM,CAAC,QAAQ,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrC,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 array.\n//\n// The API returns a flat array that includes uid/parent, where parent is an array\n// containing the parent UID (or empty array for top-level labels).\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, ...labelWithoutParent } = label;\n\t\t// Preserve all fields except parent (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 label of labels) {\n\t\tconst node = byUid.get(label.uid);\n\t\tif (!node) {\n\t\t\tthrow new Error(`Label ${label.uid} not found`);\n\t\t}\n\n\t\tconst parentUid = label.parent.length > 0 ? label.parent[0] : null;\n\t\tif (!parentUid) {\n\t\t\ttopLevel.push(node);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst parent = byUid.get(parentUid);\n\t\tif (!parent) {\n\t\t\tconst msg = `Orphaned label ${label.uid} with parent ${parentUid}`;\n\t\t\tthrow new Error(msg);\n\t\t}\n\n\t\t(parent.children ??= []).push(node);\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":"toContentstack.d.ts","sourceRoot":"","sources":["../../../src/schema/entries/toContentstack.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"toContentstack.d.ts","sourceRoot":"","sources":["../../../src/schema/entries/toContentstack.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAOlE,OAAO,KAAK,WAAW,MAAM,iCAAiC,CAAC;AAC/D,OAAO,KAAK,GAAG,MAAM,eAAe,CAAC;AAUrC,wBAA8B,cAAc,CAC3C,GAAG,EAAE,GAAG,EACR,WAAW,EAAE,WAAW,EACxB,GAAG,EAAE,WAAW,yDAuChB"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import deleteEntry from '#cli/cs/entries/delete.js';
|
|
2
2
|
import getEntryLocales from '#cli/cs/entries/getEntryLocales.js';
|
|
3
3
|
import importEntry from '#cli/cs/entries/import.js';
|
|
4
|
+
import { ensureLocaleExists } from '#cli/cs/locales/ensureLocaleExists.js';
|
|
4
5
|
import BeaconReplacer from '#cli/dto/entry/BeaconReplacer.js';
|
|
5
6
|
import getUi from '../lib/SchemaUi.js';
|
|
6
7
|
import planMerge from '../xfer/lib/planMerge.js';
|
|
@@ -26,7 +27,18 @@ export default async function toContentstack(ctx, contentType, bar) {
|
|
|
26
27
|
remove: async (entry) => deleteEntry(ctx.cs.client, contentType.uid, entry.uid),
|
|
27
28
|
update,
|
|
28
29
|
});
|
|
29
|
-
|
|
30
|
+
// Process unmodified entries to ensure all locale versions are synced
|
|
31
|
+
await processUnmodifiedEntries(result.unmodified, ctx, contentType, csEntriesByTitle, fsEntriesByTitle, transformer, filenamesByTitle);
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
function shouldSyncLocales(fsLocaleVersions, csLocaleSet) {
|
|
35
|
+
// Check if we have new locale versions that don't exist in Contentstack
|
|
36
|
+
const fsLocaleSet = new Set(fsLocaleVersions.map((lv) => (lv.locale === 'default' ? null : lv.locale)));
|
|
37
|
+
return Array.from(fsLocaleSet).some((locale) => locale !== null && !csLocaleSet.has(locale));
|
|
38
|
+
}
|
|
39
|
+
async function processUnmodifiedEntries(unmodified, ctx, contentType, csEntriesByTitle, fsEntriesByTitle, transformer, filenamesByTitle) {
|
|
40
|
+
const ui = getUi();
|
|
41
|
+
for (const title of unmodified) {
|
|
30
42
|
const cs = csEntriesByTitle.get(title);
|
|
31
43
|
const fs = fsEntriesByTitle.get(title);
|
|
32
44
|
if (cs && !fs && ui.options.schema.deletionStrategy !== 'delete') {
|
|
@@ -38,10 +50,18 @@ export default async function toContentstack(ctx, contentType, bar) {
|
|
|
38
50
|
if (!cs || !fs) {
|
|
39
51
|
throw new Error(`No matching entry found for ${title}.`);
|
|
40
52
|
}
|
|
53
|
+
// Load all locale versions from filesystem
|
|
54
|
+
const fsLocaleVersions = await loadFsLocaleVersions(fs, contentType.uid, filenamesByTitle);
|
|
55
|
+
const csLocaleSet = await getExistingLocales(ctx, contentType, cs.uid);
|
|
56
|
+
// Only push if there are new locale versions to sync
|
|
57
|
+
if (!shouldSyncLocales(fsLocaleVersions, csLocaleSet)) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
// Push all locale versions (including new locales like zh-cn)
|
|
61
|
+
await updateAllLocales(ctx, transformer, contentType, fsLocaleVersions, cs.uid, csLocaleSet);
|
|
41
62
|
const entry = { ...fs, uid: cs.uid };
|
|
42
63
|
ctx.references.recordEntryForReferences(contentType.uid, entry);
|
|
43
64
|
}
|
|
44
|
-
return result;
|
|
45
65
|
}
|
|
46
66
|
function buildUpdateFn(ctx, csEntriesByTitle, transformer, contentType, filenamesByTitle) {
|
|
47
67
|
return async (entry) => {
|
|
@@ -72,14 +92,19 @@ async function getExistingLocales(ctx, contentType, entryUid) {
|
|
|
72
92
|
return new Set(csLocales.map((l) => l.code));
|
|
73
93
|
}
|
|
74
94
|
async function updateAllLocales(ctx, transformer, contentType, fsLocaleVersions, entryUid, csLocaleSet) {
|
|
95
|
+
// Ensure all required locales exist in the target stack before pushing entries
|
|
96
|
+
const localeEnsurePromises = fsLocaleVersions
|
|
97
|
+
.filter((lv) => lv.locale !== 'default')
|
|
98
|
+
.map(async (lv) => ensureLocaleExists(ctx.cs.client, lv.locale));
|
|
99
|
+
await Promise.all(localeEnsurePromises);
|
|
75
100
|
// Import all locale versions in parallel for better performance
|
|
76
101
|
const importPromises = fsLocaleVersions.map(async (localeVersion) => {
|
|
77
102
|
const transformed = transformer.process(localeVersion.entry);
|
|
78
103
|
// Pass undefined for 'default' locale (single-locale backward compat)
|
|
79
104
|
const locale = localeVersion.locale === 'default' ? undefined : localeVersion.locale;
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
105
|
+
// Always use overwrite=true for locale-specific versions since the entry exists.
|
|
106
|
+
// For 'default' locale (single-locale backward compat), only overwrite if entry has locales.
|
|
107
|
+
const overwrite = locale ? true : csLocaleSet.size > 0;
|
|
83
108
|
return importEntry(ctx.cs.client, contentType.uid, { ...transformed, uid: entryUid }, overwrite, locale);
|
|
84
109
|
});
|
|
85
110
|
await Promise.all(importPromises);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toContentstack.js","sourceRoot":"","sources":["../../../src/schema/entries/toContentstack.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContentType } from '#cli/cs/content-types/Types.js';\nimport deleteEntry from '#cli/cs/entries/delete.js';\nimport getEntryLocales from '#cli/cs/entries/getEntryLocales.js';\nimport importEntry from '#cli/cs/entries/import.js';\nimport type { Entry } from '#cli/cs/entries/Types.js';\nimport BeaconReplacer from '#cli/dto/entry/BeaconReplacer.js';\nimport type ProgressBar from '#cli/ui/progress/ProgressBar.js';\nimport type Ctx from '../ctx/Ctx.js';\nimport getUi from '../lib/SchemaUi.js';\nimport planMerge from '../xfer/lib/planMerge.js';\nimport processPlan from '../xfer/lib/processPlan.js';\nimport equality from './equality.js';\nimport buildCreator from './lib/buildCreator.js';\nimport generateFilenames from './lib/generateFilenames.js';\nimport loadEntryLocales from './lib/loadEntryLocales.js';\nimport schemaDirectory from './schemaDirectory.js';\n\nexport default async function toContentstack(\n\tctx: Ctx,\n\tcontentType: ContentType,\n\tbar: ProgressBar,\n) {\n\tconst ui = getUi();\n\n\tconst fsEntriesByTitle = ctx.fs.entries.byTitleFor(contentType.uid);\n\tconst csEntriesByTitle = ctx.cs.entries.byTitleFor(contentType.uid);\n\tconst transformer = new BeaconReplacer(ctx, contentType);\n\tconst filenamesByTitle = generateFilenames(fsEntriesByTitle);\n\tconst create = buildCreator(ctx, transformer, contentType);\n\tconst update = buildUpdateFn(\n\t\tctx,\n\t\tcsEntriesByTitle,\n\t\ttransformer,\n\t\tcontentType,\n\t\tfilenamesByTitle,\n\t);\n\n\tconst result = await processPlan<Entry>({\n\t\tcreate,\n\t\tdeletionStrategy: ui.options.schema.deletionStrategy,\n\t\tplan: planMerge(equality, fsEntriesByTitle, csEntriesByTitle),\n\t\tprogress: bar,\n\t\tremove: async (entry) =>\n\t\t\tdeleteEntry(ctx.cs.client, contentType.uid, entry.uid),\n\t\tupdate,\n\t});\n\n\tfor (const title of result.unmodified) {\n\t\tconst cs = csEntriesByTitle.get(title);\n\t\tconst fs = fsEntriesByTitle.get(title);\n\n\t\tif (cs && !fs && ui.options.schema.deletionStrategy !== 'delete') {\n\t\t\t// The entry was deleted from the file system, but the user has chosen\n\t\t\t// to ignore deletions in Contentstack. The item is invalid as a\n\t\t\t// reference, but does not represent an error state.\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!cs || !fs) {\n\t\t\tthrow new Error(`No matching entry found for ${title}.`);\n\t\t}\n\n\t\tconst entry = { ...fs, uid: cs.uid };\n\t\tctx.references.recordEntryForReferences(contentType.uid, entry);\n\t}\n\n\treturn result;\n}\n\nfunction buildUpdateFn(\n\tctx: Ctx,\n\tcsEntriesByTitle: ReadonlyMap<string, Entry>,\n\ttransformer: BeaconReplacer,\n\tcontentType: ContentType,\n\tfilenamesByTitle: ReadonlyMap<Entry['uid'], string>,\n) {\n\treturn async (entry: Entry) => {\n\t\tconst match = csEntriesByTitle.get(entry.title);\n\t\tif (!match) {\n\t\t\tthrow new Error(`No matching entry found for ${entry.title}.`);\n\t\t}\n\n\t\tconst fsLocaleVersions = await loadFsLocaleVersions(\n\t\t\tentry,\n\t\t\tcontentType.uid,\n\t\t\tfilenamesByTitle,\n\t\t);\n\n\t\tconst csLocaleSet = await getExistingLocales(ctx, contentType, match.uid);\n\n\t\tawait updateAllLocales(\n\t\t\tctx,\n\t\t\ttransformer,\n\t\t\tcontentType,\n\t\t\tfsLocaleVersions,\n\t\t\tmatch.uid,\n\t\t\tcsLocaleSet,\n\t\t);\n\n\t\tctx.references.recordEntryForReferences(contentType.uid, {\n\t\t\t...entry,\n\t\t\tuid: match.uid,\n\t\t});\n\t};\n}\n\nasync function loadFsLocaleVersions(\n\tentry: Entry,\n\tcontentTypeUid: string,\n\tfilenamesByTitle: ReadonlyMap<Entry['uid'], string>,\n) {\n\tconst filename = filenamesByTitle.get(entry.title);\n\tif (!filename) {\n\t\tthrow new Error(`No filename found for entry ${entry.title}.`);\n\t}\n\n\tconst baseFilename = filename.replace(/\\.yaml$/u, '');\n\tconst directory = schemaDirectory(contentTypeUid);\n\n\treturn loadEntryLocales(directory, entry.title, baseFilename);\n}\n\nasync function getExistingLocales(\n\tctx: Ctx,\n\tcontentType: ContentType,\n\tentryUid: string,\n) {\n\tconst csLocales = await getEntryLocales(\n\t\tctx.cs.client,\n\t\tcontentType.uid,\n\t\tentryUid,\n\t);\n\treturn new Set(csLocales.map((l) => l.code));\n}\n\nasync function updateAllLocales(\n\tctx: Ctx,\n\ttransformer: BeaconReplacer,\n\tcontentType: ContentType,\n\tfsLocaleVersions: Awaited<ReturnType<typeof loadFsLocaleVersions>>,\n\tentryUid: string,\n\tcsLocaleSet: Set<string>,\n) {\n\t// Import all locale versions in parallel for better performance\n\tconst importPromises = fsLocaleVersions.map(async (localeVersion) => {\n\t\tconst transformed = transformer.process(localeVersion.entry);\n\n\t\t// Pass undefined for 'default' locale (single-locale backward compat)\n\t\tconst locale =\n\t\t\tlocaleVersion.locale === 'default' ? undefined : localeVersion.locale;\n\t\tconst overwrite = locale\n\t\t\t? csLocaleSet.has(localeVersion.locale)\n\t\t\t: csLocaleSet.size > 0;\n\n\t\treturn importEntry(\n\t\t\tctx.cs.client,\n\t\t\tcontentType.uid,\n\t\t\t{ ...transformed, uid: entryUid },\n\t\t\toverwrite,\n\t\t\tlocale,\n\t\t);\n\t});\n\n\tawait Promise.all(importPromises);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"toContentstack.js","sourceRoot":"","sources":["../../../src/schema/entries/toContentstack.ts"],"names":[],"mappings":"AACA,OAAO,WAAW,MAAM,2BAA2B,CAAC;AACpD,OAAO,eAAe,MAAM,oCAAoC,CAAC;AACjE,OAAO,WAAW,MAAM,2BAA2B,CAAC;AAEpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,cAAc,MAAM,kCAAkC,CAAC;AAG9D,OAAO,KAAK,MAAM,oBAAoB,CAAC;AACvC,OAAO,SAAS,MAAM,0BAA0B,CAAC;AACjD,OAAO,WAAW,MAAM,4BAA4B,CAAC;AACrD,OAAO,QAAQ,MAAM,eAAe,CAAC;AACrC,OAAO,YAAY,MAAM,uBAAuB,CAAC;AACjD,OAAO,iBAAiB,MAAM,4BAA4B,CAAC;AAC3D,OAAO,gBAAgB,MAAM,2BAA2B,CAAC;AACzD,OAAO,eAAe,MAAM,sBAAsB,CAAC;AAEnD,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,cAAc,CAC3C,GAAQ,EACR,WAAwB,EACxB,GAAgB;IAEhB,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IAEnB,MAAM,gBAAgB,GAAG,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACpE,MAAM,gBAAgB,GAAG,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACpE,MAAM,WAAW,GAAG,IAAI,cAAc,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IACzD,MAAM,gBAAgB,GAAG,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;IAC7D,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;IAC3D,MAAM,MAAM,GAAG,aAAa,CAC3B,GAAG,EACH,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,gBAAgB,CAChB,CAAC;IAEF,MAAM,MAAM,GAAG,MAAM,WAAW,CAAQ;QACvC,MAAM;QACN,gBAAgB,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,gBAAgB;QACpD,IAAI,EAAE,SAAS,CAAC,QAAQ,EAAE,gBAAgB,EAAE,gBAAgB,CAAC;QAC7D,QAAQ,EAAE,GAAG;QACb,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CACvB,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC;QACvD,MAAM;KACN,CAAC,CAAC;IAEH,sEAAsE;IACtE,MAAM,wBAAwB,CAC7B,MAAM,CAAC,UAAU,EACjB,GAAG,EACH,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,gBAAgB,CAChB,CAAC;IAEF,OAAO,MAAM,CAAC;AACf,CAAC;AAED,SAAS,iBAAiB,CACzB,gBAAkE,EAClE,WAAwB;IAExB,wEAAwE;IACxE,MAAM,WAAW,GAAG,IAAI,GAAG,CAC1B,gBAAgB,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAC1E,CAAC;IACF,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAClC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,KAAK,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CACvD,CAAC;AACH,CAAC;AAED,KAAK,UAAU,wBAAwB,CACtC,UAA4B,EAC5B,GAAQ,EACR,WAAwB,EACxB,gBAA4C,EAC5C,gBAA4C,EAC5C,WAA2B,EAC3B,gBAAmD;IAEnD,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IAEnB,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;QAChC,MAAM,EAAE,GAAG,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACvC,MAAM,EAAE,GAAG,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAEvC,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,gBAAgB,KAAK,QAAQ,EAAE,CAAC;YAClE,sEAAsE;YACtE,gEAAgE;YAChE,oDAAoD;YACpD,SAAS;QACV,CAAC;QAED,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CAAC,+BAA+B,KAAK,GAAG,CAAC,CAAC;QAC1D,CAAC;QAED,2CAA2C;QAC3C,MAAM,gBAAgB,GAAG,MAAM,oBAAoB,CAClD,EAAE,EACF,WAAW,CAAC,GAAG,EACf,gBAAgB,CAChB,CAAC;QAEF,MAAM,WAAW,GAAG,MAAM,kBAAkB,CAAC,GAAG,EAAE,WAAW,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;QAEvE,qDAAqD;QACrD,IAAI,CAAC,iBAAiB,CAAC,gBAAgB,EAAE,WAAW,CAAC,EAAE,CAAC;YACvD,SAAS;QACV,CAAC;QAED,8DAA8D;QAC9D,MAAM,gBAAgB,CACrB,GAAG,EACH,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,EAAE,CAAC,GAAG,EACN,WAAW,CACX,CAAC;QAEF,MAAM,KAAK,GAAG,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC;QACrC,GAAG,CAAC,UAAU,CAAC,wBAAwB,CAAC,WAAW,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACjE,CAAC;AACF,CAAC;AAED,SAAS,aAAa,CACrB,GAAQ,EACR,gBAA4C,EAC5C,WAA2B,EAC3B,WAAwB,EACxB,gBAAmD;IAEnD,OAAO,KAAK,EAAE,KAAY,EAAE,EAAE;QAC7B,MAAM,KAAK,GAAG,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAChD,IAAI,CAAC,KAAK,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,+BAA+B,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,gBAAgB,GAAG,MAAM,oBAAoB,CAClD,KAAK,EACL,WAAW,CAAC,GAAG,EACf,gBAAgB,CAChB,CAAC;QAEF,MAAM,WAAW,GAAG,MAAM,kBAAkB,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QAE1E,MAAM,gBAAgB,CACrB,GAAG,EACH,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,KAAK,CAAC,GAAG,EACT,WAAW,CACX,CAAC;QAEF,GAAG,CAAC,UAAU,CAAC,wBAAwB,CAAC,WAAW,CAAC,GAAG,EAAE;YACxD,GAAG,KAAK;YACR,GAAG,EAAE,KAAK,CAAC,GAAG;SACd,CAAC,CAAC;IACJ,CAAC,CAAC;AACH,CAAC;AAED,KAAK,UAAU,oBAAoB,CAClC,KAAY,EACZ,cAAsB,EACtB,gBAAmD;IAEnD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACnD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,+BAA+B,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC;IAChE,CAAC;IAED,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IACtD,MAAM,SAAS,GAAG,eAAe,CAAC,cAAc,CAAC,CAAC;IAElD,OAAO,gBAAgB,CAAC,SAAS,EAAE,KAAK,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;AAC/D,CAAC;AAED,KAAK,UAAU,kBAAkB,CAChC,GAAQ,EACR,WAAwB,EACxB,QAAgB;IAEhB,MAAM,SAAS,GAAG,MAAM,eAAe,CACtC,GAAG,CAAC,EAAE,CAAC,MAAM,EACb,WAAW,CAAC,GAAG,EACf,QAAQ,CACR,CAAC;IACF,OAAO,IAAI,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAC9C,CAAC;AAED,KAAK,UAAU,gBAAgB,CAC9B,GAAQ,EACR,WAA2B,EAC3B,WAAwB,EACxB,gBAAkE,EAClE,QAAgB,EAChB,WAAwB;IAExB,+EAA+E;IAC/E,MAAM,oBAAoB,GAAG,gBAAgB;SAC3C,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,KAAK,SAAS,CAAC;SACvC,GAAG,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAElE,MAAM,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAExC,gEAAgE;IAChE,MAAM,cAAc,GAAG,gBAAgB,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE;QACnE,MAAM,WAAW,GAAG,WAAW,CAAC,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAE7D,sEAAsE;QACtE,MAAM,MAAM,GACX,aAAa,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC;QAEvE,iFAAiF;QACjF,6FAA6F;QAC7F,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,GAAG,CAAC,CAAC;QAEvD,OAAO,WAAW,CACjB,GAAG,CAAC,EAAE,CAAC,MAAM,EACb,WAAW,CAAC,GAAG,EACf,EAAE,GAAG,WAAW,EAAE,GAAG,EAAE,QAAQ,EAAE,EACjC,SAAS,EACT,MAAM,CACN,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;AACnC,CAAC","sourcesContent":["import type { ContentType } from '#cli/cs/content-types/Types.js';\nimport deleteEntry from '#cli/cs/entries/delete.js';\nimport getEntryLocales from '#cli/cs/entries/getEntryLocales.js';\nimport importEntry from '#cli/cs/entries/import.js';\nimport type { Entry } from '#cli/cs/entries/Types.js';\nimport { ensureLocaleExists } from '#cli/cs/locales/ensureLocaleExists.js';\nimport BeaconReplacer from '#cli/dto/entry/BeaconReplacer.js';\nimport type ProgressBar from '#cli/ui/progress/ProgressBar.js';\nimport type Ctx from '../ctx/Ctx.js';\nimport getUi from '../lib/SchemaUi.js';\nimport planMerge from '../xfer/lib/planMerge.js';\nimport processPlan from '../xfer/lib/processPlan.js';\nimport equality from './equality.js';\nimport buildCreator from './lib/buildCreator.js';\nimport generateFilenames from './lib/generateFilenames.js';\nimport loadEntryLocales from './lib/loadEntryLocales.js';\nimport schemaDirectory from './schemaDirectory.js';\n\nexport default async function toContentstack(\n\tctx: Ctx,\n\tcontentType: ContentType,\n\tbar: ProgressBar,\n) {\n\tconst ui = getUi();\n\n\tconst fsEntriesByTitle = ctx.fs.entries.byTitleFor(contentType.uid);\n\tconst csEntriesByTitle = ctx.cs.entries.byTitleFor(contentType.uid);\n\tconst transformer = new BeaconReplacer(ctx, contentType);\n\tconst filenamesByTitle = generateFilenames(fsEntriesByTitle);\n\tconst create = buildCreator(ctx, transformer, contentType);\n\tconst update = buildUpdateFn(\n\t\tctx,\n\t\tcsEntriesByTitle,\n\t\ttransformer,\n\t\tcontentType,\n\t\tfilenamesByTitle,\n\t);\n\n\tconst result = await processPlan<Entry>({\n\t\tcreate,\n\t\tdeletionStrategy: ui.options.schema.deletionStrategy,\n\t\tplan: planMerge(equality, fsEntriesByTitle, csEntriesByTitle),\n\t\tprogress: bar,\n\t\tremove: async (entry) =>\n\t\t\tdeleteEntry(ctx.cs.client, contentType.uid, entry.uid),\n\t\tupdate,\n\t});\n\n\t// Process unmodified entries to ensure all locale versions are synced\n\tawait processUnmodifiedEntries(\n\t\tresult.unmodified,\n\t\tctx,\n\t\tcontentType,\n\t\tcsEntriesByTitle,\n\t\tfsEntriesByTitle,\n\t\ttransformer,\n\t\tfilenamesByTitle,\n\t);\n\n\treturn result;\n}\n\nfunction shouldSyncLocales(\n\tfsLocaleVersions: Awaited<ReturnType<typeof loadFsLocaleVersions>>,\n\tcsLocaleSet: Set<string>,\n): boolean {\n\t// Check if we have new locale versions that don't exist in Contentstack\n\tconst fsLocaleSet = new Set(\n\t\tfsLocaleVersions.map((lv) => (lv.locale === 'default' ? null : lv.locale)),\n\t);\n\treturn Array.from(fsLocaleSet).some(\n\t\t(locale) => locale !== null && !csLocaleSet.has(locale),\n\t);\n}\n\nasync function processUnmodifiedEntries(\n\tunmodified: Iterable<string>,\n\tctx: Ctx,\n\tcontentType: ContentType,\n\tcsEntriesByTitle: ReadonlyMap<string, Entry>,\n\tfsEntriesByTitle: ReadonlyMap<string, Entry>,\n\ttransformer: BeaconReplacer,\n\tfilenamesByTitle: ReadonlyMap<Entry['uid'], string>,\n) {\n\tconst ui = getUi();\n\n\tfor (const title of unmodified) {\n\t\tconst cs = csEntriesByTitle.get(title);\n\t\tconst fs = fsEntriesByTitle.get(title);\n\n\t\tif (cs && !fs && ui.options.schema.deletionStrategy !== 'delete') {\n\t\t\t// The entry was deleted from the file system, but the user has chosen\n\t\t\t// to ignore deletions in Contentstack. The item is invalid as a\n\t\t\t// reference, but does not represent an error state.\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!cs || !fs) {\n\t\t\tthrow new Error(`No matching entry found for ${title}.`);\n\t\t}\n\n\t\t// Load all locale versions from filesystem\n\t\tconst fsLocaleVersions = await loadFsLocaleVersions(\n\t\t\tfs,\n\t\t\tcontentType.uid,\n\t\t\tfilenamesByTitle,\n\t\t);\n\n\t\tconst csLocaleSet = await getExistingLocales(ctx, contentType, cs.uid);\n\n\t\t// Only push if there are new locale versions to sync\n\t\tif (!shouldSyncLocales(fsLocaleVersions, csLocaleSet)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Push all locale versions (including new locales like zh-cn)\n\t\tawait updateAllLocales(\n\t\t\tctx,\n\t\t\ttransformer,\n\t\t\tcontentType,\n\t\t\tfsLocaleVersions,\n\t\t\tcs.uid,\n\t\t\tcsLocaleSet,\n\t\t);\n\n\t\tconst entry = { ...fs, uid: cs.uid };\n\t\tctx.references.recordEntryForReferences(contentType.uid, entry);\n\t}\n}\n\nfunction buildUpdateFn(\n\tctx: Ctx,\n\tcsEntriesByTitle: ReadonlyMap<string, Entry>,\n\ttransformer: BeaconReplacer,\n\tcontentType: ContentType,\n\tfilenamesByTitle: ReadonlyMap<Entry['uid'], string>,\n) {\n\treturn async (entry: Entry) => {\n\t\tconst match = csEntriesByTitle.get(entry.title);\n\t\tif (!match) {\n\t\t\tthrow new Error(`No matching entry found for ${entry.title}.`);\n\t\t}\n\n\t\tconst fsLocaleVersions = await loadFsLocaleVersions(\n\t\t\tentry,\n\t\t\tcontentType.uid,\n\t\t\tfilenamesByTitle,\n\t\t);\n\n\t\tconst csLocaleSet = await getExistingLocales(ctx, contentType, match.uid);\n\n\t\tawait updateAllLocales(\n\t\t\tctx,\n\t\t\ttransformer,\n\t\t\tcontentType,\n\t\t\tfsLocaleVersions,\n\t\t\tmatch.uid,\n\t\t\tcsLocaleSet,\n\t\t);\n\n\t\tctx.references.recordEntryForReferences(contentType.uid, {\n\t\t\t...entry,\n\t\t\tuid: match.uid,\n\t\t});\n\t};\n}\n\nasync function loadFsLocaleVersions(\n\tentry: Entry,\n\tcontentTypeUid: string,\n\tfilenamesByTitle: ReadonlyMap<Entry['uid'], string>,\n) {\n\tconst filename = filenamesByTitle.get(entry.title);\n\tif (!filename) {\n\t\tthrow new Error(`No filename found for entry ${entry.title}.`);\n\t}\n\n\tconst baseFilename = filename.replace(/\\.yaml$/u, '');\n\tconst directory = schemaDirectory(contentTypeUid);\n\n\treturn loadEntryLocales(directory, entry.title, baseFilename);\n}\n\nasync function getExistingLocales(\n\tctx: Ctx,\n\tcontentType: ContentType,\n\tentryUid: string,\n) {\n\tconst csLocales = await getEntryLocales(\n\t\tctx.cs.client,\n\t\tcontentType.uid,\n\t\tentryUid,\n\t);\n\treturn new Set(csLocales.map((l) => l.code));\n}\n\nasync function updateAllLocales(\n\tctx: Ctx,\n\ttransformer: BeaconReplacer,\n\tcontentType: ContentType,\n\tfsLocaleVersions: Awaited<ReturnType<typeof loadFsLocaleVersions>>,\n\tentryUid: string,\n\tcsLocaleSet: Set<string>,\n) {\n\t// Ensure all required locales exist in the target stack before pushing entries\n\tconst localeEnsurePromises = fsLocaleVersions\n\t\t.filter((lv) => lv.locale !== 'default')\n\t\t.map(async (lv) => ensureLocaleExists(ctx.cs.client, lv.locale));\n\n\tawait Promise.all(localeEnsurePromises);\n\n\t// Import all locale versions in parallel for better performance\n\tconst importPromises = fsLocaleVersions.map(async (localeVersion) => {\n\t\tconst transformed = transformer.process(localeVersion.entry);\n\n\t\t// Pass undefined for 'default' locale (single-locale backward compat)\n\t\tconst locale =\n\t\t\tlocaleVersion.locale === 'default' ? undefined : localeVersion.locale;\n\n\t\t// Always use overwrite=true for locale-specific versions since the entry exists.\n\t\t// For 'default' locale (single-locale backward compat), only overwrite if entry has locales.\n\t\tconst overwrite = locale ? true : csLocaleSet.size > 0;\n\n\t\treturn importEntry(\n\t\t\tctx.cs.client,\n\t\t\tcontentType.uid,\n\t\t\t{ ...transformed, uid: entryUid },\n\t\t\toverwrite,\n\t\t\tlocale,\n\t\t);\n\t});\n\n\tawait Promise.all(importPromises);\n}\n"]}
|
|
@@ -52,23 +52,36 @@ function createWriteFn(ctx, contentType, directory, getBasePath) {
|
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
54
54
|
// If only one locale, save without locale suffix for backward compatibility.
|
|
55
|
-
// When multiple locales exist
|
|
56
|
-
//
|
|
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
|
+
// When multiple locales exist, write English as base file and other locales
|
|
56
|
+
// with locale suffixes (e.g., Entry.yaml for English, Entry.zh-chs.yaml for Chinese)
|
|
64
57
|
// Write all locale versions in parallel for better performance
|
|
65
|
-
const writePromises = locales.map(async (locale) =>
|
|
58
|
+
const writePromises = locales.map(async (locale) => {
|
|
59
|
+
const isEnglish = /^en(?:[-_]|$)/iu.test(locale.code);
|
|
60
|
+
// Use locale suffix for non-English locales when multiple locales exist
|
|
61
|
+
const useLocaleSuffix = locales.length > 1 && !isEnglish;
|
|
62
|
+
return writeLocaleVersion(ctx, contentType, entry, locale.code, getBasePath, useLocaleSuffix);
|
|
63
|
+
});
|
|
66
64
|
await Promise.all(writePromises);
|
|
67
65
|
};
|
|
68
66
|
}
|
|
69
67
|
async function writeLocaleVersion(ctx, contentType, entry, localeCode, getBasePath, useLocaleSuffix) {
|
|
70
68
|
const exported = await exportEntryLocale(contentType.uid, ctx.cs.client, entry.uid, localeCode);
|
|
69
|
+
// Skip writing this locale version if it's a fallback (locale doesn't match requested)
|
|
70
|
+
// This happens when Contentstack returns the default locale content because
|
|
71
|
+
// no localized version exists for the requested locale
|
|
72
|
+
if (useLocaleSuffix &&
|
|
73
|
+
exported.locale &&
|
|
74
|
+
typeof exported.locale === 'string' &&
|
|
75
|
+
exported.locale !== localeCode) {
|
|
76
|
+
// This is a fallback locale, skip writing it
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
71
79
|
const { uid, ...transformed } = transformEntry(ctx, contentType, exported);
|
|
80
|
+
// Preserve the actual locale code from the source stack
|
|
81
|
+
// This ensures we maintain the exact language-region configuration
|
|
82
|
+
if ('locale' in transformed) {
|
|
83
|
+
transformed.locale = localeCode;
|
|
84
|
+
}
|
|
72
85
|
const basePath = getBasePath(entry);
|
|
73
86
|
const filePath = useLocaleSuffix
|
|
74
87
|
? basePath.replace(/\.yaml$/u, `.${localeCode}.yaml`)
|