@tandem-language-exchange/content-store 1.2.0 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -13
- package/dist/chunk-4DE47ZJD.js +19 -0
- package/dist/chunk-4DE47ZJD.js.map +1 -0
- package/dist/{chunk-YZSLCPN6.js → chunk-6FXNAJSI.js} +160 -14
- package/dist/chunk-6FXNAJSI.js.map +1 -0
- package/dist/{chunk-UCBZUEUP.js → chunk-BAJT7RMQ.js} +31 -69
- package/dist/chunk-BAJT7RMQ.js.map +1 -0
- package/dist/{chunk-XP3USUQC.js → chunk-EQ3DSPTJ.js} +6 -2
- package/dist/{chunk-XP3USUQC.js.map → chunk-EQ3DSPTJ.js.map} +1 -1
- package/dist/chunk-UPIQFNCR.js +17 -0
- package/dist/chunk-UPIQFNCR.js.map +1 -0
- package/dist/{chunk-VRWRAFDK.js → chunk-VKXN2SE6.js} +79 -24
- package/dist/chunk-VKXN2SE6.js.map +1 -0
- package/dist/client/fetch-content-bundles.js +7 -4
- package/dist/client/fetch-content-bundles.js.map +1 -1
- package/dist/client/fetch-merged-translation-bundles.js +46 -0
- package/dist/client/fetch-merged-translation-bundles.js.map +1 -0
- package/dist/client/fetch-translation-bundles.js +22 -11
- package/dist/client/fetch-translation-bundles.js.map +1 -1
- package/dist/client/query-cms.js +33 -0
- package/dist/client/query-cms.js.map +1 -0
- package/dist/{index-Db97SUTy.d.ts → index-PQ7XN47c.d.ts} +36 -7
- package/dist/index.d.ts +1 -1
- package/dist/node.browser.js +7 -0
- package/dist/node.browser.js.map +1 -1
- package/dist/node.d.ts +9 -3
- package/dist/node.js +237 -15
- package/dist/node.js.map +1 -1
- package/package.json +8 -5
- package/dist/chunk-UCBZUEUP.js.map +0 -1
- package/dist/chunk-VRWRAFDK.js.map +0 -1
- package/dist/chunk-YZSLCPN6.js.map +0 -1
- package/dist/client/cli.js +0 -82
- package/dist/client/cli.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/client/fetch-translation-bundles.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { config
|
|
1
|
+
{"version":3,"sources":["../../src/client/fetch-translation-bundles.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { Command } from 'commander';\nimport { config } from './config';\nimport { ContentStore } from '../shared/s3';\nimport { fetchTranslationBundles, type TranslationFilterConfig } from '../shared/bundles';\n\nconst program = new Command();\n\nprogram\n .name('fetch-translation-bundles')\n .description(\n 'Download latest translation bundles from S3 to the local filesystem.\\n\\n' +\n 'Accepts a JSON config file that specifies projects, resources, and locales.\\n' +\n 'Example config:\\n' +\n ' { \"projects\": { \"tandem\": [], \"tandem-(website)\": [\"main\",\"ai\"] }, \"locales\": [\"en\",\"de\"] }',\n )\n .requiredOption(\n '--config <filepath>',\n 'Path to a JSON config file defining projects, resources, and locales',\n )\n .option('--output <directory>', 'Output directory', './content-cache')\n .action(async (opts: { config: string; output: string }) => {\n let filterConfig: TranslationFilterConfig;\n try {\n filterConfig = JSON.parse(fs.readFileSync(opts.config, 'utf-8'));\n } catch (err) {\n console.error(`Failed to read config file \"${opts.config}\":`, err);\n process.exit(1);\n }\n\n const store = new ContentStore(config.s3);\n\n try {\n const files = await fetchTranslationBundles(store, opts.output, filterConfig);\n\n console.log('Fetched bundles:');\n for (const [project, pathsByKey] of Object.entries(files)) {\n console.log(` ${project}:`);\n for (const [objectKey, filePath] of Object.entries(pathsByKey)) {\n console.log(` ${objectKey} -> ${filePath}`);\n }\n }\n } catch (err) {\n console.error('Fetch failed:', err);\n process.exit(1);\n }\n });\n\nprogram.parse();"],"mappings":";;;;;;;;;;;;;;AAAA,OAAO,QAAQ;AACf,SAAS,eAAe;AAKxB,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACK,KAAK,2BAA2B,EAChC;AAAA,EACC;AAIF,EACC;AAAA,EACC;AAAA,EACA;AACF,EACC,OAAO,wBAAwB,oBAAoB,iBAAiB,EACpE,OAAO,OAAO,SAA6C;AACxD,MAAI;AACJ,MAAI;AACA,mBAAe,KAAK,MAAM,GAAG,aAAa,KAAK,QAAQ,OAAO,CAAC;AAAA,EACnE,SAAS,KAAK;AACV,YAAQ,MAAM,+BAA+B,KAAK,MAAM,MAAM,GAAG;AACjE,YAAQ,KAAK,CAAC;AAAA,EAClB;AAEA,QAAM,QAAQ,IAAI,aAAa,OAAO,EAAE;AAExC,MAAI;AACA,UAAM,QAAQ,MAAM,wBAAwB,OAAO,KAAK,QAAQ,YAAY;AAE5E,YAAQ,IAAI,kBAAkB;AAC9B,eAAW,CAAC,SAAS,UAAU,KAAK,OAAO,QAAQ,KAAK,GAAG;AACvD,cAAQ,IAAI,KAAK,OAAO,GAAG;AAC3B,iBAAW,CAAC,WAAW,QAAQ,KAAK,OAAO,QAAQ,UAAU,GAAG;AAC5D,gBAAQ,IAAI,OAAO,SAAS,OAAO,QAAQ,EAAE;AAAA,MACjD;AAAA,IACJ;AAAA,EACJ,SAAS,KAAK;AACV,YAAQ,MAAM,iBAAiB,GAAG;AAClC,YAAQ,KAAK,CAAC;AAAA,EAClB;AACJ,CAAC;AAEL,QAAQ,MAAM;","names":[]}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
queryCmsBundle
|
|
4
|
+
} from "../chunk-VKXN2SE6.js";
|
|
5
|
+
import "../chunk-EQ3DSPTJ.js";
|
|
6
|
+
import "../chunk-6FXNAJSI.js";
|
|
7
|
+
|
|
8
|
+
// src/client/query-cms.ts
|
|
9
|
+
import { Command } from "commander";
|
|
10
|
+
var program = new Command();
|
|
11
|
+
program.name("query-cms").description("Query a previously fetched CMS bundle from the local filesystem").requiredOption("--cms <provider>", "CMS provider: contentful | sanity").requiredOption("--type <type>", "Content type to query").option("--output <directory>", "Directory where bundles are stored", "./content-cache").option("--fields <json>", `Filter by fields (JSON object, e.g. '{"columns":"2"}')`).option("--select <props>", "Comma-separated properties to include in results").option("--limit <n>", "Maximum number of results", parseInt).option("--include <n>", "Depth of nested references to include", parseInt).action(
|
|
12
|
+
async (opts) => {
|
|
13
|
+
const cms = opts.cms;
|
|
14
|
+
if (!["contentful", "sanity"].includes(cms)) {
|
|
15
|
+
console.error(`Invalid CMS provider: ${cms}`);
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
const results = await queryCmsBundle(opts.output, cms, opts.type, {
|
|
20
|
+
fields: opts.fields ? JSON.parse(opts.fields) : void 0,
|
|
21
|
+
select: opts.select ? opts.select.split(",").map((s) => s.trim()) : void 0,
|
|
22
|
+
limit: opts.limit,
|
|
23
|
+
include: opts.include
|
|
24
|
+
});
|
|
25
|
+
console.log(JSON.stringify(results, null, 2));
|
|
26
|
+
} catch (err) {
|
|
27
|
+
console.error("Query failed:", err);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
program.parse();
|
|
33
|
+
//# sourceMappingURL=query-cms.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/client/query-cms.ts"],"sourcesContent":["import { Command } from 'commander';\nimport type { CMSProvider } from '../shared/types';\nimport { queryCmsBundle } from '../shared/bundles';\n\nconst program = new Command();\n\nprogram\n .name('query-cms')\n .description('Query a previously fetched CMS bundle from the local filesystem')\n .requiredOption('--cms <provider>', 'CMS provider: contentful | sanity')\n .requiredOption('--type <type>', 'Content type to query')\n .option('--output <directory>', 'Directory where bundles are stored', './content-cache')\n .option('--fields <json>', 'Filter by fields (JSON object, e.g. \\'{\"columns\":\"2\"}\\')')\n .option('--select <props>', 'Comma-separated properties to include in results')\n .option('--limit <n>', 'Maximum number of results', parseInt)\n .option('--include <n>', 'Depth of nested references to include', parseInt)\n .action(\n async (opts: {\n cms: string;\n type: string;\n output: string;\n fields?: string;\n select?: string;\n limit?: number;\n include?: number;\n }) => {\n const cms = opts.cms as CMSProvider;\n\n if (!['contentful', 'sanity'].includes(cms)) {\n console.error(`Invalid CMS provider: ${cms}`);\n process.exit(1);\n }\n\n try {\n const results = await queryCmsBundle(opts.output, cms, opts.type, {\n fields: opts.fields ? JSON.parse(opts.fields) : undefined,\n select: opts.select\n ? opts.select.split(',').map((s) => s.trim())\n : undefined,\n limit: opts.limit,\n include: opts.include,\n });\n\n console.log(JSON.stringify(results, null, 2));\n } catch (err) {\n console.error('Query failed:', err);\n process.exit(1);\n }\n },\n );\n\nprogram.parse();"],"mappings":";;;;;;;;AAAA,SAAS,eAAe;AAIxB,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACK,KAAK,WAAW,EAChB,YAAY,iEAAiE,EAC7E,eAAe,oBAAoB,mCAAmC,EACtE,eAAe,iBAAiB,uBAAuB,EACvD,OAAO,wBAAwB,sCAAsC,iBAAiB,EACtF,OAAO,mBAAmB,wDAA0D,EACpF,OAAO,oBAAoB,kDAAkD,EAC7E,OAAO,eAAe,6BAA6B,QAAQ,EAC3D,OAAO,iBAAiB,yCAAyC,QAAQ,EACzE;AAAA,EACG,OAAO,SAQD;AACF,UAAM,MAAM,KAAK;AAEjB,QAAI,CAAC,CAAC,cAAc,QAAQ,EAAE,SAAS,GAAG,GAAG;AACzC,cAAQ,MAAM,yBAAyB,GAAG,EAAE;AAC5C,cAAQ,KAAK,CAAC;AAAA,IAClB;AAEA,QAAI;AACA,YAAM,UAAU,MAAM,eAAe,KAAK,QAAQ,KAAK,KAAK,MAAM;AAAA,QAC9D,QAAQ,KAAK,SAAS,KAAK,MAAM,KAAK,MAAM,IAAI;AAAA,QAChD,QAAQ,KAAK,SACP,KAAK,OAAO,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,IAC1C;AAAA,QACN,OAAO,KAAK;AAAA,QACZ,SAAS,KAAK;AAAA,MAClB,CAAC;AAED,cAAQ,IAAI,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAAA,IAChD,SAAS,KAAK;AACV,cAAQ,MAAM,iBAAiB,GAAG;AAClC,cAAQ,KAAK,CAAC;AAAA,IAClB;AAAA,EACJ;AACJ;AAEJ,QAAQ,MAAM;","names":[]}
|
|
@@ -11,7 +11,11 @@ declare class ContentStore {
|
|
|
11
11
|
private bucket;
|
|
12
12
|
constructor(cfg: S3Config);
|
|
13
13
|
upload(key: string, data: unknown): Promise<string>;
|
|
14
|
+
/** Raw UTF-8 body (e.g. Lingohub file bytes as text). */
|
|
15
|
+
uploadRaw(key: string, body: string, contentType: string): Promise<string>;
|
|
14
16
|
download(key: string): Promise<unknown>;
|
|
17
|
+
/** Raw UTF-8 body from S3 (no JSON.parse). */
|
|
18
|
+
downloadRaw(key: string): Promise<string>;
|
|
15
19
|
}
|
|
16
20
|
|
|
17
21
|
/** Retry/backoff for S3 reads (aligned with CMS `RetryConfig` shape). */
|
|
@@ -41,12 +45,33 @@ interface FetchCmsBundlesOptions {
|
|
|
41
45
|
/** S3 GET retry; defaults via {@link getDefaultS3RetryConfig}. */
|
|
42
46
|
retry?: S3RetryConfig;
|
|
43
47
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
48
|
+
/**
|
|
49
|
+
* Config-file-friendly shape used by `fetchTranslationBundles` and the CLI.
|
|
50
|
+
*
|
|
51
|
+
* ```json
|
|
52
|
+
* {
|
|
53
|
+
* "projects": {
|
|
54
|
+
* "tandem": [],
|
|
55
|
+
* "tandem-(website)": ["main", "ai"]
|
|
56
|
+
* },
|
|
57
|
+
* "locales": ["en", "de", "it"]
|
|
58
|
+
* }
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* `projects` maps each Lingohub project id to an array of resource keys.
|
|
62
|
+
* An empty array means **all** resources for that project.
|
|
63
|
+
* `locales` is optional — omit (or pass `[]`) to fetch the default locale set.
|
|
64
|
+
*/
|
|
65
|
+
interface TranslationFilterConfig {
|
|
66
|
+
projects: Record<string, string[]>;
|
|
67
|
+
locales?: string[];
|
|
68
|
+
}
|
|
69
|
+
interface FetchTranslationBundlesOptions extends TranslationFilterConfig {
|
|
47
70
|
/** S3 GET retry; defaults via {@link getDefaultS3RetryConfig}. */
|
|
48
71
|
retry?: S3RetryConfig;
|
|
49
72
|
}
|
|
73
|
+
/** One merged JSON file per catalog locale (`en.json`, …). Same options as {@link FetchTranslationBundlesOptions}. */
|
|
74
|
+
type FetchMergedTranslationBundlesOptions = FetchTranslationBundlesOptions;
|
|
50
75
|
interface QueryOptions {
|
|
51
76
|
/**
|
|
52
77
|
* Filter items by matching property values (exact equality, or array for IN).
|
|
@@ -83,12 +108,16 @@ interface QueryOptions {
|
|
|
83
108
|
* @returns A map of contentType to absolute file path.
|
|
84
109
|
*/
|
|
85
110
|
declare function fetchCmsBundles(store: ContentStore, outputDir: string, options: FetchCmsBundlesOptions): Promise<Record<string, string>>;
|
|
111
|
+
declare function fetchTranslationBundles(store: ContentStore, outputDir: string, options: FetchTranslationBundlesOptions): Promise<TranslationBundleInfo>;
|
|
86
112
|
/**
|
|
87
|
-
* Downloads
|
|
113
|
+
* Downloads translation bundles from S3, parses each raw Lingohub file, and merges all
|
|
114
|
+
* key/value pairs per **catalog** locale into a single JSON file (e.g. `en.json`).
|
|
115
|
+
* Duplicate keys across resources or projects: **last write wins** (iteration order:
|
|
116
|
+
* projects → resources → locales).
|
|
88
117
|
*
|
|
89
|
-
* @returns
|
|
118
|
+
* @returns Map of locale code to absolute path of the merged `{locale}.json` file.
|
|
90
119
|
*/
|
|
91
|
-
declare function
|
|
120
|
+
declare function fetchMergedTranslationBundles(store: ContentStore, outputDir: string, options: FetchMergedTranslationBundlesOptions): Promise<Record<string, string>>;
|
|
92
121
|
/**
|
|
93
122
|
* Queries a previously fetched bundle from the local filesystem.
|
|
94
123
|
*/
|
|
@@ -100,4 +129,4 @@ interface SDKConfig {
|
|
|
100
129
|
outputDir: string;
|
|
101
130
|
}
|
|
102
131
|
|
|
103
|
-
export { type BundleItem as B, type CMSProvider as C, type FetchCmsBundlesOptions as F, type QueryOptions as Q, type SDKConfig as S, type TranslationBundleInfo as T, type FetchTranslationBundlesOptions as a, type
|
|
132
|
+
export { type BundleItem as B, type CMSProvider as C, type FetchCmsBundlesOptions as F, type QueryOptions as Q, type SDKConfig as S, type TranslationBundleInfo as T, type FetchTranslationBundlesOptions as a, type FetchMergedTranslationBundlesOptions as b, type CmsBundleInfo as c, ContentStore as d, type S3Config as e, type S3RetryConfig as f, type TranslationFilterConfig as g, fetchCmsBundles as h, fetchMergedTranslationBundles as i, fetchTranslationBundles as j, getDefaultS3RetryConfig as k, queryCmsBundle as q };
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { B as BundleItem, C as CMSProvider,
|
|
1
|
+
export { B as BundleItem, C as CMSProvider, c as CmsBundleInfo, F as FetchCmsBundlesOptions, b as FetchMergedTranslationBundlesOptions, a as FetchTranslationBundlesOptions, Q as QueryOptions, e as S3Config, f as S3RetryConfig, S as SDKConfig, T as TranslationBundleInfo, g as TranslationFilterConfig } from './index-PQ7XN47c.js';
|
package/dist/node.browser.js
CHANGED
|
@@ -45,6 +45,9 @@ var ContentStoreSDK = class {
|
|
|
45
45
|
fetchTranslationBundles() {
|
|
46
46
|
return Promise.reject(new Error(SERVER_ONLY));
|
|
47
47
|
}
|
|
48
|
+
fetchMergedTranslationBundles() {
|
|
49
|
+
return Promise.reject(new Error(SERVER_ONLY));
|
|
50
|
+
}
|
|
48
51
|
};
|
|
49
52
|
var ContentStore = class {
|
|
50
53
|
constructor(_cfg) {
|
|
@@ -60,10 +63,14 @@ async function queryCmsBundle() {
|
|
|
60
63
|
async function fetchTranslationBundles() {
|
|
61
64
|
serverOnly();
|
|
62
65
|
}
|
|
66
|
+
async function fetchMergedTranslationBundles() {
|
|
67
|
+
serverOnly();
|
|
68
|
+
}
|
|
63
69
|
export {
|
|
64
70
|
ContentStore,
|
|
65
71
|
ContentStoreSDK,
|
|
66
72
|
fetchCmsBundles,
|
|
73
|
+
fetchMergedTranslationBundles,
|
|
67
74
|
fetchTranslationBundles,
|
|
68
75
|
queryCmsBundle,
|
|
69
76
|
trimDepth
|
package/dist/node.browser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shared/trimDepth.ts","../src/node.browser.ts"],"sourcesContent":["/**\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","/**\n * Browser / client-bundler entry for `@tandem-language-exchange/content-store/node`.\n * Next.js and Turbopack resolve this when the `browser` condition applies, so `fs`\n * is never pulled into client chunks.\n *\n * Server-only APIs throw if called; `trimDepth` is real and safe everywhere.\n */\nexport type {\n SDKConfig,\n FetchCmsBundlesOptions,\n FetchTranslationBundlesOptions,\n QueryOptions,\n CmsBundleInfo,\n TranslationBundleInfo,\n BundleItem,\n} from './sdk/client-types';\nexport type { CMSProvider, S3Config } from './shared/types';\n\nexport { trimDepth } from './shared/trimDepth';\n\nconst SERVER_ONLY =\n '@tandem-language-exchange/content-store/node uses the filesystem and S3 and only runs on the server. ' +\n 'Import it from getServerSideProps, Route Handlers, or \"use server\" modules — not from _app, layouts, or client components. ' +\n 'You can use `import type { ... } from \"@tandem-language-exchange/content-store\"` in shared code.';\n\nfunction serverOnly(): never {\n throw new Error(SERVER_ONLY);\n}\n\nexport class ContentStoreSDK {\n constructor(_config: unknown) {\n serverOnly();\n }\n\n fetchCmsBundles(): Promise<never> {\n return Promise.reject(new Error(SERVER_ONLY));\n }\n\n queryCmsBundle(): Promise<never> {\n return Promise.reject(new Error(SERVER_ONLY));\n }\n\n fetchTranslationBundles(): Promise<never> {\n return Promise.reject(new Error(SERVER_ONLY));\n }\n}\n\nexport class ContentStore {\n constructor(_cfg: unknown) {\n serverOnly();\n }\n}\n\nexport async function fetchCmsBundles(): Promise<never> {\n serverOnly();\n}\n\nexport async function queryCmsBundle(): Promise<never> {\n serverOnly();\n}\n\nexport async function fetchTranslationBundles(): Promise<never> {\n serverOnly();\n}\n"],"mappings":";AAQO,SAAS,UAAU,OAAgB,WAA4B;AACpE,MAAI,UAAU,QAAQ,UAAU,UAAa,OAAO,UAAU,UAAU;AACtE,WAAO;AAAA,EACT;AAEA,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MAAM,IAAI,CAAC,SAAS,UAAU,MAAM,SAAS,CAAC;AAAA,EACvD;AAEA,QAAM,MAAM;AACZ,QAAM,SAAkC,CAAC;AAEzC,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,GAAG,GAAG;AACxC,QAAI,MAAM,QAAQ,MAAM,UAAa,OAAO,MAAM,UAAU;AAC1D,aAAO,CAAC,IAAI;AAAA,IACd,WAAW,aAAa,GAAG;AACzB,aAAO,CAAC,IAAI;AAAA,IACd,WAAW,MAAM,QAAQ,CAAC,GAAG;AAC3B,aAAO,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS;AAC1B,YAAI,SAAS,QAAQ,OAAO,SAAS,YAAY,CAAC,MAAM,QAAQ,IAAI,GAAG;AACrE,iBAAO,UAAU,MAAM,YAAY,CAAC;AAAA,QACtC;AACA,eAAO;AAAA,MACT,CAAC;AAAA,IACH,OAAO;AACL,aAAO,CAAC,IAAI,UAAU,GAAG,YAAY,CAAC;AAAA,IACxC;AAAA,EACF;AAEA,SAAO;AACT;;;
|
|
1
|
+
{"version":3,"sources":["../src/shared/trimDepth.ts","../src/node.browser.ts"],"sourcesContent":["/**\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","/**\n * Browser / client-bundler entry for `@tandem-language-exchange/content-store/node`.\n * Next.js and Turbopack resolve this when the `browser` condition applies, so `fs`\n * is never pulled into client chunks.\n *\n * Server-only APIs throw if called; `trimDepth` is real and safe everywhere.\n */\nexport type {\n SDKConfig,\n FetchCmsBundlesOptions,\n FetchTranslationBundlesOptions,\n FetchMergedTranslationBundlesOptions,\n TranslationFilterConfig,\n QueryOptions,\n CmsBundleInfo,\n TranslationBundleInfo,\n BundleItem,\n} from './sdk/client-types';\nexport type { CMSProvider, S3Config } from './shared/types';\n\nexport { trimDepth } from './shared/trimDepth';\n\nconst SERVER_ONLY =\n '@tandem-language-exchange/content-store/node uses the filesystem and S3 and only runs on the server. ' +\n 'Import it from getServerSideProps, Route Handlers, or \"use server\" modules — not from _app, layouts, or client components. ' +\n 'You can use `import type { ... } from \"@tandem-language-exchange/content-store\"` in shared code.';\n\nfunction serverOnly(): never {\n throw new Error(SERVER_ONLY);\n}\n\nexport class ContentStoreSDK {\n constructor(_config: unknown) {\n serverOnly();\n }\n\n fetchCmsBundles(): Promise<never> {\n return Promise.reject(new Error(SERVER_ONLY));\n }\n\n queryCmsBundle(): Promise<never> {\n return Promise.reject(new Error(SERVER_ONLY));\n }\n\n fetchTranslationBundles(): Promise<never> {\n return Promise.reject(new Error(SERVER_ONLY));\n }\n\n fetchMergedTranslationBundles(): Promise<never> {\n return Promise.reject(new Error(SERVER_ONLY));\n }\n}\n\nexport class ContentStore {\n constructor(_cfg: unknown) {\n serverOnly();\n }\n}\n\nexport async function fetchCmsBundles(): Promise<never> {\n serverOnly();\n}\n\nexport async function queryCmsBundle(): Promise<never> {\n serverOnly();\n}\n\nexport async function fetchTranslationBundles(): Promise<never> {\n serverOnly();\n}\n\nexport async function fetchMergedTranslationBundles(): Promise<never> {\n serverOnly();\n}\n"],"mappings":";AAQO,SAAS,UAAU,OAAgB,WAA4B;AACpE,MAAI,UAAU,QAAQ,UAAU,UAAa,OAAO,UAAU,UAAU;AACtE,WAAO;AAAA,EACT;AAEA,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MAAM,IAAI,CAAC,SAAS,UAAU,MAAM,SAAS,CAAC;AAAA,EACvD;AAEA,QAAM,MAAM;AACZ,QAAM,SAAkC,CAAC;AAEzC,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,GAAG,GAAG;AACxC,QAAI,MAAM,QAAQ,MAAM,UAAa,OAAO,MAAM,UAAU;AAC1D,aAAO,CAAC,IAAI;AAAA,IACd,WAAW,aAAa,GAAG;AACzB,aAAO,CAAC,IAAI;AAAA,IACd,WAAW,MAAM,QAAQ,CAAC,GAAG;AAC3B,aAAO,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS;AAC1B,YAAI,SAAS,QAAQ,OAAO,SAAS,YAAY,CAAC,MAAM,QAAQ,IAAI,GAAG;AACrE,iBAAO,UAAU,MAAM,YAAY,CAAC;AAAA,QACtC;AACA,eAAO;AAAA,MACT,CAAC;AAAA,IACH,OAAO;AACL,aAAO,CAAC,IAAI,UAAU,GAAG,YAAY,CAAC;AAAA,IACxC;AAAA,EACF;AAEA,SAAO;AACT;;;AChBA,IAAM,cACJ;AAIF,SAAS,aAAoB;AAC3B,QAAM,IAAI,MAAM,WAAW;AAC7B;AAEO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,YAAY,SAAkB;AAC5B,eAAW;AAAA,EACb;AAAA,EAEA,kBAAkC;AAChC,WAAO,QAAQ,OAAO,IAAI,MAAM,WAAW,CAAC;AAAA,EAC9C;AAAA,EAEA,iBAAiC;AAC/B,WAAO,QAAQ,OAAO,IAAI,MAAM,WAAW,CAAC;AAAA,EAC9C;AAAA,EAEA,0BAA0C;AACxC,WAAO,QAAQ,OAAO,IAAI,MAAM,WAAW,CAAC;AAAA,EAC9C;AAAA,EAEA,gCAAgD;AAC9C,WAAO,QAAQ,OAAO,IAAI,MAAM,WAAW,CAAC;AAAA,EAC9C;AACF;AAEO,IAAM,eAAN,MAAmB;AAAA,EACxB,YAAY,MAAe;AACzB,eAAW;AAAA,EACb;AACF;AAEA,eAAsB,kBAAkC;AACtD,aAAW;AACb;AAEA,eAAsB,iBAAiC;AACrD,aAAW;AACb;AAEA,eAAsB,0BAA0C;AAC9D,aAAW;AACb;AAEA,eAAsB,gCAAgD;AACpE,aAAW;AACb;","names":[]}
|
package/dist/node.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as SDKConfig, F as FetchCmsBundlesOptions, a as FetchTranslationBundlesOptions, T as TranslationBundleInfo, C as CMSProvider, Q as QueryOptions } from './index-
|
|
2
|
-
export { B as BundleItem,
|
|
1
|
+
import { S as SDKConfig, F as FetchCmsBundlesOptions, a as FetchTranslationBundlesOptions, T as TranslationBundleInfo, b as FetchMergedTranslationBundlesOptions, C as CMSProvider, Q as QueryOptions } from './index-PQ7XN47c.js';
|
|
2
|
+
export { B as BundleItem, c as CmsBundleInfo, d as ContentStore, e as S3Config, f as S3RetryConfig, g as TranslationFilterConfig, h as fetchCmsBundles, i as fetchMergedTranslationBundles, j as fetchTranslationBundles, k as getDefaultS3RetryConfig, q as queryCmsBundle } from './index-PQ7XN47c.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Trims nested object depth.
|
|
@@ -29,10 +29,16 @@ declare class ContentStoreSDK {
|
|
|
29
29
|
* @returns Per project, a map of S3 object key to absolute file path.
|
|
30
30
|
*/
|
|
31
31
|
fetchTranslationBundles(options: FetchTranslationBundlesOptions): Promise<TranslationBundleInfo>;
|
|
32
|
+
/**
|
|
33
|
+
* Downloads all translation resources for the given projects/locales, parses them,
|
|
34
|
+
* and writes one merged `{locale}.json` per locale (string key/value map; duplicate keys:
|
|
35
|
+
* last wins).
|
|
36
|
+
*/
|
|
37
|
+
fetchMergedTranslationBundles(options: FetchMergedTranslationBundlesOptions): Promise<Record<string, string>>;
|
|
32
38
|
/**
|
|
33
39
|
* Queries a previously fetched bundle from the local filesystem.
|
|
34
40
|
*/
|
|
35
41
|
queryCmsBundle(cms: CMSProvider, contentType: string, options?: QueryOptions): Promise<unknown[]>;
|
|
36
42
|
}
|
|
37
43
|
|
|
38
|
-
export { CMSProvider, ContentStoreSDK, FetchCmsBundlesOptions, FetchTranslationBundlesOptions, QueryOptions, SDKConfig, TranslationBundleInfo, trimDepth };
|
|
44
|
+
export { CMSProvider, ContentStoreSDK, FetchCmsBundlesOptions, FetchMergedTranslationBundlesOptions, FetchTranslationBundlesOptions, QueryOptions, SDKConfig, TranslationBundleInfo, trimDepth };
|