@tandem-language-exchange/content-store 1.3.8 → 1.3.9

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.
@@ -14,7 +14,7 @@ import {
14
14
  import {
15
15
  allProjects,
16
16
  defaultLocales
17
- } from "./chunk-GGZIMFPD.js";
17
+ } from "./chunk-DTDEL2NS.js";
18
18
 
19
19
  // src/shared/bundles.ts
20
20
  import fs from "fs/promises";
@@ -296,4 +296,4 @@ export {
296
296
  fetchMergedTranslationBundles,
297
297
  queryCmsBundle
298
298
  };
299
- //# sourceMappingURL=chunk-ZLSV6OOO.js.map
299
+ //# sourceMappingURL=chunk-624IDAD4.js.map
@@ -12,10 +12,10 @@ import {
12
12
  syncCmsContent,
13
13
  syncTranslations,
14
14
  triggerPipelineBuild
15
- } from "./chunk-CAC2DUWN.js";
15
+ } from "./chunk-RAPCYWUA.js";
16
16
  import {
17
17
  allProjects
18
- } from "./chunk-GGZIMFPD.js";
18
+ } from "./chunk-DTDEL2NS.js";
19
19
 
20
20
  // src/server/slack.ts
21
21
  import { App } from "@slack/bolt";
@@ -251,4 +251,4 @@ export {
251
251
  notifySlack,
252
252
  startSlackBot
253
253
  };
254
- //# sourceMappingURL=chunk-LLNHAWCQ.js.map
254
+ //# sourceMappingURL=chunk-D22WOY76.js.map
@@ -13,9 +13,6 @@ var localeMapping = {
13
13
  "zh-hans": "zh-Hans-CN",
14
14
  "zh-hant": "zh-TW"
15
15
  },
16
- invites: {
17
- "prs": "fa"
18
- },
19
16
  website: {
20
17
  "prs": "fa"
21
18
  }
@@ -26,7 +23,8 @@ var allProjects = {
26
23
  resource: "main",
27
24
  fileName: "Website.[locale].json",
28
25
  type: "json",
29
- locales: ["de", "en", "es", "fr", "it", "ja", "ko", "pt-br", "ru", "zh-hans", "zh-hant"]
26
+ locales: ["ar", "de", "en", "es", "fr", "it", "ja", "ko", "pt-br", "prs", "ps", "ru", "zh-hans", "zh-hant"],
27
+ localeMapping: localeMapping.website
30
28
  }
31
29
  ],
32
30
  "tandem-(website)": [
@@ -244,7 +242,7 @@ var allProjects = {
244
242
  fileName: "[locale].json",
245
243
  type: "json",
246
244
  locales: ["ar", "de", "en", "es", "fr", "it", "ja", "ko", "prs", "ps", "pt-br", "ru", "uk", "zh-hans", "zh-hant"],
247
- localeMapping: localeMapping.invites
245
+ localeMapping: localeMapping.website
248
246
  }
249
247
  ]
250
248
  };
@@ -253,4 +251,4 @@ export {
253
251
  defaultLocales,
254
252
  allProjects
255
253
  };
256
- //# sourceMappingURL=chunk-GGZIMFPD.js.map
254
+ //# sourceMappingURL=chunk-DTDEL2NS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/shared/lingohub.ts"],"sourcesContent":["export const defaultLocales = ['de', 'en', 'es', 'fr', 'it', 'ja', 'ko', 'pt-br', 'ru', 'th', 'uk', 'vi', 'zh-hans', 'zh-hant'];\n\nconst localeMapping = {\n ios: {\n 'pt-br': 'pt',\n 'zh-hans': 'zh-Hans',\n 'zh-hant': 'zh-Hant',\n },\n android: {\n 'pt-br': 'pt',\n 'zh-hans': 'zh-Hans-CN',\n 'zh-hant': 'zh-TW',\n },\n website: {\n 'prs': 'fa',\n },\n};\n\nexport type LingohubResource = {\n resource: string,\n fileName: string;\n type: 'json'|'strings'|'xml';\n localeMapping?: Record<string, string>;\n locales?: string[]\n}\n\nexport const allProjects: Record<string, LingohubResource[]> = {\n 'tandem-(new-website)': [\n {\n resource: 'main',\n fileName: 'Website.[locale].json',\n type: 'json',\n locales: ['ar','de', 'en', 'es', 'fr', 'it', 'ja', 'ko', 'pt-br', 'prs', 'ps', 'ru', 'zh-hans', 'zh-hant'],\n localeMapping: localeMapping.website,\n }\n ],\n 'tandem-(website)': [\n {\n resource: 'main',\n fileName: '[locale].json',\n type: 'json',\n locales: ['ar', 'de', 'en', 'es', 'fr', 'it', 'ja', 'ko', 'pt-br', 'prs', 'ps', 'ru', 'th', 'uk', 'vi', 'zh-hans', 'zh-hant'],\n localeMapping: localeMapping.website,\n },\n {\n resource: 'ai',\n fileName: 'AI.[locale].json',\n type: 'json'\n },\n {\n resource: 'languages',\n fileName: 'languages.[locale].json',\n type: 'json'\n }\n ],\n 'tandem': [\n {\n resource: 'infoplist',\n fileName: 'InfoPlist.[locale].strings',\n type: 'strings',\n localeMapping: localeMapping.ios,\n },\n {\n resource: 'localizable',\n fileName: 'Localizable.[locale].strings',\n type: 'strings',\n localeMapping: localeMapping.ios,\n },\n {\n resource: 'ipad',\n fileName: 'Main_iPad.[locale].strings',\n type: 'strings',\n localeMapping: localeMapping.ios,\n },\n {\n resource: 'main',\n fileName: 'Main.[locale].strings',\n type: 'strings',\n localeMapping: localeMapping.ios,\n }\n ],\n 'tandem-(android)': [\n {\n resource: 'accessibility',\n fileName: 'accessibility_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'call',\n fileName: 'call_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'cert',\n fileName: 'cert_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'chat',\n fileName: 'chat_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'checklist',\n fileName: 'checklist_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'clubs',\n fileName: 'clubs_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'common',\n fileName: 'common_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'community',\n fileName: 'community_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'correction',\n fileName: 'correction_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'country_names',\n fileName: 'country_names.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'emoji',\n fileName: 'emoji_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'errors',\n fileName: 'errors.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'expressions',\n fileName: 'expressions_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'gif',\n fileName: 'gif_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'guidelines',\n fileName: 'guidelines_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'lanuguages',\n fileName: 'languages_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'localizable',\n fileName: 'localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'localizable2',\n fileName: 'localizable2.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'login',\n fileName: 'login_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'myprofile',\n fileName: 'myprofile_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'onb',\n fileName: 'onb_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'parties',\n fileName: 'parties_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'pro',\n fileName: 'pro_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'pro_screen',\n fileName: 'pro_screen_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'push_notification',\n fileName: 'push_notification_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'reporting',\n fileName: 'reporting_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'translation',\n fileName: 'translation_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n }\n\n ],\n 'tandem-(web-invites)': [\n {\n resource: 'main',\n fileName: '[locale].json',\n type: 'json',\n locales: ['ar', 'de', 'en', 'es', 'fr', 'it', 'ja', 'ko', 'prs', 'ps', 'pt-br', 'ru', 'uk', 'zh-hans', 'zh-hant'],\n localeMapping: localeMapping.website,\n }\n ]\n};\n"],"mappings":"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","names":[]}
@@ -11,7 +11,7 @@ import {
11
11
  import {
12
12
  allProjects,
13
13
  defaultLocales
14
- } from "./chunk-GGZIMFPD.js";
14
+ } from "./chunk-DTDEL2NS.js";
15
15
 
16
16
  // src/server/adapters/azure/types.ts
17
17
  var AZURE_DEVOPS_PROJECT_KEYS = [
@@ -1014,4 +1014,4 @@ export {
1014
1014
  syncCmsContent,
1015
1015
  syncTranslations
1016
1016
  };
1017
- //# sourceMappingURL=chunk-CAC2DUWN.js.map
1017
+ //# sourceMappingURL=chunk-RAPCYWUA.js.map
@@ -4,13 +4,13 @@ import {
4
4
  } from "../chunk-SDEERVPV.js";
5
5
  import {
6
6
  fetchCmsBundles
7
- } from "../chunk-ZLSV6OOO.js";
7
+ } from "../chunk-624IDAD4.js";
8
8
  import "../chunk-EQ3DSPTJ.js";
9
9
  import "../chunk-OCAIIQZW.js";
10
10
  import {
11
11
  ContentStore
12
12
  } from "../chunk-K4RASQFK.js";
13
- import "../chunk-GGZIMFPD.js";
13
+ import "../chunk-DTDEL2NS.js";
14
14
 
15
15
  // src/client/fetch-content-bundles.ts
16
16
  import { Command } from "commander";
@@ -4,7 +4,7 @@ import {
4
4
  } from "../chunk-SDEERVPV.js";
5
5
  import {
6
6
  fetchMergedTranslationBundles
7
- } from "../chunk-ZLSV6OOO.js";
7
+ } from "../chunk-624IDAD4.js";
8
8
  import "../chunk-EQ3DSPTJ.js";
9
9
  import "../chunk-OCAIIQZW.js";
10
10
  import {
@@ -12,7 +12,7 @@ import {
12
12
  } from "../chunk-K4RASQFK.js";
13
13
  import {
14
14
  allProjects
15
- } from "../chunk-GGZIMFPD.js";
15
+ } from "../chunk-DTDEL2NS.js";
16
16
 
17
17
  // src/client/fetch-merged-translation-bundles.ts
18
18
  import fs from "fs";
@@ -4,7 +4,7 @@ import {
4
4
  } from "../chunk-SDEERVPV.js";
5
5
  import {
6
6
  fetchTranslationBundles
7
- } from "../chunk-ZLSV6OOO.js";
7
+ } from "../chunk-624IDAD4.js";
8
8
  import "../chunk-EQ3DSPTJ.js";
9
9
  import "../chunk-OCAIIQZW.js";
10
10
  import {
@@ -12,7 +12,7 @@ import {
12
12
  } from "../chunk-K4RASQFK.js";
13
13
  import {
14
14
  allProjects
15
- } from "../chunk-GGZIMFPD.js";
15
+ } from "../chunk-DTDEL2NS.js";
16
16
 
17
17
  // src/client/fetch-translation-bundles.ts
18
18
  import fs from "fs";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  allProjects
4
- } from "../chunk-GGZIMFPD.js";
4
+ } from "../chunk-DTDEL2NS.js";
5
5
 
6
6
  // src/client/list-projects.ts
7
7
  import { Command } from "commander";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  allProjects
4
- } from "../chunk-GGZIMFPD.js";
4
+ } from "../chunk-DTDEL2NS.js";
5
5
 
6
6
  // src/client/list-resources.ts
7
7
  import { createInterface } from "readline/promises";
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  queryCmsBundle
4
- } from "../chunk-ZLSV6OOO.js";
4
+ } from "../chunk-624IDAD4.js";
5
5
  import "../chunk-EQ3DSPTJ.js";
6
6
  import "../chunk-K4RASQFK.js";
7
- import "../chunk-GGZIMFPD.js";
7
+ import "../chunk-DTDEL2NS.js";
8
8
 
9
9
  // src/client/query-cms.ts
10
10
  import { Command } from "commander";
package/dist/node.js CHANGED
@@ -189,9 +189,6 @@ var localeMapping = {
189
189
  "zh-hans": "zh-Hans-CN",
190
190
  "zh-hant": "zh-TW"
191
191
  },
192
- invites: {
193
- "prs": "fa"
194
- },
195
192
  website: {
196
193
  "prs": "fa"
197
194
  }
@@ -202,7 +199,8 @@ var allProjects = {
202
199
  resource: "main",
203
200
  fileName: "Website.[locale].json",
204
201
  type: "json",
205
- locales: ["de", "en", "es", "fr", "it", "ja", "ko", "pt-br", "ru", "zh-hans", "zh-hant"]
202
+ locales: ["ar", "de", "en", "es", "fr", "it", "ja", "ko", "pt-br", "prs", "ps", "ru", "zh-hans", "zh-hant"],
203
+ localeMapping: localeMapping.website
206
204
  }
207
205
  ],
208
206
  "tandem-(website)": [
@@ -420,7 +418,7 @@ var allProjects = {
420
418
  fileName: "[locale].json",
421
419
  type: "json",
422
420
  locales: ["ar", "de", "en", "es", "fr", "it", "ja", "ko", "prs", "ps", "pt-br", "ru", "uk", "zh-hans", "zh-hant"],
423
- localeMapping: localeMapping.invites
421
+ localeMapping: localeMapping.website
424
422
  }
425
423
  ]
426
424
  };
package/dist/node.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/shared/s3.ts","../src/shared/bundles.ts","../src/shared/s3-retry.ts","../src/shared/trimDepth.ts","../src/shared/lingohub.ts","../src/shared/translationResource.ts","../src/shared/utils.ts","../src/shared/content-refresh.ts","../src/sdk/client.ts","../src/sdk/next-content-refresh.ts"],"sourcesContent":["import {\n S3Client,\n PutObjectCommand,\n GetObjectCommand,\n} from '@aws-sdk/client-s3';\nimport type { S3Config } from './types';\n\nexport class ContentStore {\n private client: S3Client;\n private bucket: string;\n\n constructor(cfg: S3Config) {\n this.client = new S3Client({\n region: cfg.region,\n credentials: {\n accessKeyId: cfg.accessKeyId,\n secretAccessKey: cfg.secretAccessKey,\n },\n });\n this.bucket = cfg.bucket;\n }\n\n async upload(key: string, data: unknown): Promise<string> {\n await this.client.send(\n new PutObjectCommand({\n Bucket: this.bucket,\n Key: key,\n Body: JSON.stringify(data, null, 2),\n ContentType: 'application/json',\n }),\n );\n return key;\n }\n\n /** Raw UTF-8 body (e.g. Lingohub file bytes as text). */\n async uploadRaw(\n key: string,\n body: string,\n contentType: string,\n ): Promise<string> {\n await this.client.send(\n new PutObjectCommand({\n Bucket: this.bucket,\n Key: key,\n Body: body,\n ContentType: contentType,\n }),\n );\n return key;\n }\n\n async download(key: string): Promise<unknown> {\n const response = await this.client.send(\n new GetObjectCommand({ Bucket: this.bucket, Key: key }),\n );\n const body = await response.Body?.transformToString();\n if (!body) throw new Error(`Empty response for key: ${key}`);\n return JSON.parse(body);\n }\n\n /** Raw UTF-8 body from S3 (no JSON.parse). */\n async downloadRaw(key: string): Promise<string> {\n const response = await this.client.send(\n new GetObjectCommand({ Bucket: this.bucket, Key: key }),\n );\n const body = await response.Body?.transformToString();\n if (!body) throw new Error(`Empty response for key: ${key}`);\n return body;\n }\n}\n\n/** {cms}-{contentType}.json (always points at the latest version) */\nexport const buildCmsObjectKey = (cms: string, contentType: string): string => {\n return `${cms}-${contentType}.json`;\n}\n\nexport const buildTranslationObjectKey = (project:string, fileName: string, locale: string): string => {\n return `lingohub-${project}.${fileName.replaceAll('[locale]', locale)}`;\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { CMSProvider } from './types';\nimport { buildCmsObjectKey, buildTranslationObjectKey, ContentStore } from './s3';\nimport {\n downloadRawWithRetry,\n downloadWithRetry,\n getDefaultS3RetryConfig,\n type S3RetryConfig,\n} from './s3-retry';\nimport { trimDepth } from './trimDepth';\nimport {\n allProjects,\n defaultLocales,\n type LingohubResource,\n} from './lingohub';\n\n/**\n * Resolves the effective locale list for a single resource.\n *\n * - No explicit request + resource has own locales → resource.locales (full)\n * - Explicit request + resource has own locales → intersection (skip unsupported)\n * - No explicit request + no resource locales → defaultLocales\n * - Explicit request + no resource locales → requested locales\n */\nfunction resolveResourceLocales(\n resource: LingohubResource,\n requestedLocales: string[] | null,\n): string[] {\n if (resource.locales) {\n return requestedLocales\n ? requestedLocales.filter((l) => resource.locales!.includes(l))\n : resource.locales;\n }\n return requestedLocales ?? defaultLocales;\n}\nimport {\n parseTranslationResourceRaw,\n toFlatStringMap,\n translationJsonOutputPath,\n} from './translationResource';\n\nexport { trimDepth } from './trimDepth';\nexport type { S3RetryConfig } from './s3-retry';\nexport { getDefaultS3RetryConfig } from './s3-retry';\n\n/**\n * Expand dotted keys into a nested object structure.\n * e.g. `{ \"General.tryAgain\": \"Try Again\" }` → `{ \"General\": { \"tryAgain\": \"Try Again\" } }`\n */\nexport function nestKeys(flat: unknown): unknown {\n if (typeof flat !== 'object' || flat === null || Array.isArray(flat)) return flat;\n const src = flat as Record<string, unknown>;\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(src)) {\n const parts = key.split('.');\n let cur = result;\n for (let i = 0; i < parts.length - 1; i++) {\n const seg = parts[i]!;\n if (!(seg in cur) || typeof cur[seg] !== 'object' || cur[seg] === null) {\n cur[seg] = {};\n }\n cur = cur[seg] as Record<string, unknown>;\n }\n cur[parts[parts.length - 1]!] = value;\n }\n return result;\n}\n\nexport interface CmsBundleInfo {\n [key: string]: string;\n}\n\nexport interface TranslationBundleInfo {\n [key: string] : Record<string, string>;\n}\n\nexport interface BundleItem {\n [key: string]: any; // eslint-disable-line @typescript-eslint/no-explicit-any\n}\n\nexport interface FetchCmsBundlesOptions {\n cms: CMSProvider;\n contentTypes: string[];\n /** S3 GET retry; defaults via {@link getDefaultS3RetryConfig}. */\n retry?: S3RetryConfig;\n}\n\n/**\n * Config-file-friendly shape used by `fetchTranslationBundles` and the CLI.\n *\n * ```json\n * {\n * \"projects\": {\n * \"tandem\": [],\n * \"tandem-(website)\": [\"main\", \"ai\"]\n * },\n * \"locales\": [\"en\", \"de\", \"it\"]\n * }\n * ```\n *\n * `projects` maps each Lingohub project id to an array of resource keys.\n * An empty array means **all** resources for that project.\n * `locales` is optional — omit (or pass `[]`) to fetch the default locale set.\n */\nexport interface TranslationFilterConfig {\n projects: Record<string, string[]>;\n locales?: string[];\n /** Output key structure. `\"flat\"` (default) keeps dotted keys as-is; `\"nested\"` expands dots into nested objects. */\n structure?: 'flat' | 'nested';\n}\n\nexport interface FetchTranslationBundlesOptions extends TranslationFilterConfig {\n /** S3 GET retry; defaults via {@link getDefaultS3RetryConfig}. */\n retry?: S3RetryConfig;\n}\n\n/** One merged JSON file per catalog locale (`en.json`, …). Same options as {@link FetchTranslationBundlesOptions}. */\nexport type FetchMergedTranslationBundlesOptions = FetchTranslationBundlesOptions;\n\nexport interface QueryOptions {\n /**\n * Filter items by matching property values (exact equality, or array for IN).\n * Keys may use dot notation for nested paths, e.g. `{ 'meta._id': 'abc' }` matches\n * `item.meta._id`.\n *\n * Contentful-style operators on the path (before `[`):\n * - `{ 'field[exists]': true }` — field is present and non-empty (not null, undefined,\n * `''`, `[]`, or `{}`).\n * - `{ 'field[exists]': false }` — field is missing or empty (same emptiness rules).\n * Nested paths work, e.g. `{ 'blocks.hero[exists]': false }`.\n */\n fields?: Record<string, unknown>;\n /**\n * Properties to include in each result object. Omit to return all properties.\n * Keys may use dot notation; nested segments become nested objects in the result,\n * e.g. `['slug', 'meta._updatedAt']` → `{ slug, meta: { _updatedAt } }`.\n */\n select?: string[];\n /** Maximum number of items to return. */\n limit?: number;\n /**\n * How many levels deep to return.\n * - 1 = the item's own scalar properties only; nested objects/refs are nulled.\n * - 2 = the item including its direct references; refs inside those are nulled.\n * - 3 = three levels deep, and so on.\n * - Omit to return the full depth.\n */\n include?: number;\n}\n\n/** Read a value at a dotted path; returns whether every segment existed. */\nfunction getAtPath(\n obj: unknown,\n dottedPath: string,\n): { found: true; value: unknown } | { found: false } {\n const parts = dottedPath.split('.').filter((p) => p.length > 0);\n if (parts.length === 0) return { found: false };\n\n let cur: unknown = obj;\n for (const p of parts) {\n if (cur === null || typeof cur !== 'object' || Array.isArray(cur)) {\n return { found: false };\n }\n const rec = cur as Record<string, unknown>;\n if (!(p in rec)) return { found: false };\n cur = rec[p];\n }\n return { found: true, value: cur };\n}\n\nconst FIELD_OP_KEY = /^(.+)\\[([^\\]]+)]$/;\n\nfunction parseFieldKey(key: string): { path: string; operator?: string } {\n const m = FIELD_OP_KEY.exec(key);\n if (!m) return { path: key };\n return { path: m[1]!, operator: m[2]! };\n}\n\n/** True when a bundle value counts as “no content” (aligned with typical CMS “empty”). */\nfunction isEmptyValue(value: unknown): boolean {\n if (value === null || value === undefined) return true;\n if (value === '') return true;\n if (Array.isArray(value) && value.length === 0) {\n return true;\n }\n return typeof value === 'object' &&\n !Array.isArray(value) &&\n Object.keys(value).length === 0;\n\n}\n\nfunction matchesFieldFilter(\n item: BundleItem,\n key: string,\n expected: unknown,\n): boolean {\n const { path, operator } = parseFieldKey(key);\n const at = getAtPath(item, path);\n\n if (operator === 'exists') {\n if (expected !== true && expected !== false) return false;\n const empty = !at.found || isEmptyValue(at.value);\n return !expected ? empty : !empty;\n }\n\n const actual = at.found ? at.value : undefined;\n if (Array.isArray(expected)) return expected.includes(actual);\n return actual === expected;\n}\n\n/** Set `value` on `target` at a dotted path, creating plain objects as needed. */\nfunction setNestedAt(\n target: Record<string, unknown>,\n dottedPath: string,\n value: unknown,\n): void {\n const parts = dottedPath.split('.').filter((p) => p.length > 0);\n if (parts.length === 0) return;\n\n if (parts.length === 1) {\n target[parts[0]!] = value;\n return;\n }\n\n const head = parts[0]!;\n const rest = parts.slice(1).join('.');\n let nested = target[head];\n if (\n nested === null ||\n typeof nested !== 'object' ||\n Array.isArray(nested)\n ) {\n nested = {};\n target[head] = nested;\n }\n setNestedAt(nested as Record<string, unknown>, rest, value);\n}\n\n/**\n * Downloads the latest CMS bundles from S3 and writes them as JSON files to `outputDir`.\n *\n * @returns A map of contentType to absolute file path.\n */\nexport async function fetchCmsBundles(\n store: ContentStore,\n outputDir: string,\n options: FetchCmsBundlesOptions,\n): Promise<Record<string, string>> {\n const { cms, contentTypes } = options;\n const retry = options.retry ?? getDefaultS3RetryConfig();\n await fs.mkdir(outputDir, { recursive: true });\n\n const result: CmsBundleInfo = {};\n\n await Promise.all(\n contentTypes.map(async (contentType) => {\n const key = buildCmsObjectKey(cms, contentType);\n const data = await downloadWithRetry(store, key, retry);\n const filePath = path.resolve(outputDir, key);\n await fs.writeFile(filePath, JSON.stringify(data, null, 2), 'utf-8');\n result[contentType] = filePath;\n }),\n );\n\n return result;\n}\n\n/**\n * Downloads the latest translation bundles from S3 and writes them as JSON files to `outputDir`.\n *\n * @returns For each project, a map of S3 object key to absolute file path on disk.\n */\n/** Filter a project's full resource list by the resource keys specified in the config. */\nfunction filterResources(\n projectResources: LingohubResource[],\n resourceFilter: string[],\n): LingohubResource[] {\n if (resourceFilter.length === 0) return projectResources;\n return projectResources.filter((r) => resourceFilter.includes(r.resource));\n}\n\nexport async function fetchTranslationBundles(\n store: ContentStore,\n outputDir: string,\n options: FetchTranslationBundlesOptions,\n): Promise<TranslationBundleInfo> {\n const { projects, locales, structure } = options;\n const nested = structure === 'nested';\n const retry = options.retry ?? getDefaultS3RetryConfig();\n await fs.mkdir(outputDir, { recursive: true });\n\n const result: TranslationBundleInfo = {};\n const requestedLocales = locales && locales.length ? locales : null;\n\n await Promise.all(\n Object.entries(projects).map(async ([project, resourceFilter]) => {\n const allResources = allProjects[project];\n if (!allResources?.length) return;\n\n const resources = filterResources(allResources, resourceFilter);\n if (!resources.length) return;\n\n const resourceTasks: { objectKey: string; resource: LingohubResource }[] =\n [];\n for (const resource of resources) {\n const resourceLocales = resolveResourceLocales(resource, requestedLocales);\n for (const loc of resourceLocales) {\n const locale =\n resource.localeMapping && resource.localeMapping[loc]\n ? resource.localeMapping[loc]\n : loc;\n const objectKey = buildTranslationObjectKey(\n project,\n resource.fileName,\n locale,\n );\n resourceTasks.push({ objectKey, resource });\n }\n }\n\n await Promise.all(\n resourceTasks.map(async ({ objectKey, resource }) => {\n const raw = await downloadRawWithRetry(store, objectKey, retry);\n const parsed = parseTranslationResourceRaw(raw, resource);\n const output = nested ? nestKeys(parsed) : parsed;\n const filePath = translationJsonOutputPath(outputDir, objectKey);\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n await fs.writeFile(\n filePath,\n JSON.stringify(output, null, 2),\n 'utf-8',\n );\n if (!result[project]) {\n result[project] = {};\n }\n result[project][objectKey] = filePath;\n }),\n );\n }),\n );\n\n return result;\n}\n\n/**\n * Downloads translation bundles from S3, parses each raw Lingohub file, and merges all\n * key/value pairs per **catalog** locale into a single JSON file (e.g. `en.json`).\n * Duplicate keys across resources or projects: **last write wins** (iteration order:\n * projects → resources → locales).\n *\n * @returns Map of locale code to absolute path of the merged `{locale}.json` file.\n */\nexport async function fetchMergedTranslationBundles(\n store: ContentStore,\n outputDir: string,\n options: FetchMergedTranslationBundlesOptions,\n): Promise<Record<string, string>> {\n const { projects, locales, structure } = options;\n const nested = structure === 'nested';\n const retry = options.retry ?? getDefaultS3RetryConfig();\n await fs.mkdir(outputDir, { recursive: true });\n\n const requestedLocales = locales && locales.length ? locales : null;\n\n type Task = {\n catalogLocale: string;\n objectKey: string;\n resource: LingohubResource;\n };\n const tasks: Task[] = [];\n const allLocales = new Set<string>();\n\n for (const [project, resourceFilter] of Object.entries(projects)) {\n const allResources = allProjects[project];\n if (!allResources?.length) continue;\n\n const resources = filterResources(allResources, resourceFilter);\n if (!resources.length) continue;\n\n for (const resource of resources) {\n const resourceLocales = resolveResourceLocales(resource, requestedLocales);\n for (const loc of resourceLocales) {\n allLocales.add(loc);\n const mappedLocale =\n resource.localeMapping && resource.localeMapping[loc]\n ? resource.localeMapping[loc]\n : loc;\n const objectKey = buildTranslationObjectKey(\n project,\n resource.fileName,\n mappedLocale,\n );\n tasks.push({ catalogLocale: loc, objectKey, resource });\n }\n }\n }\n\n const results = await Promise.all(\n tasks.map(async ({ catalogLocale, objectKey, resource }) => {\n const raw = await downloadRawWithRetry(store, objectKey, retry);\n const parsed = parseTranslationResourceRaw(raw, resource);\n const stringMap = toFlatStringMap(parsed);\n return { catalogLocale, stringMap };\n }),\n );\n\n const merged: Record<string, Record<string, string>> = {};\n for (const loc of allLocales) {\n merged[loc] = {};\n }\n for (const { catalogLocale, stringMap } of results) {\n Object.assign(merged[catalogLocale]!, stringMap);\n }\n\n const out: Record<string, string> = {};\n for (const loc of allLocales) {\n const filePath = path.resolve(outputDir, `${loc}.json`);\n const output = nested ? nestKeys(merged[loc]) : merged[loc];\n await fs.writeFile(\n filePath,\n JSON.stringify(output, null, 2),\n 'utf-8',\n );\n out[loc] = filePath;\n }\n\n return out;\n}\n\n/**\n * Queries a previously fetched bundle from the local filesystem.\n */\nexport async function queryCmsBundle(\n outputDir: string,\n cms: CMSProvider,\n contentType: string,\n options: QueryOptions = {},\n): Promise<unknown[]> {\n const filePath = path.resolve(\n outputDir,\n `${cms}-${contentType}.json`,\n );\n const raw = await fs.readFile(filePath, 'utf-8');\n let items:BundleItem[] = JSON.parse(raw) as Record<string, unknown>[];\n\n if (options.fields) {\n const filters = options.fields;\n items = items.filter((item) =>\n Object.entries(filters).every(([key, expected]) =>\n matchesFieldFilter(item, key, expected),\n ),\n );\n }\n\n if (options.limit !== undefined && options.limit > 0) {\n items = items.slice(0, options.limit);\n }\n\n if (options.include !== undefined) {\n items = items.map(\n (item) => trimDepth(item, options.include!) as Record<string, unknown>,\n );\n }\n\n if (options.select?.length) {\n const keys = options.select;\n items = items.map((item) => {\n const picked: Record<string, unknown> = {};\n for (const k of keys) {\n const at = getAtPath(item, k);\n if (at.found) setNestedAt(picked, k, at.value);\n }\n return picked;\n });\n }\n\n return items;\n}\n","import type { ContentStore } from './s3';\n\n/** Retry/backoff for S3 reads (aligned with CMS `RetryConfig` shape). */\nexport interface S3RetryConfig {\n maxRetries: number;\n baseDelayMs: number;\n maxDelayMs: number;\n}\n\nfunction computeDelay(\n attempt: number,\n baseDelayMs: number,\n maxDelayMs: number,\n): number {\n const exponential = baseDelayMs * Math.pow(2, attempt);\n const jitter = Math.random() * baseDelayMs;\n return Math.min(exponential + jitter, maxDelayMs);\n}\n\n/**\n * Default S3 download retry policy from env.\n * `S3_RETRY_*` overrides `RETRY_*` when set.\n */\nexport function getDefaultS3RetryConfig(): S3RetryConfig {\n return {\n maxRetries: parseInt(\n process.env.S3_RETRY_MAX_RETRIES ??\n process.env.RETRY_MAX_RETRIES ??\n '5',\n 10,\n ),\n baseDelayMs: parseInt(\n process.env.S3_RETRY_BASE_DELAY_MS ??\n process.env.RETRY_BASE_DELAY_MS ??\n '1000',\n 10,\n ),\n maxDelayMs: parseInt(\n process.env.S3_RETRY_MAX_DELAY_MS ??\n process.env.RETRY_MAX_DELAY_MS ??\n '60000',\n 10,\n ),\n };\n}\n\n/**\n * True when a failed S3 GET may succeed after a short wait (503 Slow Down,\n * transient network, throttling). Never true for definitive client errors (404, etc.).\n */\nexport function isRetryableS3DownloadError(err: unknown): boolean {\n if (err === null || err === undefined) return false;\n\n if (typeof err === 'object') {\n const e = err as {\n name?: string;\n Code?: string;\n $metadata?: { httpStatusCode?: number };\n };\n const status = e.$metadata?.httpStatusCode;\n if (status === 404 || status === 403 || status === 401 || status === 400) {\n return false;\n }\n if (\n status !== undefined &&\n (status === 408 ||\n status === 429 ||\n status === 500 ||\n status === 502 ||\n status === 503 ||\n status === 504)\n ) {\n return true;\n }\n\n const name = e.name ?? '';\n const code = e.Code ?? '';\n if (\n /SlowDown|Throttl|Timeout|TooManyRequests|ServiceUnavailable|InternalError/i.test(\n name,\n ) ||\n /SlowDown|Throttl/i.test(code)\n ) {\n return true;\n }\n }\n\n if (err instanceof Error) {\n const m = err.message;\n if (\n /ECONNRESET|ETIMEDOUT|EPIPE|ECONNREFUSED|socket hang up|getaddrinfo/i.test(\n m,\n )\n ) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Runs `fn` with retries when `isRetryableS3DownloadError` applies; otherwise throws immediately.\n */\nexport async function withS3Retry<T>(\n fn: () => Promise<T>,\n { maxRetries, baseDelayMs, maxDelayMs }: S3RetryConfig,\n): Promise<T> {\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await fn();\n } catch (err) {\n if (!isRetryableS3DownloadError(err)) {\n throw err;\n }\n if (attempt === maxRetries) {\n throw err;\n }\n\n const delay = computeDelay(attempt, baseDelayMs, maxDelayMs);\n console.warn(\n ` S3 request failed (attempt ${attempt + 1}/${maxRetries + 1}): ${\n err instanceof Error ? err.message : String(err)\n }. Retrying in ${Math.round(delay)}ms…`,\n );\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n\n throw new Error('withS3Retry: unreachable');\n}\n\nexport async function downloadWithRetry(\n store: ContentStore,\n key: string,\n cfg: S3RetryConfig,\n): Promise<unknown> {\n return withS3Retry(() => store.download(key), cfg);\n}\n\nexport async function downloadRawWithRetry(\n store: ContentStore,\n key: string,\n cfg: S3RetryConfig,\n): Promise<string> {\n return withS3Retry(() => store.downloadRaw(key), cfg);\n}\n","/**\n * Trims nested object depth.\n *\n * `remaining` represents how many levels the current object is allowed.\n * - Scalar properties are always kept.\n * - Nested objects / arrays-of-objects consume one level. When `remaining`\n * drops to 1 they are replaced with `null` (no budget left for refs).\n */\nexport function trimDepth(value: unknown, remaining: number): unknown {\n if (value === null || value === undefined || typeof value !== 'object') {\n return value;\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => trimDepth(item, remaining));\n }\n\n const obj = value as Record<string, unknown>;\n const result: Record<string, unknown> = {};\n\n for (const [k, v] of Object.entries(obj)) {\n if (v === null || v === undefined || typeof v !== 'object') {\n result[k] = v;\n } else if (remaining <= 1) {\n result[k] = null;\n } else if (Array.isArray(v)) {\n result[k] = v.map((item) => {\n if (item !== null && typeof item === 'object' && !Array.isArray(item)) {\n return trimDepth(item, remaining - 1);\n }\n return item;\n });\n } else {\n result[k] = trimDepth(v, remaining - 1);\n }\n }\n\n return result;\n}\n","export const defaultLocales = ['de', 'en', 'es', 'fr', 'it', 'ja', 'ko', 'pt-br', 'ru', 'th', 'uk', 'vi', 'zh-hans', 'zh-hant'];\n\nconst localeMapping = {\n ios: {\n 'pt-br': 'pt',\n 'zh-hans': 'zh-Hans',\n 'zh-hant': 'zh-Hant',\n },\n android: {\n 'pt-br': 'pt',\n 'zh-hans': 'zh-Hans-CN',\n 'zh-hant': 'zh-TW',\n },\n invites: {\n 'prs': 'fa',\n },\n website: {\n 'prs': 'fa',\n },\n};\n\nexport type LingohubResource = {\n resource: string,\n fileName: string;\n type: 'json'|'strings'|'xml';\n localeMapping?: Record<string, string>;\n locales?: string[]\n}\n\nexport const allProjects: Record<string, LingohubResource[]> = {\n 'tandem-(new-website)': [\n {\n resource: 'main',\n fileName: 'Website.[locale].json',\n type: 'json',\n locales: ['de', 'en', 'es', 'fr', 'it', 'ja', 'ko', 'pt-br', 'ru', 'zh-hans', 'zh-hant']\n }\n ],\n 'tandem-(website)': [\n {\n resource: 'main',\n fileName: '[locale].json',\n type: 'json',\n locales: ['ar', 'de', 'en', 'es', 'fr', 'it', 'ja', 'ko', 'pt-br', 'prs', 'ps', 'ru', 'th', 'uk', 'vi', 'zh-hans', 'zh-hant'],\n localeMapping: localeMapping.website,\n },\n {\n resource: 'ai',\n fileName: 'AI.[locale].json',\n type: 'json'\n },\n {\n resource: 'languages',\n fileName: 'languages.[locale].json',\n type: 'json'\n }\n ],\n 'tandem': [\n {\n resource: 'infoplist',\n fileName: 'InfoPlist.[locale].strings',\n type: 'strings',\n localeMapping: localeMapping.ios,\n },\n {\n resource: 'localizable',\n fileName: 'Localizable.[locale].strings',\n type: 'strings',\n localeMapping: localeMapping.ios,\n },\n {\n resource: 'ipad',\n fileName: 'Main_iPad.[locale].strings',\n type: 'strings',\n localeMapping: localeMapping.ios,\n },\n {\n resource: 'main',\n fileName: 'Main.[locale].strings',\n type: 'strings',\n localeMapping: localeMapping.ios,\n }\n ],\n 'tandem-(android)': [\n {\n resource: 'accessibility',\n fileName: 'accessibility_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'call',\n fileName: 'call_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'cert',\n fileName: 'cert_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'chat',\n fileName: 'chat_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'checklist',\n fileName: 'checklist_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'clubs',\n fileName: 'clubs_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'common',\n fileName: 'common_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'community',\n fileName: 'community_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'correction',\n fileName: 'correction_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'country_names',\n fileName: 'country_names.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'emoji',\n fileName: 'emoji_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'errors',\n fileName: 'errors.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'expressions',\n fileName: 'expressions_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'gif',\n fileName: 'gif_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'guidelines',\n fileName: 'guidelines_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'lanuguages',\n fileName: 'languages_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'localizable',\n fileName: 'localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'localizable2',\n fileName: 'localizable2.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'login',\n fileName: 'login_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'myprofile',\n fileName: 'myprofile_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'onb',\n fileName: 'onb_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'parties',\n fileName: 'parties_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'pro',\n fileName: 'pro_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'pro_screen',\n fileName: 'pro_screen_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'push_notification',\n fileName: 'push_notification_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'reporting',\n fileName: 'reporting_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'translation',\n fileName: 'translation_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n }\n\n ],\n 'tandem-(web-invites)': [\n {\n resource: 'main',\n fileName: '[locale].json',\n type: 'json',\n locales: ['ar', 'de', 'en', 'es', 'fr', 'it', 'ja', 'ko', 'prs', 'ps', 'pt-br', 'ru', 'uk', 'zh-hans', 'zh-hant'],\n localeMapping: localeMapping.invites,\n }\n ]\n};\n","import path from 'node:path';\nimport { convertXMLToJS, parseIOSStrings, transformObjectToFlat } from './utils';\nimport type { LingohubResource } from './lingohub';\n\n/** Content-Type for raw Lingohub bodies stored in S3. */\nexport function contentTypeForTranslationKey(objectKey: string): string {\n if (objectKey.endsWith('.json')) return 'application/json; charset=utf-8';\n if (objectKey.endsWith('.xml')) return 'application/xml; charset=utf-8';\n if (objectKey.endsWith('.strings')) return 'text/plain; charset=utf-8';\n return 'application/octet-stream';\n}\n\n/**\n * Parses a raw Lingohub file body from S3 into structured data.\n */\nexport function parseTranslationResourceRaw(\n raw: string,\n resource: LingohubResource,\n): unknown {\n if (resource.type === 'json') {\n return JSON.parse(raw) as unknown;\n }\n\n if (resource.type === 'strings') {\n return parseIOSStrings(raw);\n }\n\n if (resource.type === 'xml') {\n return convertXMLToJS(raw);\n }\n\n throw new Error(`Unsupported resource type: ${resource.type}`);\n}\n\n/**\n * Normalizes parsed translation data to a flat string map for merging (duplicate keys: last wins).\n */\nexport function toFlatStringMap(parsed: unknown): Record<string, string> {\n if (parsed === null || parsed === undefined) return {};\n if (typeof parsed === 'string') return { value: parsed };\n if (typeof parsed !== 'object') return { value: String(parsed) };\n if (Array.isArray(parsed)) {\n const out: Record<string, string> = {};\n parsed.forEach((v, i) => {\n out[String(i)] =\n typeof v === 'object' && v !== null ? JSON.stringify(v) : String(v);\n });\n return out;\n }\n\n const flat = transformObjectToFlat(parsed as Record<string, unknown>);\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(flat)) {\n if (v === null || v === undefined) {\n out[k] = '';\n } else if (typeof v === 'object') {\n out[k] = JSON.stringify(v);\n } else {\n out[k] = String(v);\n }\n }\n return out;\n}\n\n/** Where to write normalized JSON for one translation object key (avoids `.json.json`). */\nexport function translationJsonOutputPath(\n outputDir: string,\n objectKey: string,\n): string {\n if (objectKey.endsWith('.json')) {\n return path.resolve(outputDir, objectKey);\n }\n return path.resolve(outputDir, `${objectKey}.json`);\n}\n","import convert from 'xml-js';\nimport merge from 'lodash.merge';\n\nconst set = (obj: Record<string, unknown>, path: string, value: unknown): void => {\n const parts = path.split('.');\n let current: Record<string, unknown> = obj;\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i];\n if (part === '__proto__' || part === 'constructor' || part === 'prototype') return;\n if (current[part] === undefined || typeof current[part] !== 'object') {\n current[part] = {};\n }\n current = current[part] as Record<string, unknown>;\n }\n const last = parts[parts.length - 1];\n if (last !== '__proto__' && last !== 'constructor' && last !== 'prototype') {\n current[last] = value;\n }\n};\n\nexport const transformObjectToNested = (data: Record<string, unknown>): Record<string, unknown> => {\n const result: Record<string, unknown> = {};\n\n Object.entries(data).forEach(([key, value]) => {\n const tempObject: Record<string, unknown> = {};\n set(tempObject, key, value);\n merge(result, tempObject);\n });\n\n return result;\n};\n\nexport const transformObjectToFlat = (data: Record<string, any>): Record<string, any> => { // eslint-disable-line @typescript-eslint/no-explicit-any\n const result: Record<string, unknown> = {};\n\n const flatten = (obj: Record<string, any>, path: string[] = []) => { // eslint-disable-line @typescript-eslint/no-explicit-any\n Object.entries(obj).forEach(([key, value]) => {\n if (value !== null && typeof value === 'object' && !Array.isArray(value)) {\n flatten(value, path.concat(key));\n } else {\n result[path.concat(key).join('.')] = value;\n }\n });\n };\n\n flatten(data);\n\n return result;\n}\n\nexport const convertXMLToJS = (xml: string): Record<string, string> => {\n const converted = convert.xml2js(xml, {\n ignoreComment: true,\n ignoreDeclaration: true,\n ignoreInstruction: true,\n compact: true,\n }) as {\n resources: {\n string: {\n _attributes: { name: string },\n _text: 'User does not exist'\n }[];\n }\n };\n\n let mapped = {};\n const strings = converted.resources.string;\n const items = Array.isArray(strings) ? strings : [strings];\n items.forEach((item) => {\n if (!item?._attributes?.name) return;\n mapped = {\n ...mapped,\n [item._attributes.name]: item._text,\n };\n });\n\n return mapped;\n};\n\nexport const parseIOSStrings = (strings: string): Record<string, string> => {\n const parsedObj: Record<string, string> = {};\n strings\n .split('\\n')\n .filter((line) => line.startsWith('\"') && line.endsWith(';'))\n .map((line) => line.trim().slice(0, -1))\n .forEach((line) => {\n const eqIdx = line.indexOf(' = ');\n if (eqIdx === -1) return;\n const key = line.slice(1, eqIdx - 1);\n const value = line.slice(eqIdx + 3 + 1, -1);\n if (!key) return;\n parsedObj[key] = value;\n });\n\n return parsedObj;\n};","import { timingSafeEqual } from 'node:crypto';\nimport type { CMSProvider } from './types';\nimport type {\n FetchCmsBundlesOptions,\n FetchTranslationBundlesOptions,\n TranslationBundleInfo,\n} from './bundles';\n\nexport type ContentRefreshScope = 'cms' | 'translations' | 'all';\n\nexport interface ContentRefreshRequest {\n scope?: ContentRefreshScope;\n cms?: CMSProvider;\n content_types?: string[];\n projects?: string[];\n locales?: string[];\n}\n\n/** Defaults applied when the request omits fields (set by the host application). */\nexport interface ContentRefreshDefaults {\n scope?: ContentRefreshScope;\n cms?: CMSProvider;\n contentTypes?: string[];\n translationProjects?: string[];\n locales?: string[];\n}\n\nexport interface ContentRefreshError {\n step: string;\n message: string;\n}\n\nexport interface ContentRefreshResult {\n ok: boolean;\n scope: ContentRefreshScope;\n cmsFiles?: Record<string, string>;\n translationFiles?: TranslationBundleInfo;\n errors: ContentRefreshError[];\n durationMs: number;\n}\n\nexport interface ContentRefreshFetchers {\n fetchCmsBundles: (\n options: FetchCmsBundlesOptions,\n ) => Promise<Record<string, string>>;\n fetchTranslationBundles: (\n options: FetchTranslationBundlesOptions,\n ) => Promise<TranslationBundleInfo>;\n}\n\nexport function resolveContentRefreshScope(\n request: ContentRefreshRequest,\n defaults: ContentRefreshDefaults,\n): ContentRefreshScope {\n return request.scope ?? defaults.scope ?? 'cms';\n}\n\n/** Base64 of `username:password` (value only — prefix with `Basic ` in the header). */\nexport function encodeBasicAuthCredentials(\n username: string,\n password: string,\n): string {\n return Buffer.from(`${username}:${password}`, 'utf8').toString('base64');\n}\n\n/**\n * Validates `Authorization: Basic <base64>` against the expected credentials\n * (base64 of `user:pass`, same as staging site basic auth).\n */\nexport function assertContentRefreshBasicAuth(\n authorizationHeader: string | undefined,\n expectedCredentialsBase64: string,\n): void {\n if (!expectedCredentialsBase64) {\n throw new ContentRefreshAuthError(\n 'Content refresh basic auth is not configured (set CONTENT_REFRESH_BASIC_AUTH)',\n 500,\n );\n }\n if (!authorizationHeader?.startsWith('Basic ')) {\n throw new ContentRefreshAuthError(\n 'Missing or malformed Authorization header (expected Basic)',\n 401,\n );\n }\n const provided = authorizationHeader.slice(6).trim();\n const bufA = new TextEncoder().encode(provided);\n const bufB = new TextEncoder().encode(expectedCredentialsBase64);\n if (bufA.byteLength !== bufB.byteLength || !timingSafeEqual(bufA, bufB)) {\n throw new ContentRefreshAuthError('Invalid basic auth credentials', 403);\n }\n}\n\nexport class ContentRefreshAuthError extends Error {\n constructor(\n message: string,\n readonly statusCode: number,\n ) {\n super(message);\n this.name = 'ContentRefreshAuthError';\n }\n}\n\n/**\n * Pull the latest bundles from S3 into the host app's configured output directory.\n */\nexport async function executeContentRefresh(\n fetchers: ContentRefreshFetchers,\n request: ContentRefreshRequest,\n defaults: ContentRefreshDefaults = {},\n): Promise<ContentRefreshResult> {\n const started = Date.now();\n const scope = resolveContentRefreshScope(request, defaults);\n const errors: ContentRefreshError[] = [];\n let cmsFiles: Record<string, string> | undefined;\n let translationFiles: TranslationBundleInfo | undefined;\n\n if (scope === 'cms' || scope === 'all') {\n const cms = request.cms ?? defaults.cms ?? 'contentful';\n const contentTypes = request.content_types ?? defaults.contentTypes;\n if (!contentTypes?.length) {\n errors.push({\n step: 'cms',\n message: 'content_types (or handler defaults.contentTypes) is required for CMS refresh',\n });\n } else {\n try {\n cmsFiles = await fetchers.fetchCmsBundles({ cms, contentTypes });\n } catch (err) {\n errors.push({\n step: 'cms',\n message: err instanceof Error ? err.message : String(err),\n });\n }\n }\n }\n\n if (scope === 'translations' || scope === 'all') {\n const projects = request.projects ?? defaults.translationProjects;\n if (!projects?.length) {\n errors.push({\n step: 'translations',\n message:\n 'projects (or handler defaults.translationProjects) is required for translation refresh',\n });\n } else {\n const locales = request.locales ?? defaults.locales;\n try {\n const projectMap = Object.fromEntries(\n projects.map((p) => [p, [] as string[]]),\n );\n translationFiles = await fetchers.fetchTranslationBundles({\n projects: projectMap,\n locales,\n });\n } catch (err) {\n errors.push({\n step: 'translations',\n message: err instanceof Error ? err.message : String(err),\n });\n }\n }\n }\n\n return {\n ok: errors.length === 0,\n scope,\n cmsFiles,\n translationFiles,\n errors,\n durationMs: Date.now() - started,\n };\n}\n\nexport interface PostContentRefreshResponse {\n target: string;\n ok: boolean;\n status: number;\n body?: unknown;\n error?: string;\n}\n\n/**\n * Ask a remote application (web-site, web-app, …) to refresh its local content cache.\n */\nexport async function postContentRefresh(\n target: string,\n url: string,\n basicAuth: string,\n request: ContentRefreshRequest,\n): Promise<PostContentRefreshResponse> {\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n Authorization: `Basic ${basicAuth}`,\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n },\n body: JSON.stringify(request),\n });\n\n const text = await response.text();\n let body: unknown;\n if (text) {\n try {\n body = JSON.parse(text) as unknown;\n } catch {\n body = text;\n }\n }\n\n return {\n target,\n ok: response.ok,\n status: response.status,\n body,\n error: response.ok\n ? undefined\n : typeof body === 'object' && body !== null && 'error' in body\n ? String((body as { error: unknown }).error)\n : `HTTP ${response.status}`,\n };\n } catch (err) {\n return {\n target,\n ok: false,\n status: 0,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n","import type { CMSProvider } from '../shared/types';\nimport { ContentStore } from '../shared/s3';\nimport {\n fetchCmsBundles,\n fetchMergedTranslationBundles,\n fetchTranslationBundles,\n queryCmsBundle,\n type FetchCmsBundlesOptions,\n type FetchMergedTranslationBundlesOptions,\n type FetchTranslationBundlesOptions,\n type QueryOptions,\n type TranslationBundleInfo,\n} from '../shared/bundles';\nimport {\n executeContentRefresh,\n type ContentRefreshDefaults,\n type ContentRefreshRequest,\n type ContentRefreshResult,\n} from '../shared/content-refresh';\nimport type { SDKConfig } from './client-types';\n\nexport type {\n ContentRefreshDefaults,\n ContentRefreshRequest,\n ContentRefreshResult,\n ContentRefreshScope,\n} from '../shared/content-refresh';\nexport type {\n FetchCmsBundlesOptions,\n FetchTranslationBundlesOptions,\n FetchMergedTranslationBundlesOptions,\n TranslationFilterConfig,\n QueryOptions,\n CmsBundleInfo,\n TranslationBundleInfo,\n BundleItem,\n SDKConfig,\n S3RetryConfig,\n} from './client-types';\nexport { getDefaultS3RetryConfig } from './client-types';\n\nexport class ContentStoreSDK {\n private store: ContentStore;\n private outputDir: string;\n\n constructor(config: SDKConfig) {\n this.store = new ContentStore(config.s3);\n this.outputDir = config.outputDir;\n }\n\n /**\n * Downloads the latest bundles from S3 and writes them as JSON files\n * to `outputDir`.\n *\n * @returns A map of contentType to absolute file path.\n */\n async fetchCmsBundles(\n options: FetchCmsBundlesOptions,\n ): Promise<Record<string, string>> {\n return fetchCmsBundles(this.store, this.outputDir, options);\n }\n\n /**\n * Downloads translation bundles from S3 and writes them as JSON files\n * to `outputDir`.\n *\n * @returns Per project, a map of S3 object key to absolute file path.\n */\n async fetchTranslationBundles(\n options: FetchTranslationBundlesOptions,\n ): Promise<TranslationBundleInfo> {\n return fetchTranslationBundles(this.store, this.outputDir, options);\n }\n\n /**\n * Downloads all translation resources for the given projects/locales, parses them,\n * and writes one merged `{locale}.json` per locale (string key/value map; duplicate keys:\n * last wins).\n */\n async fetchMergedTranslationBundles(\n options: FetchMergedTranslationBundlesOptions,\n ): Promise<Record<string, string>> {\n return fetchMergedTranslationBundles(this.store, this.outputDir, options);\n }\n\n /**\n * Queries a previously fetched bundle from the local filesystem.\n */\n async queryCmsBundle(\n cms: CMSProvider,\n contentType: string,\n options: QueryOptions = {},\n ): Promise<unknown[]> {\n return queryCmsBundle(this.outputDir, cms, contentType, options);\n }\n\n /**\n * Download the latest bundles from S3 (same as the hosted refresh HTTP endpoint).\n */\n async refreshContent(\n request: ContentRefreshRequest = {},\n defaults: ContentRefreshDefaults = {},\n ): Promise<ContentRefreshResult> {\n return executeContentRefresh(\n {\n fetchCmsBundles: (opts) => this.fetchCmsBundles(opts),\n fetchTranslationBundles: (opts) => this.fetchTranslationBundles(opts),\n },\n request,\n defaults,\n );\n }\n}\n","import type { ContentStoreSDK } from './client';\nimport {\n assertContentRefreshBasicAuth,\n ContentRefreshAuthError,\n executeContentRefresh,\n type ContentRefreshDefaults,\n type ContentRefreshRequest,\n type ContentRefreshResult,\n} from '../shared/content-refresh';\n\n/** Minimal request shape for Next.js Pages API routes (`pages/api/*`). */\nexport interface NextPagesContentRefreshRequest {\n method?: string;\n headers: { authorization?: string | string[] };\n body?: ContentRefreshRequest;\n}\n\n/** Minimal response shape for Next.js Pages API routes. */\nexport interface NextPagesContentRefreshResponse {\n status(code: number): { json(body: unknown): void };\n}\n\nexport interface NextContentRefreshHandlerConfig {\n sdk: ContentStoreSDK;\n /** Base64 of `username:password` (same value as `CONTENT_REFRESH_BASIC_AUTH`). */\n basicAuth: string;\n defaults?: ContentRefreshDefaults;\n}\n\n/** @deprecated Use {@link NextContentRefreshHandlerConfig}. */\nexport type NextPagesContentRefreshHandlerConfig = NextContentRefreshHandlerConfig;\n\nfunction readAuthorizationHeader(\n value: string | string[] | null | undefined,\n): string | undefined {\n if (value == null) {\n return undefined;\n }\n if (Array.isArray(value)) {\n return value[0];\n }\n return value;\n}\n\nasync function runContentRefresh(\n config: NextContentRefreshHandlerConfig,\n authorization: string | undefined,\n body: ContentRefreshRequest,\n): Promise<{ status: number; body: ContentRefreshResult | { error: string } }> {\n const { sdk, basicAuth, defaults = {} } = config;\n\n try {\n assertContentRefreshBasicAuth(authorization, basicAuth);\n } catch (err) {\n if (err instanceof ContentRefreshAuthError) {\n return { status: err.statusCode, body: { error: err.message } };\n }\n throw err;\n }\n\n const result = await executeContentRefresh(\n {\n fetchCmsBundles: (opts) => sdk.fetchCmsBundles(opts),\n fetchTranslationBundles: (opts) => sdk.fetchTranslationBundles(opts),\n },\n body,\n defaults,\n );\n\n const status = result.ok ? 200 : result.errors.length > 0 ? 207 : 500;\n return { status, body: result };\n}\n\n/**\n * Handler for a Next.js Pages API route (e.g. pages/api/internal/content-refresh.ts).\n */\nexport function createNextPagesApiContentRefreshHandler(\n config: NextContentRefreshHandlerConfig,\n): (\n req: NextPagesContentRefreshRequest,\n res: NextPagesContentRefreshResponse,\n) => Promise<void> {\n return async (req, res): Promise<void> => {\n if (req.method !== 'POST') {\n res.status(405).json({ error: 'Method not allowed' });\n return;\n }\n\n const { status, body } = await runContentRefresh(\n config,\n readAuthorizationHeader(req.headers.authorization),\n req.body ?? {},\n );\n res.status(status).json(body);\n };\n}\n\n/**\n * Handler for a Next.js App Router route (e.g. app/api/internal/content-refresh/route.ts).\n */\nexport async function handleNextAppRouterContentRefresh(\n request: Request,\n config: NextContentRefreshHandlerConfig,\n): Promise<Response> {\n if (request.method !== 'POST') {\n return Response.json({ error: 'Method not allowed' }, { status: 405 });\n }\n\n let body: ContentRefreshRequest = {};\n try {\n body = (await request.json()) as ContentRefreshRequest;\n } catch {\n return Response.json({ error: 'Invalid JSON body' }, { status: 400 });\n }\n\n const { status, body: payload } = await runContentRefresh(\n config,\n request.headers.get('authorization') ?? undefined,\n body,\n );\n\n return Response.json(payload, { status });\n}\n"],"mappings":"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","names":["path","path","out","path"]}
1
+ {"version":3,"sources":["../src/shared/s3.ts","../src/shared/bundles.ts","../src/shared/s3-retry.ts","../src/shared/trimDepth.ts","../src/shared/lingohub.ts","../src/shared/translationResource.ts","../src/shared/utils.ts","../src/shared/content-refresh.ts","../src/sdk/client.ts","../src/sdk/next-content-refresh.ts"],"sourcesContent":["import {\n S3Client,\n PutObjectCommand,\n GetObjectCommand,\n} from '@aws-sdk/client-s3';\nimport type { S3Config } from './types';\n\nexport class ContentStore {\n private client: S3Client;\n private bucket: string;\n\n constructor(cfg: S3Config) {\n this.client = new S3Client({\n region: cfg.region,\n credentials: {\n accessKeyId: cfg.accessKeyId,\n secretAccessKey: cfg.secretAccessKey,\n },\n });\n this.bucket = cfg.bucket;\n }\n\n async upload(key: string, data: unknown): Promise<string> {\n await this.client.send(\n new PutObjectCommand({\n Bucket: this.bucket,\n Key: key,\n Body: JSON.stringify(data, null, 2),\n ContentType: 'application/json',\n }),\n );\n return key;\n }\n\n /** Raw UTF-8 body (e.g. Lingohub file bytes as text). */\n async uploadRaw(\n key: string,\n body: string,\n contentType: string,\n ): Promise<string> {\n await this.client.send(\n new PutObjectCommand({\n Bucket: this.bucket,\n Key: key,\n Body: body,\n ContentType: contentType,\n }),\n );\n return key;\n }\n\n async download(key: string): Promise<unknown> {\n const response = await this.client.send(\n new GetObjectCommand({ Bucket: this.bucket, Key: key }),\n );\n const body = await response.Body?.transformToString();\n if (!body) throw new Error(`Empty response for key: ${key}`);\n return JSON.parse(body);\n }\n\n /** Raw UTF-8 body from S3 (no JSON.parse). */\n async downloadRaw(key: string): Promise<string> {\n const response = await this.client.send(\n new GetObjectCommand({ Bucket: this.bucket, Key: key }),\n );\n const body = await response.Body?.transformToString();\n if (!body) throw new Error(`Empty response for key: ${key}`);\n return body;\n }\n}\n\n/** {cms}-{contentType}.json (always points at the latest version) */\nexport const buildCmsObjectKey = (cms: string, contentType: string): string => {\n return `${cms}-${contentType}.json`;\n}\n\nexport const buildTranslationObjectKey = (project:string, fileName: string, locale: string): string => {\n return `lingohub-${project}.${fileName.replaceAll('[locale]', locale)}`;\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { CMSProvider } from './types';\nimport { buildCmsObjectKey, buildTranslationObjectKey, ContentStore } from './s3';\nimport {\n downloadRawWithRetry,\n downloadWithRetry,\n getDefaultS3RetryConfig,\n type S3RetryConfig,\n} from './s3-retry';\nimport { trimDepth } from './trimDepth';\nimport {\n allProjects,\n defaultLocales,\n type LingohubResource,\n} from './lingohub';\n\n/**\n * Resolves the effective locale list for a single resource.\n *\n * - No explicit request + resource has own locales → resource.locales (full)\n * - Explicit request + resource has own locales → intersection (skip unsupported)\n * - No explicit request + no resource locales → defaultLocales\n * - Explicit request + no resource locales → requested locales\n */\nfunction resolveResourceLocales(\n resource: LingohubResource,\n requestedLocales: string[] | null,\n): string[] {\n if (resource.locales) {\n return requestedLocales\n ? requestedLocales.filter((l) => resource.locales!.includes(l))\n : resource.locales;\n }\n return requestedLocales ?? defaultLocales;\n}\nimport {\n parseTranslationResourceRaw,\n toFlatStringMap,\n translationJsonOutputPath,\n} from './translationResource';\n\nexport { trimDepth } from './trimDepth';\nexport type { S3RetryConfig } from './s3-retry';\nexport { getDefaultS3RetryConfig } from './s3-retry';\n\n/**\n * Expand dotted keys into a nested object structure.\n * e.g. `{ \"General.tryAgain\": \"Try Again\" }` → `{ \"General\": { \"tryAgain\": \"Try Again\" } }`\n */\nexport function nestKeys(flat: unknown): unknown {\n if (typeof flat !== 'object' || flat === null || Array.isArray(flat)) return flat;\n const src = flat as Record<string, unknown>;\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(src)) {\n const parts = key.split('.');\n let cur = result;\n for (let i = 0; i < parts.length - 1; i++) {\n const seg = parts[i]!;\n if (!(seg in cur) || typeof cur[seg] !== 'object' || cur[seg] === null) {\n cur[seg] = {};\n }\n cur = cur[seg] as Record<string, unknown>;\n }\n cur[parts[parts.length - 1]!] = value;\n }\n return result;\n}\n\nexport interface CmsBundleInfo {\n [key: string]: string;\n}\n\nexport interface TranslationBundleInfo {\n [key: string] : Record<string, string>;\n}\n\nexport interface BundleItem {\n [key: string]: any; // eslint-disable-line @typescript-eslint/no-explicit-any\n}\n\nexport interface FetchCmsBundlesOptions {\n cms: CMSProvider;\n contentTypes: string[];\n /** S3 GET retry; defaults via {@link getDefaultS3RetryConfig}. */\n retry?: S3RetryConfig;\n}\n\n/**\n * Config-file-friendly shape used by `fetchTranslationBundles` and the CLI.\n *\n * ```json\n * {\n * \"projects\": {\n * \"tandem\": [],\n * \"tandem-(website)\": [\"main\", \"ai\"]\n * },\n * \"locales\": [\"en\", \"de\", \"it\"]\n * }\n * ```\n *\n * `projects` maps each Lingohub project id to an array of resource keys.\n * An empty array means **all** resources for that project.\n * `locales` is optional — omit (or pass `[]`) to fetch the default locale set.\n */\nexport interface TranslationFilterConfig {\n projects: Record<string, string[]>;\n locales?: string[];\n /** Output key structure. `\"flat\"` (default) keeps dotted keys as-is; `\"nested\"` expands dots into nested objects. */\n structure?: 'flat' | 'nested';\n}\n\nexport interface FetchTranslationBundlesOptions extends TranslationFilterConfig {\n /** S3 GET retry; defaults via {@link getDefaultS3RetryConfig}. */\n retry?: S3RetryConfig;\n}\n\n/** One merged JSON file per catalog locale (`en.json`, …). Same options as {@link FetchTranslationBundlesOptions}. */\nexport type FetchMergedTranslationBundlesOptions = FetchTranslationBundlesOptions;\n\nexport interface QueryOptions {\n /**\n * Filter items by matching property values (exact equality, or array for IN).\n * Keys may use dot notation for nested paths, e.g. `{ 'meta._id': 'abc' }` matches\n * `item.meta._id`.\n *\n * Contentful-style operators on the path (before `[`):\n * - `{ 'field[exists]': true }` — field is present and non-empty (not null, undefined,\n * `''`, `[]`, or `{}`).\n * - `{ 'field[exists]': false }` — field is missing or empty (same emptiness rules).\n * Nested paths work, e.g. `{ 'blocks.hero[exists]': false }`.\n */\n fields?: Record<string, unknown>;\n /**\n * Properties to include in each result object. Omit to return all properties.\n * Keys may use dot notation; nested segments become nested objects in the result,\n * e.g. `['slug', 'meta._updatedAt']` → `{ slug, meta: { _updatedAt } }`.\n */\n select?: string[];\n /** Maximum number of items to return. */\n limit?: number;\n /**\n * How many levels deep to return.\n * - 1 = the item's own scalar properties only; nested objects/refs are nulled.\n * - 2 = the item including its direct references; refs inside those are nulled.\n * - 3 = three levels deep, and so on.\n * - Omit to return the full depth.\n */\n include?: number;\n}\n\n/** Read a value at a dotted path; returns whether every segment existed. */\nfunction getAtPath(\n obj: unknown,\n dottedPath: string,\n): { found: true; value: unknown } | { found: false } {\n const parts = dottedPath.split('.').filter((p) => p.length > 0);\n if (parts.length === 0) return { found: false };\n\n let cur: unknown = obj;\n for (const p of parts) {\n if (cur === null || typeof cur !== 'object' || Array.isArray(cur)) {\n return { found: false };\n }\n const rec = cur as Record<string, unknown>;\n if (!(p in rec)) return { found: false };\n cur = rec[p];\n }\n return { found: true, value: cur };\n}\n\nconst FIELD_OP_KEY = /^(.+)\\[([^\\]]+)]$/;\n\nfunction parseFieldKey(key: string): { path: string; operator?: string } {\n const m = FIELD_OP_KEY.exec(key);\n if (!m) return { path: key };\n return { path: m[1]!, operator: m[2]! };\n}\n\n/** True when a bundle value counts as “no content” (aligned with typical CMS “empty”). */\nfunction isEmptyValue(value: unknown): boolean {\n if (value === null || value === undefined) return true;\n if (value === '') return true;\n if (Array.isArray(value) && value.length === 0) {\n return true;\n }\n return typeof value === 'object' &&\n !Array.isArray(value) &&\n Object.keys(value).length === 0;\n\n}\n\nfunction matchesFieldFilter(\n item: BundleItem,\n key: string,\n expected: unknown,\n): boolean {\n const { path, operator } = parseFieldKey(key);\n const at = getAtPath(item, path);\n\n if (operator === 'exists') {\n if (expected !== true && expected !== false) return false;\n const empty = !at.found || isEmptyValue(at.value);\n return !expected ? empty : !empty;\n }\n\n const actual = at.found ? at.value : undefined;\n if (Array.isArray(expected)) return expected.includes(actual);\n return actual === expected;\n}\n\n/** Set `value` on `target` at a dotted path, creating plain objects as needed. */\nfunction setNestedAt(\n target: Record<string, unknown>,\n dottedPath: string,\n value: unknown,\n): void {\n const parts = dottedPath.split('.').filter((p) => p.length > 0);\n if (parts.length === 0) return;\n\n if (parts.length === 1) {\n target[parts[0]!] = value;\n return;\n }\n\n const head = parts[0]!;\n const rest = parts.slice(1).join('.');\n let nested = target[head];\n if (\n nested === null ||\n typeof nested !== 'object' ||\n Array.isArray(nested)\n ) {\n nested = {};\n target[head] = nested;\n }\n setNestedAt(nested as Record<string, unknown>, rest, value);\n}\n\n/**\n * Downloads the latest CMS bundles from S3 and writes them as JSON files to `outputDir`.\n *\n * @returns A map of contentType to absolute file path.\n */\nexport async function fetchCmsBundles(\n store: ContentStore,\n outputDir: string,\n options: FetchCmsBundlesOptions,\n): Promise<Record<string, string>> {\n const { cms, contentTypes } = options;\n const retry = options.retry ?? getDefaultS3RetryConfig();\n await fs.mkdir(outputDir, { recursive: true });\n\n const result: CmsBundleInfo = {};\n\n await Promise.all(\n contentTypes.map(async (contentType) => {\n const key = buildCmsObjectKey(cms, contentType);\n const data = await downloadWithRetry(store, key, retry);\n const filePath = path.resolve(outputDir, key);\n await fs.writeFile(filePath, JSON.stringify(data, null, 2), 'utf-8');\n result[contentType] = filePath;\n }),\n );\n\n return result;\n}\n\n/**\n * Downloads the latest translation bundles from S3 and writes them as JSON files to `outputDir`.\n *\n * @returns For each project, a map of S3 object key to absolute file path on disk.\n */\n/** Filter a project's full resource list by the resource keys specified in the config. */\nfunction filterResources(\n projectResources: LingohubResource[],\n resourceFilter: string[],\n): LingohubResource[] {\n if (resourceFilter.length === 0) return projectResources;\n return projectResources.filter((r) => resourceFilter.includes(r.resource));\n}\n\nexport async function fetchTranslationBundles(\n store: ContentStore,\n outputDir: string,\n options: FetchTranslationBundlesOptions,\n): Promise<TranslationBundleInfo> {\n const { projects, locales, structure } = options;\n const nested = structure === 'nested';\n const retry = options.retry ?? getDefaultS3RetryConfig();\n await fs.mkdir(outputDir, { recursive: true });\n\n const result: TranslationBundleInfo = {};\n const requestedLocales = locales && locales.length ? locales : null;\n\n await Promise.all(\n Object.entries(projects).map(async ([project, resourceFilter]) => {\n const allResources = allProjects[project];\n if (!allResources?.length) return;\n\n const resources = filterResources(allResources, resourceFilter);\n if (!resources.length) return;\n\n const resourceTasks: { objectKey: string; resource: LingohubResource }[] =\n [];\n for (const resource of resources) {\n const resourceLocales = resolveResourceLocales(resource, requestedLocales);\n for (const loc of resourceLocales) {\n const locale =\n resource.localeMapping && resource.localeMapping[loc]\n ? resource.localeMapping[loc]\n : loc;\n const objectKey = buildTranslationObjectKey(\n project,\n resource.fileName,\n locale,\n );\n resourceTasks.push({ objectKey, resource });\n }\n }\n\n await Promise.all(\n resourceTasks.map(async ({ objectKey, resource }) => {\n const raw = await downloadRawWithRetry(store, objectKey, retry);\n const parsed = parseTranslationResourceRaw(raw, resource);\n const output = nested ? nestKeys(parsed) : parsed;\n const filePath = translationJsonOutputPath(outputDir, objectKey);\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n await fs.writeFile(\n filePath,\n JSON.stringify(output, null, 2),\n 'utf-8',\n );\n if (!result[project]) {\n result[project] = {};\n }\n result[project][objectKey] = filePath;\n }),\n );\n }),\n );\n\n return result;\n}\n\n/**\n * Downloads translation bundles from S3, parses each raw Lingohub file, and merges all\n * key/value pairs per **catalog** locale into a single JSON file (e.g. `en.json`).\n * Duplicate keys across resources or projects: **last write wins** (iteration order:\n * projects → resources → locales).\n *\n * @returns Map of locale code to absolute path of the merged `{locale}.json` file.\n */\nexport async function fetchMergedTranslationBundles(\n store: ContentStore,\n outputDir: string,\n options: FetchMergedTranslationBundlesOptions,\n): Promise<Record<string, string>> {\n const { projects, locales, structure } = options;\n const nested = structure === 'nested';\n const retry = options.retry ?? getDefaultS3RetryConfig();\n await fs.mkdir(outputDir, { recursive: true });\n\n const requestedLocales = locales && locales.length ? locales : null;\n\n type Task = {\n catalogLocale: string;\n objectKey: string;\n resource: LingohubResource;\n };\n const tasks: Task[] = [];\n const allLocales = new Set<string>();\n\n for (const [project, resourceFilter] of Object.entries(projects)) {\n const allResources = allProjects[project];\n if (!allResources?.length) continue;\n\n const resources = filterResources(allResources, resourceFilter);\n if (!resources.length) continue;\n\n for (const resource of resources) {\n const resourceLocales = resolveResourceLocales(resource, requestedLocales);\n for (const loc of resourceLocales) {\n allLocales.add(loc);\n const mappedLocale =\n resource.localeMapping && resource.localeMapping[loc]\n ? resource.localeMapping[loc]\n : loc;\n const objectKey = buildTranslationObjectKey(\n project,\n resource.fileName,\n mappedLocale,\n );\n tasks.push({ catalogLocale: loc, objectKey, resource });\n }\n }\n }\n\n const results = await Promise.all(\n tasks.map(async ({ catalogLocale, objectKey, resource }) => {\n const raw = await downloadRawWithRetry(store, objectKey, retry);\n const parsed = parseTranslationResourceRaw(raw, resource);\n const stringMap = toFlatStringMap(parsed);\n return { catalogLocale, stringMap };\n }),\n );\n\n const merged: Record<string, Record<string, string>> = {};\n for (const loc of allLocales) {\n merged[loc] = {};\n }\n for (const { catalogLocale, stringMap } of results) {\n Object.assign(merged[catalogLocale]!, stringMap);\n }\n\n const out: Record<string, string> = {};\n for (const loc of allLocales) {\n const filePath = path.resolve(outputDir, `${loc}.json`);\n const output = nested ? nestKeys(merged[loc]) : merged[loc];\n await fs.writeFile(\n filePath,\n JSON.stringify(output, null, 2),\n 'utf-8',\n );\n out[loc] = filePath;\n }\n\n return out;\n}\n\n/**\n * Queries a previously fetched bundle from the local filesystem.\n */\nexport async function queryCmsBundle(\n outputDir: string,\n cms: CMSProvider,\n contentType: string,\n options: QueryOptions = {},\n): Promise<unknown[]> {\n const filePath = path.resolve(\n outputDir,\n `${cms}-${contentType}.json`,\n );\n const raw = await fs.readFile(filePath, 'utf-8');\n let items:BundleItem[] = JSON.parse(raw) as Record<string, unknown>[];\n\n if (options.fields) {\n const filters = options.fields;\n items = items.filter((item) =>\n Object.entries(filters).every(([key, expected]) =>\n matchesFieldFilter(item, key, expected),\n ),\n );\n }\n\n if (options.limit !== undefined && options.limit > 0) {\n items = items.slice(0, options.limit);\n }\n\n if (options.include !== undefined) {\n items = items.map(\n (item) => trimDepth(item, options.include!) as Record<string, unknown>,\n );\n }\n\n if (options.select?.length) {\n const keys = options.select;\n items = items.map((item) => {\n const picked: Record<string, unknown> = {};\n for (const k of keys) {\n const at = getAtPath(item, k);\n if (at.found) setNestedAt(picked, k, at.value);\n }\n return picked;\n });\n }\n\n return items;\n}\n","import type { ContentStore } from './s3';\n\n/** Retry/backoff for S3 reads (aligned with CMS `RetryConfig` shape). */\nexport interface S3RetryConfig {\n maxRetries: number;\n baseDelayMs: number;\n maxDelayMs: number;\n}\n\nfunction computeDelay(\n attempt: number,\n baseDelayMs: number,\n maxDelayMs: number,\n): number {\n const exponential = baseDelayMs * Math.pow(2, attempt);\n const jitter = Math.random() * baseDelayMs;\n return Math.min(exponential + jitter, maxDelayMs);\n}\n\n/**\n * Default S3 download retry policy from env.\n * `S3_RETRY_*` overrides `RETRY_*` when set.\n */\nexport function getDefaultS3RetryConfig(): S3RetryConfig {\n return {\n maxRetries: parseInt(\n process.env.S3_RETRY_MAX_RETRIES ??\n process.env.RETRY_MAX_RETRIES ??\n '5',\n 10,\n ),\n baseDelayMs: parseInt(\n process.env.S3_RETRY_BASE_DELAY_MS ??\n process.env.RETRY_BASE_DELAY_MS ??\n '1000',\n 10,\n ),\n maxDelayMs: parseInt(\n process.env.S3_RETRY_MAX_DELAY_MS ??\n process.env.RETRY_MAX_DELAY_MS ??\n '60000',\n 10,\n ),\n };\n}\n\n/**\n * True when a failed S3 GET may succeed after a short wait (503 Slow Down,\n * transient network, throttling). Never true for definitive client errors (404, etc.).\n */\nexport function isRetryableS3DownloadError(err: unknown): boolean {\n if (err === null || err === undefined) return false;\n\n if (typeof err === 'object') {\n const e = err as {\n name?: string;\n Code?: string;\n $metadata?: { httpStatusCode?: number };\n };\n const status = e.$metadata?.httpStatusCode;\n if (status === 404 || status === 403 || status === 401 || status === 400) {\n return false;\n }\n if (\n status !== undefined &&\n (status === 408 ||\n status === 429 ||\n status === 500 ||\n status === 502 ||\n status === 503 ||\n status === 504)\n ) {\n return true;\n }\n\n const name = e.name ?? '';\n const code = e.Code ?? '';\n if (\n /SlowDown|Throttl|Timeout|TooManyRequests|ServiceUnavailable|InternalError/i.test(\n name,\n ) ||\n /SlowDown|Throttl/i.test(code)\n ) {\n return true;\n }\n }\n\n if (err instanceof Error) {\n const m = err.message;\n if (\n /ECONNRESET|ETIMEDOUT|EPIPE|ECONNREFUSED|socket hang up|getaddrinfo/i.test(\n m,\n )\n ) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Runs `fn` with retries when `isRetryableS3DownloadError` applies; otherwise throws immediately.\n */\nexport async function withS3Retry<T>(\n fn: () => Promise<T>,\n { maxRetries, baseDelayMs, maxDelayMs }: S3RetryConfig,\n): Promise<T> {\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await fn();\n } catch (err) {\n if (!isRetryableS3DownloadError(err)) {\n throw err;\n }\n if (attempt === maxRetries) {\n throw err;\n }\n\n const delay = computeDelay(attempt, baseDelayMs, maxDelayMs);\n console.warn(\n ` S3 request failed (attempt ${attempt + 1}/${maxRetries + 1}): ${\n err instanceof Error ? err.message : String(err)\n }. Retrying in ${Math.round(delay)}ms…`,\n );\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n\n throw new Error('withS3Retry: unreachable');\n}\n\nexport async function downloadWithRetry(\n store: ContentStore,\n key: string,\n cfg: S3RetryConfig,\n): Promise<unknown> {\n return withS3Retry(() => store.download(key), cfg);\n}\n\nexport async function downloadRawWithRetry(\n store: ContentStore,\n key: string,\n cfg: S3RetryConfig,\n): Promise<string> {\n return withS3Retry(() => store.downloadRaw(key), cfg);\n}\n","/**\n * Trims nested object depth.\n *\n * `remaining` represents how many levels the current object is allowed.\n * - Scalar properties are always kept.\n * - Nested objects / arrays-of-objects consume one level. When `remaining`\n * drops to 1 they are replaced with `null` (no budget left for refs).\n */\nexport function trimDepth(value: unknown, remaining: number): unknown {\n if (value === null || value === undefined || typeof value !== 'object') {\n return value;\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => trimDepth(item, remaining));\n }\n\n const obj = value as Record<string, unknown>;\n const result: Record<string, unknown> = {};\n\n for (const [k, v] of Object.entries(obj)) {\n if (v === null || v === undefined || typeof v !== 'object') {\n result[k] = v;\n } else if (remaining <= 1) {\n result[k] = null;\n } else if (Array.isArray(v)) {\n result[k] = v.map((item) => {\n if (item !== null && typeof item === 'object' && !Array.isArray(item)) {\n return trimDepth(item, remaining - 1);\n }\n return item;\n });\n } else {\n result[k] = trimDepth(v, remaining - 1);\n }\n }\n\n return result;\n}\n","export const defaultLocales = ['de', 'en', 'es', 'fr', 'it', 'ja', 'ko', 'pt-br', 'ru', 'th', 'uk', 'vi', 'zh-hans', 'zh-hant'];\n\nconst localeMapping = {\n ios: {\n 'pt-br': 'pt',\n 'zh-hans': 'zh-Hans',\n 'zh-hant': 'zh-Hant',\n },\n android: {\n 'pt-br': 'pt',\n 'zh-hans': 'zh-Hans-CN',\n 'zh-hant': 'zh-TW',\n },\n website: {\n 'prs': 'fa',\n },\n};\n\nexport type LingohubResource = {\n resource: string,\n fileName: string;\n type: 'json'|'strings'|'xml';\n localeMapping?: Record<string, string>;\n locales?: string[]\n}\n\nexport const allProjects: Record<string, LingohubResource[]> = {\n 'tandem-(new-website)': [\n {\n resource: 'main',\n fileName: 'Website.[locale].json',\n type: 'json',\n locales: ['ar','de', 'en', 'es', 'fr', 'it', 'ja', 'ko', 'pt-br', 'prs', 'ps', 'ru', 'zh-hans', 'zh-hant'],\n localeMapping: localeMapping.website,\n }\n ],\n 'tandem-(website)': [\n {\n resource: 'main',\n fileName: '[locale].json',\n type: 'json',\n locales: ['ar', 'de', 'en', 'es', 'fr', 'it', 'ja', 'ko', 'pt-br', 'prs', 'ps', 'ru', 'th', 'uk', 'vi', 'zh-hans', 'zh-hant'],\n localeMapping: localeMapping.website,\n },\n {\n resource: 'ai',\n fileName: 'AI.[locale].json',\n type: 'json'\n },\n {\n resource: 'languages',\n fileName: 'languages.[locale].json',\n type: 'json'\n }\n ],\n 'tandem': [\n {\n resource: 'infoplist',\n fileName: 'InfoPlist.[locale].strings',\n type: 'strings',\n localeMapping: localeMapping.ios,\n },\n {\n resource: 'localizable',\n fileName: 'Localizable.[locale].strings',\n type: 'strings',\n localeMapping: localeMapping.ios,\n },\n {\n resource: 'ipad',\n fileName: 'Main_iPad.[locale].strings',\n type: 'strings',\n localeMapping: localeMapping.ios,\n },\n {\n resource: 'main',\n fileName: 'Main.[locale].strings',\n type: 'strings',\n localeMapping: localeMapping.ios,\n }\n ],\n 'tandem-(android)': [\n {\n resource: 'accessibility',\n fileName: 'accessibility_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'call',\n fileName: 'call_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'cert',\n fileName: 'cert_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'chat',\n fileName: 'chat_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'checklist',\n fileName: 'checklist_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'clubs',\n fileName: 'clubs_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'common',\n fileName: 'common_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'community',\n fileName: 'community_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'correction',\n fileName: 'correction_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'country_names',\n fileName: 'country_names.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'emoji',\n fileName: 'emoji_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'errors',\n fileName: 'errors.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'expressions',\n fileName: 'expressions_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'gif',\n fileName: 'gif_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'guidelines',\n fileName: 'guidelines_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'lanuguages',\n fileName: 'languages_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'localizable',\n fileName: 'localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'localizable2',\n fileName: 'localizable2.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'login',\n fileName: 'login_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'myprofile',\n fileName: 'myprofile_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'onb',\n fileName: 'onb_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'parties',\n fileName: 'parties_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'pro',\n fileName: 'pro_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'pro_screen',\n fileName: 'pro_screen_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'push_notification',\n fileName: 'push_notification_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'reporting',\n fileName: 'reporting_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'translation',\n fileName: 'translation_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n }\n\n ],\n 'tandem-(web-invites)': [\n {\n resource: 'main',\n fileName: '[locale].json',\n type: 'json',\n locales: ['ar', 'de', 'en', 'es', 'fr', 'it', 'ja', 'ko', 'prs', 'ps', 'pt-br', 'ru', 'uk', 'zh-hans', 'zh-hant'],\n localeMapping: localeMapping.website,\n }\n ]\n};\n","import path from 'node:path';\nimport { convertXMLToJS, parseIOSStrings, transformObjectToFlat } from './utils';\nimport type { LingohubResource } from './lingohub';\n\n/** Content-Type for raw Lingohub bodies stored in S3. */\nexport function contentTypeForTranslationKey(objectKey: string): string {\n if (objectKey.endsWith('.json')) return 'application/json; charset=utf-8';\n if (objectKey.endsWith('.xml')) return 'application/xml; charset=utf-8';\n if (objectKey.endsWith('.strings')) return 'text/plain; charset=utf-8';\n return 'application/octet-stream';\n}\n\n/**\n * Parses a raw Lingohub file body from S3 into structured data.\n */\nexport function parseTranslationResourceRaw(\n raw: string,\n resource: LingohubResource,\n): unknown {\n if (resource.type === 'json') {\n return JSON.parse(raw) as unknown;\n }\n\n if (resource.type === 'strings') {\n return parseIOSStrings(raw);\n }\n\n if (resource.type === 'xml') {\n return convertXMLToJS(raw);\n }\n\n throw new Error(`Unsupported resource type: ${resource.type}`);\n}\n\n/**\n * Normalizes parsed translation data to a flat string map for merging (duplicate keys: last wins).\n */\nexport function toFlatStringMap(parsed: unknown): Record<string, string> {\n if (parsed === null || parsed === undefined) return {};\n if (typeof parsed === 'string') return { value: parsed };\n if (typeof parsed !== 'object') return { value: String(parsed) };\n if (Array.isArray(parsed)) {\n const out: Record<string, string> = {};\n parsed.forEach((v, i) => {\n out[String(i)] =\n typeof v === 'object' && v !== null ? JSON.stringify(v) : String(v);\n });\n return out;\n }\n\n const flat = transformObjectToFlat(parsed as Record<string, unknown>);\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(flat)) {\n if (v === null || v === undefined) {\n out[k] = '';\n } else if (typeof v === 'object') {\n out[k] = JSON.stringify(v);\n } else {\n out[k] = String(v);\n }\n }\n return out;\n}\n\n/** Where to write normalized JSON for one translation object key (avoids `.json.json`). */\nexport function translationJsonOutputPath(\n outputDir: string,\n objectKey: string,\n): string {\n if (objectKey.endsWith('.json')) {\n return path.resolve(outputDir, objectKey);\n }\n return path.resolve(outputDir, `${objectKey}.json`);\n}\n","import convert from 'xml-js';\nimport merge from 'lodash.merge';\n\nconst set = (obj: Record<string, unknown>, path: string, value: unknown): void => {\n const parts = path.split('.');\n let current: Record<string, unknown> = obj;\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i];\n if (part === '__proto__' || part === 'constructor' || part === 'prototype') return;\n if (current[part] === undefined || typeof current[part] !== 'object') {\n current[part] = {};\n }\n current = current[part] as Record<string, unknown>;\n }\n const last = parts[parts.length - 1];\n if (last !== '__proto__' && last !== 'constructor' && last !== 'prototype') {\n current[last] = value;\n }\n};\n\nexport const transformObjectToNested = (data: Record<string, unknown>): Record<string, unknown> => {\n const result: Record<string, unknown> = {};\n\n Object.entries(data).forEach(([key, value]) => {\n const tempObject: Record<string, unknown> = {};\n set(tempObject, key, value);\n merge(result, tempObject);\n });\n\n return result;\n};\n\nexport const transformObjectToFlat = (data: Record<string, any>): Record<string, any> => { // eslint-disable-line @typescript-eslint/no-explicit-any\n const result: Record<string, unknown> = {};\n\n const flatten = (obj: Record<string, any>, path: string[] = []) => { // eslint-disable-line @typescript-eslint/no-explicit-any\n Object.entries(obj).forEach(([key, value]) => {\n if (value !== null && typeof value === 'object' && !Array.isArray(value)) {\n flatten(value, path.concat(key));\n } else {\n result[path.concat(key).join('.')] = value;\n }\n });\n };\n\n flatten(data);\n\n return result;\n}\n\nexport const convertXMLToJS = (xml: string): Record<string, string> => {\n const converted = convert.xml2js(xml, {\n ignoreComment: true,\n ignoreDeclaration: true,\n ignoreInstruction: true,\n compact: true,\n }) as {\n resources: {\n string: {\n _attributes: { name: string },\n _text: 'User does not exist'\n }[];\n }\n };\n\n let mapped = {};\n const strings = converted.resources.string;\n const items = Array.isArray(strings) ? strings : [strings];\n items.forEach((item) => {\n if (!item?._attributes?.name) return;\n mapped = {\n ...mapped,\n [item._attributes.name]: item._text,\n };\n });\n\n return mapped;\n};\n\nexport const parseIOSStrings = (strings: string): Record<string, string> => {\n const parsedObj: Record<string, string> = {};\n strings\n .split('\\n')\n .filter((line) => line.startsWith('\"') && line.endsWith(';'))\n .map((line) => line.trim().slice(0, -1))\n .forEach((line) => {\n const eqIdx = line.indexOf(' = ');\n if (eqIdx === -1) return;\n const key = line.slice(1, eqIdx - 1);\n const value = line.slice(eqIdx + 3 + 1, -1);\n if (!key) return;\n parsedObj[key] = value;\n });\n\n return parsedObj;\n};","import { timingSafeEqual } from 'node:crypto';\nimport type { CMSProvider } from './types';\nimport type {\n FetchCmsBundlesOptions,\n FetchTranslationBundlesOptions,\n TranslationBundleInfo,\n} from './bundles';\n\nexport type ContentRefreshScope = 'cms' | 'translations' | 'all';\n\nexport interface ContentRefreshRequest {\n scope?: ContentRefreshScope;\n cms?: CMSProvider;\n content_types?: string[];\n projects?: string[];\n locales?: string[];\n}\n\n/** Defaults applied when the request omits fields (set by the host application). */\nexport interface ContentRefreshDefaults {\n scope?: ContentRefreshScope;\n cms?: CMSProvider;\n contentTypes?: string[];\n translationProjects?: string[];\n locales?: string[];\n}\n\nexport interface ContentRefreshError {\n step: string;\n message: string;\n}\n\nexport interface ContentRefreshResult {\n ok: boolean;\n scope: ContentRefreshScope;\n cmsFiles?: Record<string, string>;\n translationFiles?: TranslationBundleInfo;\n errors: ContentRefreshError[];\n durationMs: number;\n}\n\nexport interface ContentRefreshFetchers {\n fetchCmsBundles: (\n options: FetchCmsBundlesOptions,\n ) => Promise<Record<string, string>>;\n fetchTranslationBundles: (\n options: FetchTranslationBundlesOptions,\n ) => Promise<TranslationBundleInfo>;\n}\n\nexport function resolveContentRefreshScope(\n request: ContentRefreshRequest,\n defaults: ContentRefreshDefaults,\n): ContentRefreshScope {\n return request.scope ?? defaults.scope ?? 'cms';\n}\n\n/** Base64 of `username:password` (value only — prefix with `Basic ` in the header). */\nexport function encodeBasicAuthCredentials(\n username: string,\n password: string,\n): string {\n return Buffer.from(`${username}:${password}`, 'utf8').toString('base64');\n}\n\n/**\n * Validates `Authorization: Basic <base64>` against the expected credentials\n * (base64 of `user:pass`, same as staging site basic auth).\n */\nexport function assertContentRefreshBasicAuth(\n authorizationHeader: string | undefined,\n expectedCredentialsBase64: string,\n): void {\n if (!expectedCredentialsBase64) {\n throw new ContentRefreshAuthError(\n 'Content refresh basic auth is not configured (set CONTENT_REFRESH_BASIC_AUTH)',\n 500,\n );\n }\n if (!authorizationHeader?.startsWith('Basic ')) {\n throw new ContentRefreshAuthError(\n 'Missing or malformed Authorization header (expected Basic)',\n 401,\n );\n }\n const provided = authorizationHeader.slice(6).trim();\n const bufA = new TextEncoder().encode(provided);\n const bufB = new TextEncoder().encode(expectedCredentialsBase64);\n if (bufA.byteLength !== bufB.byteLength || !timingSafeEqual(bufA, bufB)) {\n throw new ContentRefreshAuthError('Invalid basic auth credentials', 403);\n }\n}\n\nexport class ContentRefreshAuthError extends Error {\n constructor(\n message: string,\n readonly statusCode: number,\n ) {\n super(message);\n this.name = 'ContentRefreshAuthError';\n }\n}\n\n/**\n * Pull the latest bundles from S3 into the host app's configured output directory.\n */\nexport async function executeContentRefresh(\n fetchers: ContentRefreshFetchers,\n request: ContentRefreshRequest,\n defaults: ContentRefreshDefaults = {},\n): Promise<ContentRefreshResult> {\n const started = Date.now();\n const scope = resolveContentRefreshScope(request, defaults);\n const errors: ContentRefreshError[] = [];\n let cmsFiles: Record<string, string> | undefined;\n let translationFiles: TranslationBundleInfo | undefined;\n\n if (scope === 'cms' || scope === 'all') {\n const cms = request.cms ?? defaults.cms ?? 'contentful';\n const contentTypes = request.content_types ?? defaults.contentTypes;\n if (!contentTypes?.length) {\n errors.push({\n step: 'cms',\n message: 'content_types (or handler defaults.contentTypes) is required for CMS refresh',\n });\n } else {\n try {\n cmsFiles = await fetchers.fetchCmsBundles({ cms, contentTypes });\n } catch (err) {\n errors.push({\n step: 'cms',\n message: err instanceof Error ? err.message : String(err),\n });\n }\n }\n }\n\n if (scope === 'translations' || scope === 'all') {\n const projects = request.projects ?? defaults.translationProjects;\n if (!projects?.length) {\n errors.push({\n step: 'translations',\n message:\n 'projects (or handler defaults.translationProjects) is required for translation refresh',\n });\n } else {\n const locales = request.locales ?? defaults.locales;\n try {\n const projectMap = Object.fromEntries(\n projects.map((p) => [p, [] as string[]]),\n );\n translationFiles = await fetchers.fetchTranslationBundles({\n projects: projectMap,\n locales,\n });\n } catch (err) {\n errors.push({\n step: 'translations',\n message: err instanceof Error ? err.message : String(err),\n });\n }\n }\n }\n\n return {\n ok: errors.length === 0,\n scope,\n cmsFiles,\n translationFiles,\n errors,\n durationMs: Date.now() - started,\n };\n}\n\nexport interface PostContentRefreshResponse {\n target: string;\n ok: boolean;\n status: number;\n body?: unknown;\n error?: string;\n}\n\n/**\n * Ask a remote application (web-site, web-app, …) to refresh its local content cache.\n */\nexport async function postContentRefresh(\n target: string,\n url: string,\n basicAuth: string,\n request: ContentRefreshRequest,\n): Promise<PostContentRefreshResponse> {\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n Authorization: `Basic ${basicAuth}`,\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n },\n body: JSON.stringify(request),\n });\n\n const text = await response.text();\n let body: unknown;\n if (text) {\n try {\n body = JSON.parse(text) as unknown;\n } catch {\n body = text;\n }\n }\n\n return {\n target,\n ok: response.ok,\n status: response.status,\n body,\n error: response.ok\n ? undefined\n : typeof body === 'object' && body !== null && 'error' in body\n ? String((body as { error: unknown }).error)\n : `HTTP ${response.status}`,\n };\n } catch (err) {\n return {\n target,\n ok: false,\n status: 0,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n","import type { CMSProvider } from '../shared/types';\nimport { ContentStore } from '../shared/s3';\nimport {\n fetchCmsBundles,\n fetchMergedTranslationBundles,\n fetchTranslationBundles,\n queryCmsBundle,\n type FetchCmsBundlesOptions,\n type FetchMergedTranslationBundlesOptions,\n type FetchTranslationBundlesOptions,\n type QueryOptions,\n type TranslationBundleInfo,\n} from '../shared/bundles';\nimport {\n executeContentRefresh,\n type ContentRefreshDefaults,\n type ContentRefreshRequest,\n type ContentRefreshResult,\n} from '../shared/content-refresh';\nimport type { SDKConfig } from './client-types';\n\nexport type {\n ContentRefreshDefaults,\n ContentRefreshRequest,\n ContentRefreshResult,\n ContentRefreshScope,\n} from '../shared/content-refresh';\nexport type {\n FetchCmsBundlesOptions,\n FetchTranslationBundlesOptions,\n FetchMergedTranslationBundlesOptions,\n TranslationFilterConfig,\n QueryOptions,\n CmsBundleInfo,\n TranslationBundleInfo,\n BundleItem,\n SDKConfig,\n S3RetryConfig,\n} from './client-types';\nexport { getDefaultS3RetryConfig } from './client-types';\n\nexport class ContentStoreSDK {\n private store: ContentStore;\n private outputDir: string;\n\n constructor(config: SDKConfig) {\n this.store = new ContentStore(config.s3);\n this.outputDir = config.outputDir;\n }\n\n /**\n * Downloads the latest bundles from S3 and writes them as JSON files\n * to `outputDir`.\n *\n * @returns A map of contentType to absolute file path.\n */\n async fetchCmsBundles(\n options: FetchCmsBundlesOptions,\n ): Promise<Record<string, string>> {\n return fetchCmsBundles(this.store, this.outputDir, options);\n }\n\n /**\n * Downloads translation bundles from S3 and writes them as JSON files\n * to `outputDir`.\n *\n * @returns Per project, a map of S3 object key to absolute file path.\n */\n async fetchTranslationBundles(\n options: FetchTranslationBundlesOptions,\n ): Promise<TranslationBundleInfo> {\n return fetchTranslationBundles(this.store, this.outputDir, options);\n }\n\n /**\n * Downloads all translation resources for the given projects/locales, parses them,\n * and writes one merged `{locale}.json` per locale (string key/value map; duplicate keys:\n * last wins).\n */\n async fetchMergedTranslationBundles(\n options: FetchMergedTranslationBundlesOptions,\n ): Promise<Record<string, string>> {\n return fetchMergedTranslationBundles(this.store, this.outputDir, options);\n }\n\n /**\n * Queries a previously fetched bundle from the local filesystem.\n */\n async queryCmsBundle(\n cms: CMSProvider,\n contentType: string,\n options: QueryOptions = {},\n ): Promise<unknown[]> {\n return queryCmsBundle(this.outputDir, cms, contentType, options);\n }\n\n /**\n * Download the latest bundles from S3 (same as the hosted refresh HTTP endpoint).\n */\n async refreshContent(\n request: ContentRefreshRequest = {},\n defaults: ContentRefreshDefaults = {},\n ): Promise<ContentRefreshResult> {\n return executeContentRefresh(\n {\n fetchCmsBundles: (opts) => this.fetchCmsBundles(opts),\n fetchTranslationBundles: (opts) => this.fetchTranslationBundles(opts),\n },\n request,\n defaults,\n );\n }\n}\n","import type { ContentStoreSDK } from './client';\nimport {\n assertContentRefreshBasicAuth,\n ContentRefreshAuthError,\n executeContentRefresh,\n type ContentRefreshDefaults,\n type ContentRefreshRequest,\n type ContentRefreshResult,\n} from '../shared/content-refresh';\n\n/** Minimal request shape for Next.js Pages API routes (`pages/api/*`). */\nexport interface NextPagesContentRefreshRequest {\n method?: string;\n headers: { authorization?: string | string[] };\n body?: ContentRefreshRequest;\n}\n\n/** Minimal response shape for Next.js Pages API routes. */\nexport interface NextPagesContentRefreshResponse {\n status(code: number): { json(body: unknown): void };\n}\n\nexport interface NextContentRefreshHandlerConfig {\n sdk: ContentStoreSDK;\n /** Base64 of `username:password` (same value as `CONTENT_REFRESH_BASIC_AUTH`). */\n basicAuth: string;\n defaults?: ContentRefreshDefaults;\n}\n\n/** @deprecated Use {@link NextContentRefreshHandlerConfig}. */\nexport type NextPagesContentRefreshHandlerConfig = NextContentRefreshHandlerConfig;\n\nfunction readAuthorizationHeader(\n value: string | string[] | null | undefined,\n): string | undefined {\n if (value == null) {\n return undefined;\n }\n if (Array.isArray(value)) {\n return value[0];\n }\n return value;\n}\n\nasync function runContentRefresh(\n config: NextContentRefreshHandlerConfig,\n authorization: string | undefined,\n body: ContentRefreshRequest,\n): Promise<{ status: number; body: ContentRefreshResult | { error: string } }> {\n const { sdk, basicAuth, defaults = {} } = config;\n\n try {\n assertContentRefreshBasicAuth(authorization, basicAuth);\n } catch (err) {\n if (err instanceof ContentRefreshAuthError) {\n return { status: err.statusCode, body: { error: err.message } };\n }\n throw err;\n }\n\n const result = await executeContentRefresh(\n {\n fetchCmsBundles: (opts) => sdk.fetchCmsBundles(opts),\n fetchTranslationBundles: (opts) => sdk.fetchTranslationBundles(opts),\n },\n body,\n defaults,\n );\n\n const status = result.ok ? 200 : result.errors.length > 0 ? 207 : 500;\n return { status, body: result };\n}\n\n/**\n * Handler for a Next.js Pages API route (e.g. pages/api/internal/content-refresh.ts).\n */\nexport function createNextPagesApiContentRefreshHandler(\n config: NextContentRefreshHandlerConfig,\n): (\n req: NextPagesContentRefreshRequest,\n res: NextPagesContentRefreshResponse,\n) => Promise<void> {\n return async (req, res): Promise<void> => {\n if (req.method !== 'POST') {\n res.status(405).json({ error: 'Method not allowed' });\n return;\n }\n\n const { status, body } = await runContentRefresh(\n config,\n readAuthorizationHeader(req.headers.authorization),\n req.body ?? {},\n );\n res.status(status).json(body);\n };\n}\n\n/**\n * Handler for a Next.js App Router route (e.g. app/api/internal/content-refresh/route.ts).\n */\nexport async function handleNextAppRouterContentRefresh(\n request: Request,\n config: NextContentRefreshHandlerConfig,\n): Promise<Response> {\n if (request.method !== 'POST') {\n return Response.json({ error: 'Method not allowed' }, { status: 405 });\n }\n\n let body: ContentRefreshRequest = {};\n try {\n body = (await request.json()) as ContentRefreshRequest;\n } catch {\n return Response.json({ error: 'Invalid JSON body' }, { status: 400 });\n }\n\n const { status, body: payload } = await runContentRefresh(\n config,\n request.headers.get('authorization') ?? undefined,\n body,\n );\n\n return Response.json(payload, { status });\n}\n"],"mappings":"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","names":["path","path","out","path"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tandem-language-exchange/content-store",
3
- "version": "1.3.8",
3
+ "version": "1.3.9",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/shared/lingohub.ts"],"sourcesContent":["export const defaultLocales = ['de', 'en', 'es', 'fr', 'it', 'ja', 'ko', 'pt-br', 'ru', 'th', 'uk', 'vi', 'zh-hans', 'zh-hant'];\n\nconst localeMapping = {\n ios: {\n 'pt-br': 'pt',\n 'zh-hans': 'zh-Hans',\n 'zh-hant': 'zh-Hant',\n },\n android: {\n 'pt-br': 'pt',\n 'zh-hans': 'zh-Hans-CN',\n 'zh-hant': 'zh-TW',\n },\n invites: {\n 'prs': 'fa',\n },\n website: {\n 'prs': 'fa',\n },\n};\n\nexport type LingohubResource = {\n resource: string,\n fileName: string;\n type: 'json'|'strings'|'xml';\n localeMapping?: Record<string, string>;\n locales?: string[]\n}\n\nexport const allProjects: Record<string, LingohubResource[]> = {\n 'tandem-(new-website)': [\n {\n resource: 'main',\n fileName: 'Website.[locale].json',\n type: 'json',\n locales: ['de', 'en', 'es', 'fr', 'it', 'ja', 'ko', 'pt-br', 'ru', 'zh-hans', 'zh-hant']\n }\n ],\n 'tandem-(website)': [\n {\n resource: 'main',\n fileName: '[locale].json',\n type: 'json',\n locales: ['ar', 'de', 'en', 'es', 'fr', 'it', 'ja', 'ko', 'pt-br', 'prs', 'ps', 'ru', 'th', 'uk', 'vi', 'zh-hans', 'zh-hant'],\n localeMapping: localeMapping.website,\n },\n {\n resource: 'ai',\n fileName: 'AI.[locale].json',\n type: 'json'\n },\n {\n resource: 'languages',\n fileName: 'languages.[locale].json',\n type: 'json'\n }\n ],\n 'tandem': [\n {\n resource: 'infoplist',\n fileName: 'InfoPlist.[locale].strings',\n type: 'strings',\n localeMapping: localeMapping.ios,\n },\n {\n resource: 'localizable',\n fileName: 'Localizable.[locale].strings',\n type: 'strings',\n localeMapping: localeMapping.ios,\n },\n {\n resource: 'ipad',\n fileName: 'Main_iPad.[locale].strings',\n type: 'strings',\n localeMapping: localeMapping.ios,\n },\n {\n resource: 'main',\n fileName: 'Main.[locale].strings',\n type: 'strings',\n localeMapping: localeMapping.ios,\n }\n ],\n 'tandem-(android)': [\n {\n resource: 'accessibility',\n fileName: 'accessibility_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'call',\n fileName: 'call_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'cert',\n fileName: 'cert_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'chat',\n fileName: 'chat_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'checklist',\n fileName: 'checklist_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'clubs',\n fileName: 'clubs_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'common',\n fileName: 'common_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'community',\n fileName: 'community_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'correction',\n fileName: 'correction_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'country_names',\n fileName: 'country_names.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'emoji',\n fileName: 'emoji_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'errors',\n fileName: 'errors.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'expressions',\n fileName: 'expressions_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'gif',\n fileName: 'gif_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'guidelines',\n fileName: 'guidelines_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'lanuguages',\n fileName: 'languages_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'localizable',\n fileName: 'localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'localizable2',\n fileName: 'localizable2.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'login',\n fileName: 'login_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'myprofile',\n fileName: 'myprofile_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'onb',\n fileName: 'onb_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'parties',\n fileName: 'parties_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'pro',\n fileName: 'pro_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'pro_screen',\n fileName: 'pro_screen_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'push_notification',\n fileName: 'push_notification_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'reporting',\n fileName: 'reporting_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n },\n {\n resource: 'translation',\n fileName: 'translation_localizable.[locale].xml',\n type: 'xml',\n localeMapping: localeMapping.android,\n }\n\n ],\n 'tandem-(web-invites)': [\n {\n resource: 'main',\n fileName: '[locale].json',\n type: 'json',\n locales: ['ar', 'de', 'en', 'es', 'fr', 'it', 'ja', 'ko', 'prs', 'ps', 'pt-br', 'ru', 'uk', 'zh-hans', 'zh-hant'],\n localeMapping: localeMapping.invites,\n }\n ]\n};\n"],"mappings":"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","names":[]}