@translation-cms/sync 1.2.28 → 1.2.29
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
package/dist/api.d.ts
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Programmatic API for translation sync
|
|
3
|
+
*
|
|
4
|
+
* Use this if you want to integrate sync into your own tooling, CI/CD,
|
|
5
|
+
* or custom workflows.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* import { syncTranslations, pullTranslations } from '@translation-cms/sync/api';
|
|
9
|
+
*
|
|
10
|
+
* // Scan and sync keys to CMS
|
|
11
|
+
* await syncTranslations({ projectRoot: './my-project' });
|
|
12
|
+
*
|
|
13
|
+
* // Fetch translations from CMS
|
|
14
|
+
* await pullTranslations({ projectRoot: './my-project' });
|
|
15
|
+
*/
|
|
16
|
+
export interface SyncOptions {
|
|
17
|
+
/** Project root directory. If omitted, searches up from cwd */
|
|
18
|
+
projectRoot?: string;
|
|
19
|
+
/** Dry run: show changes without uploading */
|
|
20
|
+
dryRun?: boolean;
|
|
21
|
+
/** Force refresh: ignore cache */
|
|
22
|
+
force?: boolean;
|
|
23
|
+
/** Write sync report to this file path */
|
|
24
|
+
reportPath?: string;
|
|
25
|
+
/** Show verbose output */
|
|
26
|
+
verbose?: boolean;
|
|
27
|
+
/** Path alias mappings (mirrors tsconfig `paths`). Used to resolve @/ imports. */
|
|
28
|
+
pathMappings?: Record<string, string[]>;
|
|
29
|
+
}
|
|
30
|
+
export interface PullOptions {
|
|
31
|
+
/** Project root directory. If omitted, searches up from cwd */
|
|
32
|
+
projectRoot?: string;
|
|
33
|
+
/** Custom output directory for JSON files */
|
|
34
|
+
outputDir?: string;
|
|
35
|
+
/** Force refresh: ignore cache */
|
|
36
|
+
force?: boolean;
|
|
37
|
+
/** Override cache TTL in milliseconds */
|
|
38
|
+
ttl?: number;
|
|
39
|
+
/** Pull from specific environment */
|
|
40
|
+
environment?: string;
|
|
41
|
+
/** Show verbose output */
|
|
42
|
+
verbose?: boolean;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Scans codebase for translation keys and syncs them to the CMS.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* const result = await syncTranslations({
|
|
49
|
+
* projectRoot: './apps/web',
|
|
50
|
+
* dryRun: false,
|
|
51
|
+
* verbose: true,
|
|
52
|
+
* });
|
|
53
|
+
*
|
|
54
|
+
* console.log(`Synced ${result.keysAdded} new keys`);
|
|
55
|
+
*/
|
|
56
|
+
export declare function syncTranslations(options?: SyncOptions): Promise<{
|
|
57
|
+
keysAdded: number;
|
|
58
|
+
keysUpdated: number;
|
|
59
|
+
}>;
|
|
60
|
+
/**
|
|
61
|
+
* Fetches translations from the CMS and writes them as local JSON files.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* await pullTranslations({
|
|
65
|
+
* projectRoot: './apps/web',
|
|
66
|
+
* outputDir: './src/i18n/locales',
|
|
67
|
+
* force: true,
|
|
68
|
+
* });
|
|
69
|
+
*/
|
|
70
|
+
export declare function pullTranslations(options?: PullOptions): Promise<{
|
|
71
|
+
locales: string[];
|
|
72
|
+
fileCount: number;
|
|
73
|
+
}>;
|
|
74
|
+
export interface WatchOptions {
|
|
75
|
+
/** Project root directory. If omitted, searches up from cwd */
|
|
76
|
+
projectRoot?: string;
|
|
77
|
+
/** Custom output directory to watch (must match the pull outputDir) */
|
|
78
|
+
outputDir?: string;
|
|
79
|
+
/**
|
|
80
|
+
* How often (in ms) to poll the CMS for new translations.
|
|
81
|
+
* Default: 10000 (10 seconds). Set to 0 to disable.
|
|
82
|
+
*/
|
|
83
|
+
interval?: number;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Starts a polling loop that detects new CMS publishes and automatically
|
|
87
|
+
* re-pulls translations to local JSON files. Non-blocking — returns immediately.
|
|
88
|
+
*
|
|
89
|
+
* Call this once in dev mode after the initial pull:
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* if (phase === PHASE_DEVELOPMENT_SERVER) {
|
|
93
|
+
* await pullTranslations({ projectRoot: '.' });
|
|
94
|
+
* watchTranslations({ projectRoot: '.' });
|
|
95
|
+
* }
|
|
96
|
+
*/
|
|
97
|
+
export declare function watchTranslations(options?: WatchOptions): void;
|
|
98
|
+
/**
|
|
99
|
+
* Sync and pull in one operation (equivalent to CLI `sync` command)
|
|
100
|
+
*/
|
|
101
|
+
export declare function syncAndPull(options?: SyncOptions & PullOptions): Promise<{
|
|
102
|
+
synced: boolean;
|
|
103
|
+
pulled: boolean;
|
|
104
|
+
}>;
|
|
105
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAeH,MAAM,WAAW,WAAW;IACxB,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,kCAAkC;IAClC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0BAA0B;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kFAAkF;IAClF,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,WAAW;IACxB,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6CAA6C;IAC7C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kCAAkC;IAClC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,yCAAyC;IACzC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qCAAqC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0BAA0B;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,gBAAgB,CAClC,OAAO,GAAE,WAAgB,GAC1B,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CAmErD;AAED;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CAClC,OAAO,GAAE,WAAgB,GAC1B,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CA4DnD;AAED,MAAM,WAAW,YAAY;IACzB,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,YAAiB,GAAG,IAAI,CAqDlE;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC7B,OAAO,GAAE,WAAW,GAAG,WAAgB,GACxC,OAAO,CAAC;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAAC,CAQ/C"}
|
package/dist/api.js
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Programmatic API for translation sync
|
|
3
|
+
*
|
|
4
|
+
* Use this if you want to integrate sync into your own tooling, CI/CD,
|
|
5
|
+
* or custom workflows.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* import { syncTranslations, pullTranslations } from '@translation-cms/sync/api';
|
|
9
|
+
*
|
|
10
|
+
* // Scan and sync keys to CMS
|
|
11
|
+
* await syncTranslations({ projectRoot: './my-project' });
|
|
12
|
+
*
|
|
13
|
+
* // Fetch translations from CMS
|
|
14
|
+
* await pullTranslations({ projectRoot: './my-project' });
|
|
15
|
+
*/
|
|
16
|
+
import path from 'path';
|
|
17
|
+
import { resolveConfig, resolveRouteParams, findProjectRoot as findProjectRootHelper, loadConfigFile, } from './config/resolve-config.js';
|
|
18
|
+
import { fetchRouteParams } from './core/api.js';
|
|
19
|
+
import { runSync } from './commands/sync.js';
|
|
20
|
+
import { runPull } from './commands/pull.js';
|
|
21
|
+
import { getLastPulledTime } from './core/cache.js';
|
|
22
|
+
/**
|
|
23
|
+
* Scans codebase for translation keys and syncs them to the CMS.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* const result = await syncTranslations({
|
|
27
|
+
* projectRoot: './apps/web',
|
|
28
|
+
* dryRun: false,
|
|
29
|
+
* verbose: true,
|
|
30
|
+
* });
|
|
31
|
+
*
|
|
32
|
+
* console.log(`Synced ${result.keysAdded} new keys`);
|
|
33
|
+
*/
|
|
34
|
+
export async function syncTranslations(options = {}) {
|
|
35
|
+
const { projectRoot = findProjectRootHelper(), dryRun = false, force = false, reportPath, verbose = false, pathMappings, } = options;
|
|
36
|
+
if (verbose) {
|
|
37
|
+
// eslint-disable-next-line no-console
|
|
38
|
+
console.log(`[sync-translations] Syncing from ${projectRoot}...`);
|
|
39
|
+
}
|
|
40
|
+
const fileConfig = loadConfigFile(projectRoot);
|
|
41
|
+
const config = resolveConfig(projectRoot, fileConfig);
|
|
42
|
+
if (!config.cmsUrl || !config.projectId || !config.apiKey) {
|
|
43
|
+
throw new Error('Missing CMS configuration. Set NEXT_PUBLIC_CMS_URL, NEXT_PUBLIC_CMS_PROJECT_ID, and CMS_SYNC_API_KEY.');
|
|
44
|
+
}
|
|
45
|
+
// Fetch route params from CMS and merge with local config
|
|
46
|
+
const cmsRouteParams = await fetchRouteParams(config);
|
|
47
|
+
const userRouteParams = resolveRouteParams(projectRoot, fileConfig);
|
|
48
|
+
const scanOpts = {
|
|
49
|
+
excludedDirs: fileConfig.excludedDirs,
|
|
50
|
+
sourceExtensions: fileConfig.sourceExtensions,
|
|
51
|
+
routeParams: { ...cmsRouteParams, ...userRouteParams },
|
|
52
|
+
projectRoot,
|
|
53
|
+
includeNavRoutes: fileConfig.includeNavRoutes,
|
|
54
|
+
pathMappings,
|
|
55
|
+
};
|
|
56
|
+
const outputDir = fileConfig.outputDir ?? path.join(projectRoot, 'public', 'locales');
|
|
57
|
+
try {
|
|
58
|
+
await runSync(projectRoot, config, scanOpts, {
|
|
59
|
+
outputDir,
|
|
60
|
+
dryRun,
|
|
61
|
+
force,
|
|
62
|
+
reportPath,
|
|
63
|
+
mockDataPath: fileConfig.mockDataPath,
|
|
64
|
+
userRouteParams,
|
|
65
|
+
});
|
|
66
|
+
if (verbose) {
|
|
67
|
+
// eslint-disable-next-line no-console
|
|
68
|
+
console.log(`[sync-translations] Sync complete`);
|
|
69
|
+
}
|
|
70
|
+
// Return placeholder stats (actual stats are logged by runSync)
|
|
71
|
+
return {
|
|
72
|
+
keysAdded: 0,
|
|
73
|
+
keysUpdated: 0,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
if (verbose && error instanceof Error) {
|
|
78
|
+
// eslint-disable-next-line no-console
|
|
79
|
+
console.error('[sync-translations] Sync failed:', error.message);
|
|
80
|
+
}
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Fetches translations from the CMS and writes them as local JSON files.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* await pullTranslations({
|
|
89
|
+
* projectRoot: './apps/web',
|
|
90
|
+
* outputDir: './src/i18n/locales',
|
|
91
|
+
* force: true,
|
|
92
|
+
* });
|
|
93
|
+
*/
|
|
94
|
+
export async function pullTranslations(options = {}) {
|
|
95
|
+
const { projectRoot = findProjectRootHelper(), outputDir, force = false, ttl, environment, verbose = false, } = options;
|
|
96
|
+
if (verbose) {
|
|
97
|
+
// eslint-disable-next-line no-console
|
|
98
|
+
console.log(`[sync-translations] Pulling to ${projectRoot}...`);
|
|
99
|
+
}
|
|
100
|
+
const fileConfig = loadConfigFile(projectRoot);
|
|
101
|
+
const config = resolveConfig(projectRoot, fileConfig);
|
|
102
|
+
if (!config.cmsUrl || !config.projectId || !config.apiKey) {
|
|
103
|
+
throw new Error('Missing CMS configuration. Set NEXT_PUBLIC_CMS_URL, NEXT_PUBLIC_CMS_PROJECT_ID, and CMS_SYNC_API_KEY.');
|
|
104
|
+
}
|
|
105
|
+
// Build args array for runPull
|
|
106
|
+
const args = [];
|
|
107
|
+
if (force)
|
|
108
|
+
args.push('--force');
|
|
109
|
+
if (environment) {
|
|
110
|
+
args.push('--env');
|
|
111
|
+
args.push(environment);
|
|
112
|
+
}
|
|
113
|
+
if (ttl) {
|
|
114
|
+
args.push('--ttl');
|
|
115
|
+
args.push(String(ttl));
|
|
116
|
+
}
|
|
117
|
+
if (outputDir) {
|
|
118
|
+
args.push('--output');
|
|
119
|
+
args.push(outputDir);
|
|
120
|
+
}
|
|
121
|
+
try {
|
|
122
|
+
await runPull(projectRoot, config, fileConfig, args);
|
|
123
|
+
if (verbose) {
|
|
124
|
+
// eslint-disable-next-line no-console
|
|
125
|
+
console.log(`[sync-translations] Pull complete`);
|
|
126
|
+
}
|
|
127
|
+
// Return placeholder stats
|
|
128
|
+
return {
|
|
129
|
+
locales: [],
|
|
130
|
+
fileCount: 0,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
if (verbose && error instanceof Error) {
|
|
135
|
+
// eslint-disable-next-line no-console
|
|
136
|
+
console.error('[sync-translations] Pull failed:', error.message);
|
|
137
|
+
}
|
|
138
|
+
throw error;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Starts a polling loop that detects new CMS publishes and automatically
|
|
143
|
+
* re-pulls translations to local JSON files. Non-blocking — returns immediately.
|
|
144
|
+
*
|
|
145
|
+
* Call this once in dev mode after the initial pull:
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* if (phase === PHASE_DEVELOPMENT_SERVER) {
|
|
149
|
+
* await pullTranslations({ projectRoot: '.' });
|
|
150
|
+
* watchTranslations({ projectRoot: '.' });
|
|
151
|
+
* }
|
|
152
|
+
*/
|
|
153
|
+
export function watchTranslations(options = {}) {
|
|
154
|
+
const { projectRoot = findProjectRootHelper(), interval = 10_000 } = options;
|
|
155
|
+
if (interval <= 0)
|
|
156
|
+
return;
|
|
157
|
+
const fileConfig = loadConfigFile(projectRoot);
|
|
158
|
+
const config = resolveConfig(projectRoot, fileConfig);
|
|
159
|
+
if (!config.cmsUrl || !config.projectId || !config.apiKey) {
|
|
160
|
+
// eslint-disable-next-line no-console
|
|
161
|
+
console.warn('[CMS] Missing config — watch disabled');
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const resolvedOutputDir = options.outputDir ??
|
|
165
|
+
fileConfig.outputDir ??
|
|
166
|
+
path.join(projectRoot, 'public', 'locales');
|
|
167
|
+
const statusUrl = `${config.cmsUrl.replace(/\/$/, '')}/api/sync/${config.projectId}/status`;
|
|
168
|
+
const poll = async () => {
|
|
169
|
+
try {
|
|
170
|
+
const res = await fetch(statusUrl, {
|
|
171
|
+
headers: { 'x-api-key': config.apiKey },
|
|
172
|
+
signal: AbortSignal.timeout(5000),
|
|
173
|
+
});
|
|
174
|
+
if (!res.ok)
|
|
175
|
+
return;
|
|
176
|
+
const { lastPublishedAt } = (await res.json());
|
|
177
|
+
if (!lastPublishedAt)
|
|
178
|
+
return;
|
|
179
|
+
const lastPulled = getLastPulledTime(resolvedOutputDir);
|
|
180
|
+
const publishedMs = new Date(lastPublishedAt).getTime();
|
|
181
|
+
if (lastPulled === null || publishedMs > lastPulled) {
|
|
182
|
+
// eslint-disable-next-line no-console
|
|
183
|
+
console.log('[CMS] New translations detected — pulling...');
|
|
184
|
+
await runPull(projectRoot, config, fileConfig, ['--force']);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
// Silently ignore — CMS may be unreachable or dev server starting up
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
setInterval(poll, interval);
|
|
192
|
+
// eslint-disable-next-line no-console
|
|
193
|
+
console.log(`[CMS] Watching for translation updates every ${interval / 1000}s`);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Sync and pull in one operation (equivalent to CLI `sync` command)
|
|
197
|
+
*/
|
|
198
|
+
export async function syncAndPull(options = {}) {
|
|
199
|
+
try {
|
|
200
|
+
await syncTranslations(options);
|
|
201
|
+
await pullTranslations(options);
|
|
202
|
+
return { synced: true, pulled: true };
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
return { synced: false, pulled: false };
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
//# sourceMappingURL=api.js.map
|
package/dist/api.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
|
package/dist/bin.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* sync-translations CLI
|
|
4
|
+
*
|
|
5
|
+
* Subcommands:
|
|
6
|
+
* sync (default) Scan codebase and sync translation keys to the CMS.
|
|
7
|
+
* pull Fetch translations from CMS and write local JSON files.
|
|
8
|
+
* status Show what would change on next sync (no network calls).
|
|
9
|
+
* watch Watch for file changes and auto-sync on save.
|
|
10
|
+
* init Interactive setup — creates .translationsrc.json.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* sync-translations # sync keys + pull
|
|
14
|
+
* sync-translations sync --dry-run # preview changes only
|
|
15
|
+
* sync-translations sync --report scan.json # write JSON report
|
|
16
|
+
* sync-translations pull --output ./locales # custom output dir
|
|
17
|
+
* sync-translations pull --force # ignore TTL cache
|
|
18
|
+
* sync-translations pull --env staging # pull staging env
|
|
19
|
+
* sync-translations pull --ttl 600000 # custom TTL (ms)
|
|
20
|
+
* sync-translations status # diff vs last sync cache
|
|
21
|
+
* sync-translations watch # watch + auto-sync
|
|
22
|
+
* sync-translations init # interactive setup
|
|
23
|
+
*/
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=bin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;;;;;;GAqBG"}
|
package/dist/bin.js
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* sync-translations CLI
|
|
4
|
+
*
|
|
5
|
+
* Subcommands:
|
|
6
|
+
* sync (default) Scan codebase and sync translation keys to the CMS.
|
|
7
|
+
* pull Fetch translations from CMS and write local JSON files.
|
|
8
|
+
* status Show what would change on next sync (no network calls).
|
|
9
|
+
* watch Watch for file changes and auto-sync on save.
|
|
10
|
+
* init Interactive setup — creates .translationsrc.json.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* sync-translations # sync keys + pull
|
|
14
|
+
* sync-translations sync --dry-run # preview changes only
|
|
15
|
+
* sync-translations sync --report scan.json # write JSON report
|
|
16
|
+
* sync-translations pull --output ./locales # custom output dir
|
|
17
|
+
* sync-translations pull --force # ignore TTL cache
|
|
18
|
+
* sync-translations pull --env staging # pull staging env
|
|
19
|
+
* sync-translations pull --ttl 600000 # custom TTL (ms)
|
|
20
|
+
* sync-translations status # diff vs last sync cache
|
|
21
|
+
* sync-translations watch # watch + auto-sync
|
|
22
|
+
* sync-translations init # interactive setup
|
|
23
|
+
*/
|
|
24
|
+
import path from 'path';
|
|
25
|
+
import fs from 'fs';
|
|
26
|
+
import { resolveConfig, resolveRouteParams, findProjectRoot, loadConfigFile, } from './config/resolve-config.js';
|
|
27
|
+
import { fetchRouteParams } from './core/api.js';
|
|
28
|
+
import { runStatus } from './commands/status.js';
|
|
29
|
+
import { runWatch } from './commands/watch.js';
|
|
30
|
+
import { runInit } from './commands/init.js';
|
|
31
|
+
import { runPull } from './commands/pull.js';
|
|
32
|
+
import { runSync } from './commands/sync.js';
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
// Helpers
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
function stripJsonComments(input) {
|
|
37
|
+
let result = '';
|
|
38
|
+
let i = 0;
|
|
39
|
+
while (i < input.length) {
|
|
40
|
+
// --- String literal: copy char-by-char, respecting escape sequences ---
|
|
41
|
+
if (input[i] === '"') {
|
|
42
|
+
result += '"';
|
|
43
|
+
i++;
|
|
44
|
+
while (i < input.length) {
|
|
45
|
+
const ch = input[i];
|
|
46
|
+
result += ch;
|
|
47
|
+
i++;
|
|
48
|
+
if (ch === '\\') {
|
|
49
|
+
// Escaped character — copy next char unconditionally
|
|
50
|
+
if (i < input.length)
|
|
51
|
+
result += input[i++];
|
|
52
|
+
}
|
|
53
|
+
else if (ch === '"') {
|
|
54
|
+
break; // closing quote
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
// --- Line comment: skip everything up to the newline ---
|
|
60
|
+
if (input[i] === '/' && input[i + 1] === '/') {
|
|
61
|
+
while (i < input.length && input[i] !== '\n')
|
|
62
|
+
i++;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
// --- Block comment: skip until closing */ ---
|
|
66
|
+
if (input[i] === '/' && input[i + 1] === '*') {
|
|
67
|
+
i += 2;
|
|
68
|
+
while (i < input.length) {
|
|
69
|
+
if (input[i] === '*' && input[i + 1] === '/') {
|
|
70
|
+
i += 2;
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
i++;
|
|
74
|
+
}
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
result += input[i++];
|
|
78
|
+
}
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Load TypeScript path alias mappings from `tsconfig.json` at the project root.
|
|
83
|
+
*
|
|
84
|
+
* These mappings are passed to the scanner so that aliased imports such as
|
|
85
|
+
* `@/components/button` can be resolved to absolute file paths. tsconfig
|
|
86
|
+
* files are JSONC (JSON with comments) so we strip comments before parsing.
|
|
87
|
+
*
|
|
88
|
+
* Returns null when tsconfig.json is absent, unreadable, or has no `paths`.
|
|
89
|
+
*/
|
|
90
|
+
function loadTsConfigPathMappings(root) {
|
|
91
|
+
const tsconfigPath = path.join(root, 'tsconfig.json');
|
|
92
|
+
if (!fs.existsSync(tsconfigPath))
|
|
93
|
+
return null;
|
|
94
|
+
try {
|
|
95
|
+
const cleaned = stripJsonComments(fs.readFileSync(tsconfigPath, 'utf-8'));
|
|
96
|
+
const tsconfig = JSON.parse(cleaned);
|
|
97
|
+
// Drill into compilerOptions.paths — guard each level against unexpected shapes
|
|
98
|
+
if (typeof tsconfig !== 'object' || tsconfig === null)
|
|
99
|
+
return null;
|
|
100
|
+
if (!('compilerOptions' in tsconfig))
|
|
101
|
+
return null;
|
|
102
|
+
const opts = tsconfig.compilerOptions;
|
|
103
|
+
if (typeof opts !== 'object' || opts === null)
|
|
104
|
+
return null;
|
|
105
|
+
if (!('paths' in opts))
|
|
106
|
+
return null;
|
|
107
|
+
const paths = opts.paths;
|
|
108
|
+
if (typeof paths === 'object' && paths !== null)
|
|
109
|
+
return paths;
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
// Silently ignore tsconfig parse errors — scanning continues without alias resolution
|
|
113
|
+
}
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
/** Return the value that follows `flag` in `args`, or undefined if absent. */
|
|
117
|
+
function getFlag(args, flag) {
|
|
118
|
+
const idx = args.indexOf(flag);
|
|
119
|
+
return idx !== -1 && args[idx + 1] ? args[idx + 1] : undefined;
|
|
120
|
+
}
|
|
121
|
+
/** Return true when any of the given flag strings is present in `args`. */
|
|
122
|
+
function hasFlag(args, ...flags) {
|
|
123
|
+
return flags.some(f => args.includes(f));
|
|
124
|
+
}
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
// Main
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
/** All valid subcommand names. Used for validation and dispatch. */
|
|
129
|
+
const SUBCOMMANDS = new Set(['sync', 'pull', 'status', 'watch', 'init']);
|
|
130
|
+
/**
|
|
131
|
+
* CLI entry point.
|
|
132
|
+
*
|
|
133
|
+
* Resolves config, loads tsconfig path mappings, and dispatches to the
|
|
134
|
+
* appropriate command handler. Config resolution and scanner setup are shared
|
|
135
|
+
* across all commands except `init` (which runs before a config file exists).
|
|
136
|
+
*/
|
|
137
|
+
async function main() {
|
|
138
|
+
const args = process.argv.slice(2);
|
|
139
|
+
// First non-flag argument is the subcommand; default to 'sync' when omitted
|
|
140
|
+
const subcommand = args.find(a => !a.startsWith('-')) ?? 'sync';
|
|
141
|
+
if (!SUBCOMMANDS.has(subcommand)) {
|
|
142
|
+
// eslint-disable-next-line no-console
|
|
143
|
+
console.error(`Unknown subcommand: ${subcommand}`);
|
|
144
|
+
// eslint-disable-next-line no-console
|
|
145
|
+
console.error(`Available: ${[...SUBCOMMANDS].join(', ')}`);
|
|
146
|
+
process.exit(1);
|
|
147
|
+
}
|
|
148
|
+
const root = findProjectRoot();
|
|
149
|
+
const fileConfig = loadConfigFile(root);
|
|
150
|
+
// `init` runs before a config file exists, so it short-circuits here
|
|
151
|
+
if (subcommand === 'init') {
|
|
152
|
+
await runInit(root);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const config = resolveConfig(root, fileConfig);
|
|
156
|
+
// Path mappings let the scanner resolve aliased imports (e.g. @/components/…)
|
|
157
|
+
const pathMappings = loadTsConfigPathMappings(root);
|
|
158
|
+
// Route params from the CMS are merged with locally configured params;
|
|
159
|
+
// skip the network call for `pull` since it doesn't scan the codebase
|
|
160
|
+
let cmsRouteParams = {};
|
|
161
|
+
if (subcommand !== 'pull') {
|
|
162
|
+
cmsRouteParams = await fetchRouteParams(config);
|
|
163
|
+
}
|
|
164
|
+
// User-defined params (from config) take precedence over CMS-generated ones
|
|
165
|
+
const allRouteParams = resolveRouteParams(root, fileConfig);
|
|
166
|
+
const scanOpts = {
|
|
167
|
+
excludedDirs: fileConfig.excludedDirs,
|
|
168
|
+
sourceExtensions: fileConfig.sourceExtensions,
|
|
169
|
+
routeParams: { ...cmsRouteParams, ...allRouteParams },
|
|
170
|
+
pathMappings: pathMappings ?? undefined,
|
|
171
|
+
projectRoot: root,
|
|
172
|
+
includeNavRoutes: fileConfig.includeNavRoutes,
|
|
173
|
+
};
|
|
174
|
+
if (subcommand === 'status') {
|
|
175
|
+
runStatus(root, scanOpts);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
if (subcommand === 'watch') {
|
|
179
|
+
const outputDir = fileConfig.outputDir ?? path.join(root, 'public', 'locales');
|
|
180
|
+
await runWatch(root, config, outputDir, scanOpts);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
if (subcommand === 'pull') {
|
|
184
|
+
await runPull(root, config, fileConfig, args);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
// --- sync (default) ---
|
|
188
|
+
const outputDir = fileConfig.outputDir ?? path.join(root, 'public', 'locales');
|
|
189
|
+
const reportArg = getFlag(args, '--report');
|
|
190
|
+
await runSync(root, config, scanOpts, {
|
|
191
|
+
outputDir,
|
|
192
|
+
dryRun: hasFlag(args, '--dry-run'),
|
|
193
|
+
force: hasFlag(args, '--force'),
|
|
194
|
+
// Resolve report path relative to project root when not absolute
|
|
195
|
+
reportPath: reportArg
|
|
196
|
+
? path.isAbsolute(reportArg)
|
|
197
|
+
? reportArg
|
|
198
|
+
: path.join(root, reportArg)
|
|
199
|
+
: undefined,
|
|
200
|
+
mockDataPath: fileConfig.mockDataPath,
|
|
201
|
+
userRouteParams: fileConfig.routeParams,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
main().catch(err => {
|
|
205
|
+
process.stderr.write(`${err instanceof Error ? (err.stack ?? err.message) : String(err)}\n`);
|
|
206
|
+
process.exit(1);
|
|
207
|
+
});
|
|
208
|
+
//# sourceMappingURL=bin.js.map
|
package/dist/bin.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive `init` command.
|
|
3
|
+
*
|
|
4
|
+
* Walks the user through a series of prompts and writes a
|
|
5
|
+
* `.translationsrc.json` config file to the project root.
|
|
6
|
+
* Optionally scaffolds the i18n boilerplate files (settings,
|
|
7
|
+
* client, server, provider) into the chosen i18n directory.
|
|
8
|
+
*/
|
|
9
|
+
export declare function runInit(root: string): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=init.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwHzD"}
|