@translation-cms/sync 1.2.28 → 1.2.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.d.ts +105 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +208 -0
- package/dist/api.js.map +1 -0
- package/dist/bin.d.ts +25 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +208 -0
- package/dist/bin.js.map +1 -0
- package/dist/commands/init.d.ts +10 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +107 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/pull.d.ts +10 -0
- package/dist/commands/pull.d.ts.map +1 -0
- package/dist/commands/pull.js +35 -0
- package/dist/commands/pull.js.map +1 -0
- package/dist/commands/status.d.ts +15 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +62 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/sync.d.ts +24 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +131 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/watch.d.ts +18 -0
- package/dist/commands/watch.d.ts.map +1 -0
- package/dist/commands/watch.js +71 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/config/config-internals/args.d.ts +11 -0
- package/dist/config/config-internals/args.d.ts.map +1 -0
- package/dist/config/config-internals/args.js +22 -0
- package/dist/config/config-internals/args.js.map +1 -0
- package/dist/config/config-internals/env.d.ts +10 -0
- package/dist/config/config-internals/env.d.ts.map +1 -0
- package/dist/config/config-internals/env.js +35 -0
- package/dist/config/config-internals/env.js.map +1 -0
- package/dist/config/config-internals/file.d.ts +11 -0
- package/dist/config/config-internals/file.d.ts.map +1 -0
- package/dist/config/config-internals/file.js +28 -0
- package/dist/config/config-internals/file.js.map +1 -0
- package/dist/config/config-internals/resolve.d.ts +21 -0
- package/dist/config/config-internals/resolve.d.ts.map +1 -0
- package/dist/config/config-internals/resolve.js +73 -0
- package/dist/config/config-internals/resolve.js.map +1 -0
- package/dist/config/config-internals/root.d.ts +9 -0
- package/dist/config/config-internals/root.d.ts.map +1 -0
- package/dist/config/config-internals/root.js +22 -0
- package/dist/config/config-internals/root.js.map +1 -0
- package/dist/config/config-internals/types.d.ts +91 -0
- package/dist/config/config-internals/types.d.ts.map +1 -0
- package/dist/config/config-internals/types.js +9 -0
- package/dist/config/config-internals/types.js.map +1 -0
- package/dist/config/resolve-config.d.ts +11 -0
- package/dist/config/resolve-config.d.ts.map +1 -0
- package/dist/config/resolve-config.js +10 -0
- package/dist/config/resolve-config.js.map +1 -0
- package/dist/core/api-internals/helpers.d.ts +9 -0
- package/dist/core/api-internals/helpers.d.ts.map +1 -0
- package/dist/core/api-internals/helpers.js +14 -0
- package/dist/core/api-internals/helpers.js.map +1 -0
- package/dist/core/api-internals/pull.d.ts +19 -0
- package/dist/core/api-internals/pull.d.ts.map +1 -0
- package/dist/core/api-internals/pull.js +269 -0
- package/dist/core/api-internals/pull.js.map +1 -0
- package/dist/core/api-internals/route-config.d.ts +13 -0
- package/dist/core/api-internals/route-config.d.ts.map +1 -0
- package/dist/core/api-internals/route-config.js +34 -0
- package/dist/core/api-internals/route-config.js.map +1 -0
- package/dist/core/api-internals/sync.d.ts +19 -0
- package/dist/core/api-internals/sync.d.ts.map +1 -0
- package/dist/core/api-internals/sync.js +139 -0
- package/dist/core/api-internals/sync.js.map +1 -0
- package/dist/core/api-internals/types.d.ts +33 -0
- package/dist/core/api-internals/types.d.ts.map +1 -0
- package/dist/core/api-internals/types.js +5 -0
- package/dist/core/api-internals/types.js.map +1 -0
- package/dist/core/api.d.ts +11 -0
- package/dist/core/api.d.ts.map +1 -0
- package/dist/core/api.js +11 -0
- package/dist/core/api.js.map +1 -0
- package/dist/core/cache-internals/format.d.ts +20 -0
- package/dist/core/cache-internals/format.d.ts.map +1 -0
- package/dist/core/cache-internals/format.js +33 -0
- package/dist/core/cache-internals/format.js.map +1 -0
- package/dist/core/cache-internals/params.d.ts +33 -0
- package/dist/core/cache-internals/params.d.ts.map +1 -0
- package/dist/core/cache-internals/params.js +155 -0
- package/dist/core/cache-internals/params.js.map +1 -0
- package/dist/core/cache-internals/pull.d.ts +17 -0
- package/dist/core/cache-internals/pull.d.ts.map +1 -0
- package/dist/core/cache-internals/pull.js +34 -0
- package/dist/core/cache-internals/pull.js.map +1 -0
- package/dist/core/cache-internals/sync.d.ts +29 -0
- package/dist/core/cache-internals/sync.d.ts.map +1 -0
- package/dist/core/cache-internals/sync.js +104 -0
- package/dist/core/cache-internals/sync.js.map +1 -0
- package/dist/core/cache-internals/types.d.ts +48 -0
- package/dist/core/cache-internals/types.d.ts.map +1 -0
- package/dist/core/cache-internals/types.js +2 -0
- package/dist/core/cache-internals/types.js.map +1 -0
- package/dist/core/cache.d.ts +13 -0
- package/dist/core/cache.d.ts.map +1 -0
- package/dist/core/cache.js +33 -0
- package/dist/core/cache.js.map +1 -0
- package/dist/core/scanner-internals/ast.d.ts +40 -0
- package/dist/core/scanner-internals/ast.d.ts.map +1 -0
- package/dist/core/scanner-internals/ast.js +100 -0
- package/dist/core/scanner-internals/ast.js.map +1 -0
- package/dist/core/scanner-internals/file-walker.d.ts +10 -0
- package/dist/core/scanner-internals/file-walker.d.ts.map +1 -0
- package/dist/core/scanner-internals/file-walker.js +23 -0
- package/dist/core/scanner-internals/file-walker.js.map +1 -0
- package/dist/core/scanner-internals/import-resolver.d.ts +21 -0
- package/dist/core/scanner-internals/import-resolver.d.ts.map +1 -0
- package/dist/core/scanner-internals/import-resolver.js +119 -0
- package/dist/core/scanner-internals/import-resolver.js.map +1 -0
- package/dist/core/scanner-internals/key-extractor.d.ts +20 -0
- package/dist/core/scanner-internals/key-extractor.d.ts.map +1 -0
- package/dist/core/scanner-internals/key-extractor.js +274 -0
- package/dist/core/scanner-internals/key-extractor.js.map +1 -0
- package/dist/core/scanner-internals/nav-config-scanner.d.ts +30 -0
- package/dist/core/scanner-internals/nav-config-scanner.d.ts.map +1 -0
- package/dist/core/scanner-internals/nav-config-scanner.js +170 -0
- package/dist/core/scanner-internals/nav-config-scanner.js.map +1 -0
- package/dist/core/scanner-internals/route-detector.d.ts +27 -0
- package/dist/core/scanner-internals/route-detector.d.ts.map +1 -0
- package/dist/core/scanner-internals/route-detector.js +78 -0
- package/dist/core/scanner-internals/route-detector.js.map +1 -0
- package/dist/core/scanner-internals/types.d.ts +60 -0
- package/dist/core/scanner-internals/types.d.ts.map +1 -0
- package/dist/core/scanner-internals/types.js +29 -0
- package/dist/core/scanner-internals/types.js.map +1 -0
- package/dist/core/scanner.d.ts +21 -0
- package/dist/core/scanner.d.ts.map +1 -0
- package/dist/core/scanner.js +162 -0
- package/dist/core/scanner.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/next.d.ts +33 -0
- package/dist/next.d.ts.map +1 -0
- package/dist/next.js +110 -0
- package/dist/next.js.map +1 -0
- package/dist/preview/index.d.ts +39 -0
- package/dist/preview/index.d.ts.map +1 -0
- package/dist/preview/index.js +123 -0
- package/dist/preview/index.js.map +1 -0
- package/dist/preview/internals/highlight.d.ts +31 -0
- package/dist/preview/internals/highlight.d.ts.map +1 -0
- package/dist/preview/internals/highlight.js +184 -0
- package/dist/preview/internals/highlight.js.map +1 -0
- package/dist/preview/internals/interactions.d.ts +15 -0
- package/dist/preview/internals/interactions.d.ts.map +1 -0
- package/dist/preview/internals/interactions.js +38 -0
- package/dist/preview/internals/interactions.js.map +1 -0
- package/dist/preview/internals/interactive.d.ts +14 -0
- package/dist/preview/internals/interactive.d.ts.map +1 -0
- package/dist/preview/internals/interactive.js +122 -0
- package/dist/preview/internals/interactive.js.map +1 -0
- package/dist/preview/internals/locales.d.ts +9 -0
- package/dist/preview/internals/locales.d.ts.map +1 -0
- package/dist/preview/internals/locales.js +24 -0
- package/dist/preview/internals/locales.js.map +1 -0
- package/dist/preview/internals/state.d.ts +37 -0
- package/dist/preview/internals/state.d.ts.map +1 -0
- package/dist/preview/internals/state.js +74 -0
- package/dist/preview/internals/state.js.map +1 -0
- package/dist/preview/internals/styles.d.ts +8 -0
- package/dist/preview/internals/styles.d.ts.map +1 -0
- package/dist/preview/internals/styles.js +28 -0
- package/dist/preview/internals/styles.js.map +1 -0
- package/dist/preview/internals/types.d.ts +74 -0
- package/dist/preview/internals/types.d.ts.map +1 -0
- package/dist/preview/internals/types.js +5 -0
- package/dist/preview/internals/types.js.map +1 -0
- package/dist/preview/internals/ui-indicators.d.ts +15 -0
- package/dist/preview/internals/ui-indicators.d.ts.map +1 -0
- package/dist/preview/internals/ui-indicators.js +92 -0
- package/dist/preview/internals/ui-indicators.js.map +1 -0
- package/dist/scaffold/index.d.ts +3 -0
- package/dist/scaffold/index.d.ts.map +1 -0
- package/dist/scaffold/index.js +3 -0
- package/dist/scaffold/index.js.map +1 -0
- package/dist/scaffold/intenrals/scaffold.d.ts +24 -0
- package/dist/scaffold/intenrals/scaffold.d.ts.map +1 -0
- package/dist/scaffold/intenrals/scaffold.js +53 -0
- package/dist/scaffold/intenrals/scaffold.js.map +1 -0
- package/dist/scaffold/intenrals/templates.d.ts +10 -0
- package/dist/scaffold/intenrals/templates.d.ts.map +1 -0
- package/dist/scaffold/intenrals/templates.js +344 -0
- package/dist/scaffold/intenrals/templates.js.map +1 -0
- package/dist/scaffold/intenrals/types.d.ts +14 -0
- package/dist/scaffold/intenrals/types.d.ts.map +1 -0
- package/dist/scaffold/intenrals/types.js +5 -0
- package/dist/scaffold/intenrals/types.js.map +1 -0
- package/package.json +3 -3
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import { scaffoldI18n } from '../scaffold/index.js';
|
|
4
|
+
/**
|
|
5
|
+
* Interactive `init` command.
|
|
6
|
+
*
|
|
7
|
+
* Walks the user through a series of prompts and writes a
|
|
8
|
+
* `.translationsrc.json` config file to the project root.
|
|
9
|
+
* Optionally scaffolds the i18n boilerplate files (settings,
|
|
10
|
+
* client, server, provider) into the chosen i18n directory.
|
|
11
|
+
*/
|
|
12
|
+
export async function runInit(root) {
|
|
13
|
+
const { createInterface } = await import('readline');
|
|
14
|
+
// Use readline so we can show prompts and read answers synchronously one by one
|
|
15
|
+
const rl = createInterface({
|
|
16
|
+
input: process.stdin,
|
|
17
|
+
output: process.stdout,
|
|
18
|
+
});
|
|
19
|
+
const question = (prompt) => new Promise(resolve => rl.question(prompt, resolve));
|
|
20
|
+
// eslint-disable-next-line no-console
|
|
21
|
+
console.log('sync-translations init\n');
|
|
22
|
+
// eslint-disable-next-line no-console
|
|
23
|
+
console.log('This creates .translationsrc.json in your project root.');
|
|
24
|
+
// eslint-disable-next-line no-console
|
|
25
|
+
console.log('Values here override env vars for the sync-translations CLI.\n');
|
|
26
|
+
// Collect required config values from the user
|
|
27
|
+
const cmsUrl = await question('CMS URL (e.g. https://cms.example.com): ');
|
|
28
|
+
const projectId = await question('Project ID: ');
|
|
29
|
+
const apiKey = await question('API key: ');
|
|
30
|
+
const i18nDirInput = await question('i18n directory [./src/lib/i18n]: ');
|
|
31
|
+
const pullTtlInput = await question('Pull TTL in seconds [300]: ');
|
|
32
|
+
const scaffoldInput = await question('Scaffold i18n files (settings, client, server, provider)? [Y/n]: ');
|
|
33
|
+
rl.close();
|
|
34
|
+
// Apply defaults for optional fields
|
|
35
|
+
const i18nDir = i18nDirInput.trim() || './src/lib/i18n';
|
|
36
|
+
// Dictionaries live one level deeper than the i18n dir
|
|
37
|
+
const outputDir = `${i18nDir.replace(/\/$/, '')}/dictionaries`;
|
|
38
|
+
// Build the config object — only include keys that the user actually provided
|
|
39
|
+
const config = {
|
|
40
|
+
$schema: './node_modules/@translation-cms/sync/schema.json',
|
|
41
|
+
};
|
|
42
|
+
if (cmsUrl.trim())
|
|
43
|
+
config['cmsUrl'] = cmsUrl.trim();
|
|
44
|
+
if (projectId.trim())
|
|
45
|
+
config['projectId'] = projectId.trim();
|
|
46
|
+
if (apiKey.trim())
|
|
47
|
+
config['apiKey'] = apiKey.trim();
|
|
48
|
+
config['outputDir'] = outputDir;
|
|
49
|
+
if (pullTtlInput.trim()) {
|
|
50
|
+
const ttlSec = parseInt(pullTtlInput.trim(), 10);
|
|
51
|
+
// Convert seconds → milliseconds for the config field
|
|
52
|
+
if (!isNaN(ttlSec))
|
|
53
|
+
config['pullTtlMs'] = ttlSec * 1000;
|
|
54
|
+
}
|
|
55
|
+
// Write the config file
|
|
56
|
+
const configPath = path.join(root, '.translationsrc.json');
|
|
57
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
58
|
+
console.log(`\nCreated: ${configPath}`);
|
|
59
|
+
// Warn if an API key was written to disk — it should ideally stay in .env.local
|
|
60
|
+
if (config['apiKey']) {
|
|
61
|
+
console.log('\nWarning: .translationsrc.json contains an API key. Consider adding it to .gitignore:');
|
|
62
|
+
console.log(' echo ".translationsrc.json" >> .gitignore');
|
|
63
|
+
console.log('Or move the API key to CMS_SYNC_API_KEY in .env.local instead.');
|
|
64
|
+
}
|
|
65
|
+
// Default to scaffolding unless the user explicitly answers "n"
|
|
66
|
+
const doScaffold = scaffoldInput.trim().toLowerCase() !== 'n';
|
|
67
|
+
if (doScaffold) {
|
|
68
|
+
const absI18nDir = path.isAbsolute(i18nDir)
|
|
69
|
+
? i18nDir
|
|
70
|
+
: path.resolve(root, i18nDir);
|
|
71
|
+
const { written, skipped } = scaffoldI18n({ i18nDir: absI18nDir });
|
|
72
|
+
if (written.length > 0) {
|
|
73
|
+
console.log('\nScaffolded i18n files:');
|
|
74
|
+
for (const f of written)
|
|
75
|
+
console.log(` + src/lib/i18n/${f}`);
|
|
76
|
+
}
|
|
77
|
+
if (skipped.length > 0) {
|
|
78
|
+
// Files that already exist are left untouched to avoid overwriting customizations
|
|
79
|
+
console.log('\nSkipped (already exist):');
|
|
80
|
+
for (const f of skipped)
|
|
81
|
+
console.log(` ~ src/lib/i18n/${f}`);
|
|
82
|
+
}
|
|
83
|
+
console.log('\nNext steps:');
|
|
84
|
+
console.log(' 1. Install peer deps: pnpm add i18next react-i18next i18next-resources-to-backend');
|
|
85
|
+
console.log(' 2. Add to next.config.ts:');
|
|
86
|
+
console.log('');
|
|
87
|
+
console.log(" import { PHASE_DEVELOPMENT_SERVER, PHASE_PRODUCTION_BUILD } from 'next/constants';");
|
|
88
|
+
console.log(" import { syncTranslations, pullTranslations, watchTranslations } from '@translation-cms/sync/api';");
|
|
89
|
+
console.log('');
|
|
90
|
+
console.log(' export default async function config(phase) {');
|
|
91
|
+
console.log(' if (phase === PHASE_DEVELOPMENT_SERVER) {');
|
|
92
|
+
console.log(" await syncTranslations({ projectRoot: '.' });");
|
|
93
|
+
console.log(" await pullTranslations({ projectRoot: '.' });");
|
|
94
|
+
console.log(" watchTranslations({ projectRoot: '.' }); // auto-pull on publish");
|
|
95
|
+
console.log(' }');
|
|
96
|
+
console.log(' if (phase === PHASE_PRODUCTION_BUILD) {');
|
|
97
|
+
console.log(" await syncTranslations({ projectRoot: '.' });");
|
|
98
|
+
console.log(" await pullTranslations({ projectRoot: '.' });");
|
|
99
|
+
console.log(' }');
|
|
100
|
+
console.log(' return { /* your next.js config */ };');
|
|
101
|
+
console.log(' }');
|
|
102
|
+
console.log('');
|
|
103
|
+
console.log(' 3. Pull translations: sync-translations pull');
|
|
104
|
+
console.log(' 4. Wrap your root layout with <TranslationProvider locale={locale}>');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Config, TranslationsConfig } from '../config/resolve-config.js';
|
|
2
|
+
/**
|
|
3
|
+
* `pull` command — fetches published translations from the CMS and writes
|
|
4
|
+
* them as JSON dictionary files to the output directory.
|
|
5
|
+
*
|
|
6
|
+
* Resolution order for each option:
|
|
7
|
+
* CLI flag > .translationsrc.json > built-in default
|
|
8
|
+
*/
|
|
9
|
+
export declare function runPull(root: string, config: Config, fileConfig: TranslationsConfig, args: string[]): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=pull.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAG7E;;;;;;GAMG;AACH,wBAAsB,OAAO,CACzB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,kBAAkB,EAC9B,IAAI,EAAE,MAAM,EAAE,GACf,OAAO,CAAC,IAAI,CAAC,CAiBf"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { pullTranslations } from '../core/api.js';
|
|
3
|
+
/**
|
|
4
|
+
* `pull` command — fetches published translations from the CMS and writes
|
|
5
|
+
* them as JSON dictionary files to the output directory.
|
|
6
|
+
*
|
|
7
|
+
* Resolution order for each option:
|
|
8
|
+
* CLI flag > .translationsrc.json > built-in default
|
|
9
|
+
*/
|
|
10
|
+
export async function runPull(root, config, fileConfig, args) {
|
|
11
|
+
// --output overrides the config file value; fall back to public/locales
|
|
12
|
+
const outputArg = getFlag(args, '--output');
|
|
13
|
+
const outputDir = outputArg
|
|
14
|
+
? path.resolve(root, outputArg)
|
|
15
|
+
: fileConfig.outputDir
|
|
16
|
+
? path.resolve(root, fileConfig.outputDir)
|
|
17
|
+
: path.join(root, 'public', 'locales');
|
|
18
|
+
// --ttl overrides the config file value (already in ms)
|
|
19
|
+
const ttlArg = getFlag(args, '--ttl');
|
|
20
|
+
await pullTranslations(config, {
|
|
21
|
+
outputDir,
|
|
22
|
+
force: args.includes('--force'), // skip TTL cache check and always re-fetch
|
|
23
|
+
ttlMs: ttlArg ? parseInt(ttlArg, 10) : fileConfig.pullTtlMs,
|
|
24
|
+
env: getFlag(args, '--env'), // target a specific environment (e.g. staging)
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Returns the value of a named CLI flag (`--flag value`),
|
|
29
|
+
* or `undefined` if the flag is absent or has no value after it.
|
|
30
|
+
*/
|
|
31
|
+
function getFlag(args, flag) {
|
|
32
|
+
const idx = args.indexOf(flag);
|
|
33
|
+
return idx !== -1 && args[idx + 1] ? args[idx + 1] : undefined;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=pull.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pull.js","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CACzB,IAAY,EACZ,MAAc,EACd,UAA8B,EAC9B,IAAc;IAEd,wEAAwE;IACxE,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC5C,MAAM,SAAS,GAAG,SAAS;QACvB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC;QAC/B,CAAC,CAAC,UAAU,CAAC,SAAS;YACpB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC;YAC1C,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;IAE7C,wDAAwD;IACxD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACtC,MAAM,gBAAgB,CAAC,MAAM,EAAE;QAC3B,SAAS;QACT,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,2CAA2C;QAC5E,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS;QAC3D,GAAG,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,+CAA+C;KAC/E,CAAC,CAAC;AACP,CAAC;AAED;;;GAGG;AACH,SAAS,OAAO,CAAC,IAAc,EAAE,IAAY;IACzC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,OAAO,GAAG,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACnE,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ScanOptions } from '../core/scanner.js';
|
|
2
|
+
/**
|
|
3
|
+
* `status` command — scans the project for translation keys and compares
|
|
4
|
+
* the result against the last sync cache (.cms-sync-cache.json).
|
|
5
|
+
*
|
|
6
|
+
* Outputs a human-readable diff showing:
|
|
7
|
+
* + keys that are new since the last sync
|
|
8
|
+
* - keys that have been removed
|
|
9
|
+
* ~ keys whose preview routes have changed
|
|
10
|
+
* = keys that are unchanged
|
|
11
|
+
*
|
|
12
|
+
* Does not write anything — safe to run at any time.
|
|
13
|
+
*/
|
|
14
|
+
export declare function runStatus(root: string, scanOpts: ScanOptions): void;
|
|
15
|
+
//# sourceMappingURL=status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAQlE;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,GAAG,IAAI,CA8DnE"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { scanProject } from '../core/scanner.js';
|
|
2
|
+
import { serializeNamespaces, loadSyncCache, computeDiff, formatPreviewRoutes, } from '../core/cache.js';
|
|
3
|
+
/**
|
|
4
|
+
* `status` command — scans the project for translation keys and compares
|
|
5
|
+
* the result against the last sync cache (.cms-sync-cache.json).
|
|
6
|
+
*
|
|
7
|
+
* Outputs a human-readable diff showing:
|
|
8
|
+
* + keys that are new since the last sync
|
|
9
|
+
* - keys that have been removed
|
|
10
|
+
* ~ keys whose preview routes have changed
|
|
11
|
+
* = keys that are unchanged
|
|
12
|
+
*
|
|
13
|
+
* Does not write anything — safe to run at any time.
|
|
14
|
+
*/
|
|
15
|
+
export function runStatus(root, scanOpts) {
|
|
16
|
+
console.log(`Scanning project: ${root}`);
|
|
17
|
+
const namespaces = scanProject(root, scanOpts);
|
|
18
|
+
// Flatten the NamespaceMap into a plain serializable object and get the total key count
|
|
19
|
+
const { serialized, totalKeys } = serializeNamespaces(namespaces);
|
|
20
|
+
const namespaceCount = Object.keys(serialized).length;
|
|
21
|
+
console.log(`\nFound ${totalKeys} key(s) across ${namespaceCount} namespace(s): ${Object.keys(serialized).join(', ')}`);
|
|
22
|
+
// Load the baseline written by the last successful sync
|
|
23
|
+
const cached = loadSyncCache(root);
|
|
24
|
+
if (!cached) {
|
|
25
|
+
console.log('\nNo sync cache found (.cms-sync-cache.json). Run sync first to establish a baseline.');
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
// Diff current scan against the cached snapshot
|
|
29
|
+
const diff = computeDiff(serialized, cached);
|
|
30
|
+
console.log('\nStatus vs last sync:');
|
|
31
|
+
console.log(` + ${diff.added.length} new key(s)`);
|
|
32
|
+
console.log(` - ${diff.removed.length} removed key(s)`);
|
|
33
|
+
console.log(` ~ ${diff.routesChanged.length} route update(s)`);
|
|
34
|
+
console.log(` = ${diff.unchanged} unchanged`);
|
|
35
|
+
if (diff.added.length > 0) {
|
|
36
|
+
console.log('\nNew keys:');
|
|
37
|
+
for (const { namespace, key, routes } of diff.added) {
|
|
38
|
+
console.log(` + ${namespace}:${key} (${formatPreviewRoutes(routes)})`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (diff.removed.length > 0) {
|
|
42
|
+
console.log('\nRemoved keys:');
|
|
43
|
+
for (const { namespace, key } of diff.removed) {
|
|
44
|
+
console.log(` - ${namespace}:${key}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (diff.routesChanged.length > 0) {
|
|
48
|
+
console.log('\nRoute updates:');
|
|
49
|
+
for (const { namespace, key, before, after } of diff.routesChanged) {
|
|
50
|
+
console.log(` ~ ${namespace}:${key} [${formatPreviewRoutes(before)}] -> [${formatPreviewRoutes(after)}]`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Only prompt to sync if there are actual changes
|
|
54
|
+
const total = diff.added.length + diff.removed.length + diff.routesChanged.length;
|
|
55
|
+
if (total > 0) {
|
|
56
|
+
console.log('\nRun "sync-translations sync" to push these changes.');
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
console.log('\nEverything is in sync.');
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Config } from '../config/resolve-config.js';
|
|
2
|
+
import { type ScanOptions } from '../core/scanner.js';
|
|
3
|
+
export interface SyncCommandOptions {
|
|
4
|
+
outputDir: string;
|
|
5
|
+
dryRun: boolean;
|
|
6
|
+
force: boolean;
|
|
7
|
+
reportPath?: string;
|
|
8
|
+
/** Path (relative to root) for the generated mock-params TS file. */
|
|
9
|
+
mockDataPath?: string;
|
|
10
|
+
/** User-configured route params from config file (merged into mock data). */
|
|
11
|
+
userRouteParams?: Record<string, Record<string, string>>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* `sync` command — the main push/pull cycle:
|
|
15
|
+
*
|
|
16
|
+
* 1. Scan the project for translation keys and their preview routes.
|
|
17
|
+
* 2. Auto-generate mock route params for any dynamic routes (e.g. /[slug]).
|
|
18
|
+
* If a mockDataPath is configured, write a TS file with the merged params
|
|
19
|
+
* so the CMS can render live previews.
|
|
20
|
+
* 3. POST the discovered keys to the CMS (dry-run: report only, no writes).
|
|
21
|
+
* 4. Pull the latest published translations back to disk (skipped on dry-run).
|
|
22
|
+
*/
|
|
23
|
+
export declare function runSync(root: string, config: Config, scanOpts: ScanOptions, opts: SyncCommandOptions): Promise<void>;
|
|
24
|
+
//# sourceMappingURL=sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAe,KAAK,WAAW,EAAY,MAAM,mBAAmB,CAAC;AAQ5E,MAAM,WAAW,kBAAkB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6EAA6E;IAC7E,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC5D;AAED;;;;;;;;;GASG;AACH,wBAAsB,OAAO,CACzB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,WAAW,EACrB,IAAI,EAAE,kBAAkB,GACzB,OAAO,CAAC,IAAI,CAAC,CA2Df"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { scanProject, routeKey } from '../core/scanner.js';
|
|
4
|
+
import { postToSync, pullTranslations } from '../core/api.js';
|
|
5
|
+
import { generateRouteParams, saveRouteParamsCache, writeMockDataFile, } from '../core/cache.js';
|
|
6
|
+
/**
|
|
7
|
+
* `sync` command — the main push/pull cycle:
|
|
8
|
+
*
|
|
9
|
+
* 1. Scan the project for translation keys and their preview routes.
|
|
10
|
+
* 2. Auto-generate mock route params for any dynamic routes (e.g. /[slug]).
|
|
11
|
+
* If a mockDataPath is configured, write a TS file with the merged params
|
|
12
|
+
* so the CMS can render live previews.
|
|
13
|
+
* 3. POST the discovered keys to the CMS (dry-run: report only, no writes).
|
|
14
|
+
* 4. Pull the latest published translations back to disk (skipped on dry-run).
|
|
15
|
+
*/
|
|
16
|
+
export async function runSync(root, config, scanOpts, opts) {
|
|
17
|
+
console.log(`Scanning project: ${root}`);
|
|
18
|
+
const namespaces = scanProject(root, scanOpts);
|
|
19
|
+
// Collect every unique route string found across all keys so we can
|
|
20
|
+
// generate placeholder params for dynamic segments (e.g. [slug], [id]).
|
|
21
|
+
const detectedRoutes = new Set();
|
|
22
|
+
for (const keyMap of Object.values(namespaces)) {
|
|
23
|
+
for (const routes of keyMap.values()) {
|
|
24
|
+
for (const route of routes) {
|
|
25
|
+
// routeKey normalises PreviewRoute objects to plain strings
|
|
26
|
+
const routeStr = routeKey(route);
|
|
27
|
+
detectedRoutes.add(routeStr);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (detectedRoutes.size > 0) {
|
|
32
|
+
const autoParams = generateRouteParams(Array.from(detectedRoutes));
|
|
33
|
+
if (Object.keys(autoParams).length > 0) {
|
|
34
|
+
// Persist the auto-generated params to cache so subsequent scans
|
|
35
|
+
// can reuse them without re-deriving them from scratch
|
|
36
|
+
saveRouteParamsCache(root, autoParams);
|
|
37
|
+
console.log(`[route-params] Auto-generated params for ${Object.keys(autoParams).length} dynamic routes`);
|
|
38
|
+
if (opts.mockDataPath) {
|
|
39
|
+
// Merge auto-generated with user-configured params (user wins on conflict)
|
|
40
|
+
const merged = {
|
|
41
|
+
...autoParams,
|
|
42
|
+
...(opts.userRouteParams ?? {}),
|
|
43
|
+
};
|
|
44
|
+
writeMockDataFile(root, merged, opts.mockDataPath);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// Read local translation values from JSON files to bootstrap drafts in CMS.
|
|
49
|
+
// Keys that already have a draft in the CMS are never overwritten.
|
|
50
|
+
const localValues = readLocalValues(opts.outputDir);
|
|
51
|
+
// Push discovered keys to the CMS; dry-run mode only prints a report
|
|
52
|
+
await postToSync(config, namespaces, {
|
|
53
|
+
root,
|
|
54
|
+
force: opts.force,
|
|
55
|
+
dryRun: opts.dryRun,
|
|
56
|
+
reportPath: opts.reportPath,
|
|
57
|
+
localValues,
|
|
58
|
+
});
|
|
59
|
+
// Pull translations back to disk after a successful push.
|
|
60
|
+
// Skip when dry-running — there's nothing new to pull yet.
|
|
61
|
+
if (!opts.dryRun) {
|
|
62
|
+
await pullTranslations(config, {
|
|
63
|
+
outputDir: opts.outputDir,
|
|
64
|
+
force: opts.force,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Flatten a nested object to dot-notation keys.
|
|
70
|
+
* e.g. { button: { save: "Save" } } → { "button.save": "Save" }
|
|
71
|
+
*/
|
|
72
|
+
function flattenObject(obj, prefix = '') {
|
|
73
|
+
const result = {};
|
|
74
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
75
|
+
const fullKey = prefix ? `${prefix}.${key}` : key;
|
|
76
|
+
if (typeof value === 'string') {
|
|
77
|
+
result[fullKey] = value;
|
|
78
|
+
}
|
|
79
|
+
else if (typeof value === 'object' && value !== null) {
|
|
80
|
+
Object.assign(result, flattenObject(value, fullKey));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Read all `{locale}.json` files from outputDir and return a nested map:
|
|
87
|
+
* namespace → translationKey → locale → value
|
|
88
|
+
*
|
|
89
|
+
* Local JSON files use the nested format written by `pull`:
|
|
90
|
+
* { namespace: { "dot.notation.key": "value" } }
|
|
91
|
+
*/
|
|
92
|
+
function readLocalValues(outputDir) {
|
|
93
|
+
const result = {};
|
|
94
|
+
if (!fs.existsSync(outputDir))
|
|
95
|
+
return result;
|
|
96
|
+
let files;
|
|
97
|
+
try {
|
|
98
|
+
files = fs
|
|
99
|
+
.readdirSync(outputDir)
|
|
100
|
+
.filter(f => f.endsWith('.json') && f !== '.last-pulled');
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
for (const file of files) {
|
|
106
|
+
const locale = file.replace('.json', '');
|
|
107
|
+
try {
|
|
108
|
+
const raw = fs.readFileSync(path.join(outputDir, file), 'utf-8');
|
|
109
|
+
const content = JSON.parse(raw);
|
|
110
|
+
for (const [namespace, keys] of Object.entries(content)) {
|
|
111
|
+
if (typeof keys !== 'object' || keys === null)
|
|
112
|
+
continue;
|
|
113
|
+
const flat = flattenObject(keys);
|
|
114
|
+
if (!result[namespace])
|
|
115
|
+
result[namespace] = {};
|
|
116
|
+
for (const [key, value] of Object.entries(flat)) {
|
|
117
|
+
if (!value.trim())
|
|
118
|
+
continue;
|
|
119
|
+
if (!result[namespace][key])
|
|
120
|
+
result[namespace][key] = {};
|
|
121
|
+
result[namespace][key][locale] = value;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
// Skip malformed files silently
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return result;
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Config } from '../config/resolve-config.js';
|
|
2
|
+
import { type ScanOptions } from '../core/scanner.js';
|
|
3
|
+
/**
|
|
4
|
+
* `watch` command — runs a full sync on startup, then re-syncs automatically
|
|
5
|
+
* whenever a source file changes.
|
|
6
|
+
*
|
|
7
|
+
* Flow on each change:
|
|
8
|
+
* 1. Debounce 500 ms to coalesce rapid saves (e.g. editor auto-format).
|
|
9
|
+
* 2. Scan the project for translation keys.
|
|
10
|
+
* 3. POST discovered keys to the CMS (force — bypass TTL cache).
|
|
11
|
+
* 4. Pull the latest translations back to disk (force).
|
|
12
|
+
*
|
|
13
|
+
* Concurrent syncs are prevented by the `running` guard — if a sync is
|
|
14
|
+
* already in progress when a new change fires, the new event is dropped.
|
|
15
|
+
* Ctrl+C closes the watcher cleanly before exiting.
|
|
16
|
+
*/
|
|
17
|
+
export declare function runWatch(root: string, config: Config, outputDir: string, scanOpts: ScanOptions): Promise<void>;
|
|
18
|
+
//# sourceMappingURL=watch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../src/commands/watch.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGlE;;;;;;;;;;;;;GAaG;AACH,wBAAsB,QAAQ,CAC1B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,WAAW,GACtB,OAAO,CAAC,IAAI,CAAC,CA0Df"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import { scanProject } from '../core/scanner.js';
|
|
4
|
+
import { postToSync, pullTranslations } from '../core/api.js';
|
|
5
|
+
/**
|
|
6
|
+
* `watch` command — runs a full sync on startup, then re-syncs automatically
|
|
7
|
+
* whenever a source file changes.
|
|
8
|
+
*
|
|
9
|
+
* Flow on each change:
|
|
10
|
+
* 1. Debounce 500 ms to coalesce rapid saves (e.g. editor auto-format).
|
|
11
|
+
* 2. Scan the project for translation keys.
|
|
12
|
+
* 3. POST discovered keys to the CMS (force — bypass TTL cache).
|
|
13
|
+
* 4. Pull the latest translations back to disk (force).
|
|
14
|
+
*
|
|
15
|
+
* Concurrent syncs are prevented by the `running` guard — if a sync is
|
|
16
|
+
* already in progress when a new change fires, the new event is dropped.
|
|
17
|
+
* Ctrl+C closes the watcher cleanly before exiting.
|
|
18
|
+
*/
|
|
19
|
+
export async function runWatch(root, config, outputDir, scanOpts) {
|
|
20
|
+
console.log(`[watch] Watching ${root} for changes...`);
|
|
21
|
+
console.log('[watch] Press Ctrl+C to stop.\n');
|
|
22
|
+
// Only react to source files — ignore CSS, JSON, lock files, etc.
|
|
23
|
+
const sourceExtensions = new Set(scanOpts.sourceExtensions ?? ['.ts', '.tsx', '.js', '.jsx']);
|
|
24
|
+
let debounce = null;
|
|
25
|
+
// Prevents overlapping syncs if a change fires while a sync is still running
|
|
26
|
+
let running = false;
|
|
27
|
+
const runSync = async () => {
|
|
28
|
+
if (running)
|
|
29
|
+
return;
|
|
30
|
+
running = true;
|
|
31
|
+
try {
|
|
32
|
+
const namespaces = scanProject(root, scanOpts);
|
|
33
|
+
// force: true bypasses the TTL cache so changes are always pushed/pulled
|
|
34
|
+
await postToSync(config, namespaces, { root, force: true });
|
|
35
|
+
await pullTranslations(config, { outputDir, force: true });
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
// Log errors without crashing the watcher process
|
|
39
|
+
console.error('[watch] Sync error:', err instanceof Error ? err.message : String(err));
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
running = false;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
// Run an initial sync so the local dictionaries are up-to-date before watching
|
|
46
|
+
await runSync();
|
|
47
|
+
// fs.watch with recursive:true covers the entire tree in one watcher instance
|
|
48
|
+
const watcher = fs.watch(root, { recursive: true }, (_evt, filename) => {
|
|
49
|
+
if (!filename)
|
|
50
|
+
return;
|
|
51
|
+
const ext = path.extname(filename);
|
|
52
|
+
if (!sourceExtensions.has(ext))
|
|
53
|
+
return;
|
|
54
|
+
// Coalesce rapid saves within 500 ms into a single sync run
|
|
55
|
+
if (debounce)
|
|
56
|
+
clearTimeout(debounce);
|
|
57
|
+
debounce = setTimeout(() => {
|
|
58
|
+
console.log(`[watch] Change detected: ${filename}`);
|
|
59
|
+
void runSync();
|
|
60
|
+
}, 500);
|
|
61
|
+
});
|
|
62
|
+
// Clean up the watcher before exiting on Ctrl+C
|
|
63
|
+
process.on('SIGINT', () => {
|
|
64
|
+
watcher.close();
|
|
65
|
+
console.log('\n[watch] Stopped.');
|
|
66
|
+
process.exit(0);
|
|
67
|
+
});
|
|
68
|
+
// Hold the event loop open indefinitely — the watcher keeps us alive until SIGINT
|
|
69
|
+
await new Promise(() => undefined);
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=watch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/commands/watch.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,OAAO,EAAE,WAAW,EAAoB,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAE7D;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC1B,IAAY,EACZ,MAAc,EACd,SAAiB,EACjB,QAAqB;IAErB,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,iBAAiB,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;IAE/C,kEAAkE;IAClE,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAC5B,QAAQ,CAAC,gBAAgB,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAC9D,CAAC;IAEF,IAAI,QAAQ,GAAyC,IAAI,CAAC;IAC1D,6EAA6E;IAC7E,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,MAAM,OAAO,GAAG,KAAK,IAAmB,EAAE;QACtC,IAAI,OAAO;YAAE,OAAO;QACpB,OAAO,GAAG,IAAI,CAAC;QACf,IAAI,CAAC;YACD,MAAM,UAAU,GAAG,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YAC/C,yEAAyE;YACzE,MAAM,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5D,MAAM,gBAAgB,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/D,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACX,kDAAkD;YAClD,OAAO,CAAC,KAAK,CACT,qBAAqB,EACrB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CACnD,CAAC;QACN,CAAC;gBAAS,CAAC;YACP,OAAO,GAAG,KAAK,CAAC;QACpB,CAAC;IACL,CAAC,CAAC;IAEF,+EAA+E;IAC/E,MAAM,OAAO,EAAE,CAAC;IAEhB,8EAA8E;IAC9E,MAAM,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE;QACnE,IAAI,CAAC,QAAQ;YAAE,OAAO;QACtB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACnC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO;QAEvC,4DAA4D;QAC5D,IAAI,QAAQ;YAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;QACrC,QAAQ,GAAG,UAAU,CAAC,GAAG,EAAE;YACvB,OAAO,CAAC,GAAG,CAAC,4BAA4B,QAAQ,EAAE,CAAC,CAAC;YACpD,KAAK,OAAO,EAAE,CAAC;QACnB,CAAC,EAAE,GAAG,CAAC,CAAC;IACZ,CAAC,CAAC,CAAC;IAEH,gDAAgD;IAChD,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;QACtB,OAAO,CAAC,KAAK,EAAE,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAClC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC,CAAC,CAAC;IAEH,kFAAkF;IAClF,MAAM,IAAI,OAAO,CAAQ,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;AAC9C,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses CLI arguments that override resolved config values.
|
|
3
|
+
*/
|
|
4
|
+
import type { Config } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Scan process.argv for --project-id, --api-key, and --cms-url flags.
|
|
7
|
+
* Returns only the fields that were explicitly provided — missing flags are
|
|
8
|
+
* omitted so they can be overridden by lower-priority sources (env vars, file).
|
|
9
|
+
*/
|
|
10
|
+
export declare function parseArgs(): Partial<Config>;
|
|
11
|
+
//# sourceMappingURL=args.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../../src/config/config-internals/args.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAU3C"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses CLI arguments that override resolved config values.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Scan process.argv for --project-id, --api-key, and --cms-url flags.
|
|
6
|
+
* Returns only the fields that were explicitly provided — missing flags are
|
|
7
|
+
* omitted so they can be overridden by lower-priority sources (env vars, file).
|
|
8
|
+
*/
|
|
9
|
+
export function parseArgs() {
|
|
10
|
+
const args = process.argv.slice(2);
|
|
11
|
+
const result = {};
|
|
12
|
+
for (let i = 0; i < args.length; i++) {
|
|
13
|
+
if (args[i] === '--project-id' && args[i + 1])
|
|
14
|
+
result.projectId = args[++i];
|
|
15
|
+
if (args[i] === '--api-key' && args[i + 1])
|
|
16
|
+
result.apiKey = args[++i];
|
|
17
|
+
if (args[i] === '--cms-url' && args[i + 1])
|
|
18
|
+
result.cmsUrl = args[++i];
|
|
19
|
+
}
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=args.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../../../src/config/config-internals/args.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;;GAIG;AACH,MAAM,UAAU,SAAS;IACrB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,MAAM,GAAoB,EAAE,CAAC;IACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,cAAc,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YACzC,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACjC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,WAAW,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YAAE,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACtE,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,WAAW,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YAAE,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads .env.local files and parses them into a key/value map.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Parse a .env.local file at the given root into a plain key/value map.
|
|
6
|
+
* Skips blank lines and comments. Strips surrounding quotes from values.
|
|
7
|
+
* Returns an empty object when the file does not exist — never throws.
|
|
8
|
+
*/
|
|
9
|
+
export declare function loadEnvLocal(root: string): Record<string, string>;
|
|
10
|
+
//# sourceMappingURL=env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../../src/config/config-internals/env.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAqBjE"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads .env.local files and parses them into a key/value map.
|
|
3
|
+
*/
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
/**
|
|
7
|
+
* Parse a .env.local file at the given root into a plain key/value map.
|
|
8
|
+
* Skips blank lines and comments. Strips surrounding quotes from values.
|
|
9
|
+
* Returns an empty object when the file does not exist — never throws.
|
|
10
|
+
*/
|
|
11
|
+
export function loadEnvLocal(root) {
|
|
12
|
+
const envPath = path.join(root, '.env.local');
|
|
13
|
+
if (!fs.existsSync(envPath))
|
|
14
|
+
return {};
|
|
15
|
+
const vars = {};
|
|
16
|
+
const lines = fs.readFileSync(envPath, 'utf-8').split('\n');
|
|
17
|
+
for (const line of lines) {
|
|
18
|
+
const trimmed = line.trim();
|
|
19
|
+
// Skip blank lines and comments
|
|
20
|
+
if (!trimmed || trimmed.startsWith('#'))
|
|
21
|
+
continue;
|
|
22
|
+
const eq = trimmed.indexOf('=');
|
|
23
|
+
if (eq === -1)
|
|
24
|
+
continue;
|
|
25
|
+
const key = trimmed.slice(0, eq).trim();
|
|
26
|
+
// Strip surrounding single or double quotes from the value
|
|
27
|
+
const value = trimmed
|
|
28
|
+
.slice(eq + 1)
|
|
29
|
+
.trim()
|
|
30
|
+
.replace(/^["']|["']$/g, '');
|
|
31
|
+
vars[key] = value;
|
|
32
|
+
}
|
|
33
|
+
return vars;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../../src/config/config-internals/env.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACrC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IAC9C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,CAAC;IAEvC,MAAM,IAAI,GAA2B,EAAE,CAAC;IACxC,MAAM,KAAK,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,gCAAgC;QAChC,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAClD,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,EAAE,KAAK,CAAC,CAAC;YAAE,SAAS;QACxB,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACxC,2DAA2D;QAC3D,MAAM,KAAK,GAAG,OAAO;aAChB,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC;aACb,IAAI,EAAE;aACN,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;QACjC,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACtB,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC"}
|