@arkebcacy/beacon-cli-temp 0.1.6 → 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 +1 -1
- package/dist/cs/labels/Label.d.ts.map +1 -1
- package/dist/cs/labels/Label.js +1 -3
- package/dist/cs/labels/Label.js.map +1 -1
- package/dist/cs/labels/getAllLabels.js +1 -1
- 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/flatten.js +1 -1
- package/dist/dto/labels/flatten.js.map +1 -1
- package/dist/dto/labels/organize.d.ts.map +1 -1
- package/dist/dto/labels/organize.js +15 -14
- package/dist/dto/labels/organize.js.map +1 -1
- 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 +142 -105
- 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 +6 -3
- 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 +2 -6
- package/src/cs/labels/getAllLabels.ts +1 -1
- 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/flatten.test.ts +16 -16
- package/src/dto/labels/flatten.ts +1 -1
- package/src/dto/labels/organize.test.ts +19 -19
- package/src/dto/labels/organize.ts +15 -14
- 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 +204 -109
- package/src/schema/labels/toFilesystem.ts +10 -3
|
@@ -2,7 +2,7 @@ import type OmitIndex from '../../util/OmitIndex.js';
|
|
|
2
2
|
import type { Item } from '../Types.js';
|
|
3
3
|
export default interface Label extends OmitIndex<Item> {
|
|
4
4
|
readonly name: string;
|
|
5
|
-
readonly
|
|
5
|
+
readonly parent: readonly string[];
|
|
6
6
|
}
|
|
7
7
|
export declare function isLabel(o: unknown): o is Label;
|
|
8
8
|
//# sourceMappingURL=Label.d.ts.map
|
|
@@ -1 +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,
|
|
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"}
|
package/dist/cs/labels/Label.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { isItem } from '../Types.js';
|
|
2
2
|
export function isLabel(o) {
|
|
3
|
-
return
|
|
4
|
-
typeof o.name === 'string' &&
|
|
5
|
-
(o.parent_uid === null || typeof o.parent_uid === 'string'));
|
|
3
|
+
return isItem(o) && typeof o.name === 'string' && Array.isArray(o.parent);
|
|
6
4
|
}
|
|
7
5
|
//# sourceMappingURL=Label.js.map
|
|
@@ -1 +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,
|
|
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"]}
|
|
@@ -24,7 +24,7 @@ export default async function getAllLabels(client) {
|
|
|
24
24
|
const label = {
|
|
25
25
|
...raw,
|
|
26
26
|
name: raw.name,
|
|
27
|
-
|
|
27
|
+
parent: Array.isArray(raw.parent) ? raw.parent : [],
|
|
28
28
|
uid: raw.uid,
|
|
29
29
|
};
|
|
30
30
|
if (isLabel(label)) {
|
|
@@ -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,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,
|
|
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"]}
|
|
@@ -1 +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,
|
|
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"]}
|
|
@@ -1 +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,
|
|
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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
// Labels have a tree structure defined by uid/
|
|
1
|
+
// Labels have a tree structure defined by uid/parent array.
|
|
2
2
|
//
|
|
3
|
-
// The API returns a flat array that includes uid/
|
|
4
|
-
//
|
|
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
5
|
//
|
|
6
6
|
// We organize labels into a tree structure for serialization.
|
|
7
7
|
//
|
|
@@ -11,29 +11,30 @@ export default function organize(labels) {
|
|
|
11
11
|
const byUid = new Map();
|
|
12
12
|
const topLevel = [];
|
|
13
13
|
for (const label of labels) {
|
|
14
|
-
const {
|
|
15
|
-
// Preserve all fields except
|
|
14
|
+
const { parent, ...labelWithoutParent } = label;
|
|
15
|
+
// Preserve all fields except parent (which is represented by the tree structure)
|
|
16
16
|
byUid.set(label.uid, {
|
|
17
17
|
...labelWithoutParent,
|
|
18
18
|
name: label.name,
|
|
19
19
|
uid: label.uid,
|
|
20
20
|
});
|
|
21
21
|
}
|
|
22
|
-
for (const
|
|
23
|
-
const
|
|
24
|
-
if (!
|
|
25
|
-
throw new Error(`Label ${uid} not found`);
|
|
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
26
|
}
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
const parentUid = label.parent.length > 0 ? label.parent[0] : null;
|
|
28
|
+
if (!parentUid) {
|
|
29
|
+
topLevel.push(node);
|
|
29
30
|
continue;
|
|
30
31
|
}
|
|
31
|
-
const parent = byUid.get(
|
|
32
|
+
const parent = byUid.get(parentUid);
|
|
32
33
|
if (!parent) {
|
|
33
|
-
const msg = `Orphaned label ${uid} with parent ${
|
|
34
|
+
const msg = `Orphaned label ${label.uid} with parent ${parentUid}`;
|
|
34
35
|
throw new Error(msg);
|
|
35
36
|
}
|
|
36
|
-
(parent.children ??= []).push(
|
|
37
|
+
(parent.children ??= []).push(node);
|
|
37
38
|
}
|
|
38
39
|
return topLevel;
|
|
39
40
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"organize.js","sourceRoot":"","sources":["../../../src/dto/labels/organize.ts"],"names":[],"mappings":"AAGA,
|
|
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":"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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 { 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`)
|
|
@@ -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 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"]}
|
|
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, write English as base file and other locales\n\t\t// with locale suffixes (e.g., Entry.yaml for English, Entry.zh-chs.yaml for Chinese)\n\n\t\t// Write all locale versions in parallel for better performance\n\t\tconst writePromises = locales.map(async (locale) => {\n\t\t\tconst isEnglish = /^en(?:[-_]|$)/iu.test(locale.code);\n\t\t\t// Use locale suffix for non-English locales when multiple locales exist\n\t\t\tconst useLocaleSuffix = locales.length > 1 && !isEnglish;\n\n\t\t\treturn writeLocaleVersion(\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\t// Skip writing this locale version if it's a fallback (locale doesn't match requested)\n\t// This happens when Contentstack returns the default locale content because\n\t// no localized version exists for the requested locale\n\tif (\n\t\tuseLocaleSuffix &&\n\t\texported.locale &&\n\t\ttypeof exported.locale === 'string' &&\n\t\texported.locale !== localeCode\n\t) {\n\t\t// This is a fallback locale, skip writing it\n\t\treturn;\n\t}\n\n\tconst { uid, ...transformed } = transformEntry(ctx, contentType, exported);\n\n\t// Preserve the actual locale code from the source stack\n\t// This ensures we maintain the exact language-region configuration\n\tif ('locale' in transformed) {\n\t\ttransformed.locale = localeCode;\n\t}\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":"labelHelpers.d.ts","sourceRoot":"","sources":["../../../../src/schema/labels/lib/labelHelpers.ts"],"names":[],"mappings":"AAEA,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAyBpD;AAED,wBAAgB,YAAY,CAC3B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAIzB"}
|