@translation-cms/sync 1.2.1 → 1.2.4

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.
Files changed (161) hide show
  1. package/dist/bin.d.ts +25 -0
  2. package/dist/bin.d.ts.map +1 -0
  3. package/dist/bin.js +173 -0
  4. package/dist/bin.js.map +1 -0
  5. package/dist/commands/init.d.ts +2 -0
  6. package/dist/commands/init.d.ts.map +1 -0
  7. package/dist/commands/init.js +68 -0
  8. package/dist/commands/init.js.map +1 -0
  9. package/dist/commands/pull.d.ts +3 -0
  10. package/dist/commands/pull.d.ts.map +1 -0
  11. package/dist/commands/pull.js +22 -0
  12. package/dist/commands/pull.js.map +1 -0
  13. package/dist/commands/status.d.ts +3 -0
  14. package/dist/commands/status.d.ts.map +1 -0
  15. package/dist/commands/status.js +46 -0
  16. package/dist/commands/status.js.map +1 -0
  17. package/dist/commands/sync.d.ts +10 -0
  18. package/dist/commands/sync.d.ts.map +1 -0
  19. package/dist/commands/sync.js +20 -0
  20. package/dist/commands/sync.js.map +1 -0
  21. package/dist/commands/watch.d.ts +4 -0
  22. package/dist/commands/watch.d.ts.map +1 -0
  23. package/dist/commands/watch.js +51 -0
  24. package/dist/commands/watch.js.map +1 -0
  25. package/dist/{load-config.d.ts → config/resolve-config.d.ts} +13 -10
  26. package/dist/config/resolve-config.d.ts.map +1 -0
  27. package/dist/{resolve-config.js → config/resolve-config.js} +21 -0
  28. package/dist/config/resolve-config.js.map +1 -0
  29. package/dist/core/api-internals/helpers.d.ts +9 -0
  30. package/dist/core/api-internals/helpers.d.ts.map +1 -0
  31. package/dist/core/api-internals/helpers.js +14 -0
  32. package/dist/core/api-internals/helpers.js.map +1 -0
  33. package/dist/core/api-internals/pull.d.ts +11 -0
  34. package/dist/core/api-internals/pull.d.ts.map +1 -0
  35. package/dist/core/api-internals/pull.js +124 -0
  36. package/dist/core/api-internals/pull.js.map +1 -0
  37. package/dist/core/api-internals/route-config.d.ts +13 -0
  38. package/dist/core/api-internals/route-config.d.ts.map +1 -0
  39. package/dist/core/api-internals/route-config.js +34 -0
  40. package/dist/core/api-internals/route-config.js.map +1 -0
  41. package/dist/core/api-internals/sync.d.ts +12 -0
  42. package/dist/core/api-internals/sync.d.ts.map +1 -0
  43. package/dist/core/api-internals/sync.js +95 -0
  44. package/dist/core/api-internals/sync.js.map +1 -0
  45. package/dist/core/api-internals/types.d.ts +25 -0
  46. package/dist/core/api-internals/types.d.ts.map +1 -0
  47. package/dist/core/api-internals/types.js +5 -0
  48. package/dist/core/api-internals/types.js.map +1 -0
  49. package/dist/core/api.d.ts +11 -0
  50. package/dist/core/api.d.ts.map +1 -0
  51. package/dist/core/api.js +11 -0
  52. package/dist/core/api.js.map +1 -0
  53. package/dist/{sync.d.ts → core/cache.d.ts} +5 -33
  54. package/dist/core/cache.d.ts.map +1 -0
  55. package/dist/core/cache.js +143 -0
  56. package/dist/core/cache.js.map +1 -0
  57. package/dist/core/scanner-internals/ast.d.ts +22 -0
  58. package/dist/core/scanner-internals/ast.d.ts.map +1 -0
  59. package/dist/core/scanner-internals/ast.js +80 -0
  60. package/dist/core/scanner-internals/ast.js.map +1 -0
  61. package/dist/core/scanner-internals/file-walker.d.ts +9 -0
  62. package/dist/core/scanner-internals/file-walker.d.ts.map +1 -0
  63. package/dist/core/scanner-internals/file-walker.js +25 -0
  64. package/dist/core/scanner-internals/file-walker.js.map +1 -0
  65. package/dist/core/scanner-internals/import-resolver.d.ts +13 -0
  66. package/dist/core/scanner-internals/import-resolver.d.ts.map +1 -0
  67. package/dist/core/scanner-internals/import-resolver.js +124 -0
  68. package/dist/core/scanner-internals/import-resolver.js.map +1 -0
  69. package/dist/core/scanner-internals/key-extractor.d.ts +16 -0
  70. package/dist/core/scanner-internals/key-extractor.d.ts.map +1 -0
  71. package/dist/core/scanner-internals/key-extractor.js +172 -0
  72. package/dist/core/scanner-internals/key-extractor.js.map +1 -0
  73. package/dist/core/scanner-internals/route-detector.d.ts +19 -0
  74. package/dist/core/scanner-internals/route-detector.d.ts.map +1 -0
  75. package/dist/core/scanner-internals/route-detector.js +74 -0
  76. package/dist/core/scanner-internals/route-detector.js.map +1 -0
  77. package/dist/core/scanner-internals/types.d.ts +53 -0
  78. package/dist/core/scanner-internals/types.d.ts.map +1 -0
  79. package/dist/core/scanner-internals/types.js +29 -0
  80. package/dist/core/scanner-internals/types.js.map +1 -0
  81. package/dist/core/scanner.d.ts +20 -0
  82. package/dist/core/scanner.d.ts.map +1 -0
  83. package/dist/core/scanner.js +113 -0
  84. package/dist/core/scanner.js.map +1 -0
  85. package/dist/index.d.ts +2 -2
  86. package/dist/index.d.ts.map +1 -1
  87. package/dist/index.js +2 -2
  88. package/dist/index.js.map +1 -1
  89. package/dist/preview/index.d.ts +38 -0
  90. package/dist/preview/index.d.ts.map +1 -0
  91. package/dist/preview/index.js +114 -0
  92. package/dist/preview/index.js.map +1 -0
  93. package/dist/preview/internals/highlight.d.ts +22 -0
  94. package/dist/preview/internals/highlight.d.ts.map +1 -0
  95. package/dist/preview/internals/highlight.js +153 -0
  96. package/dist/preview/internals/highlight.js.map +1 -0
  97. package/dist/preview/internals/interactions.d.ts +15 -0
  98. package/dist/preview/internals/interactions.d.ts.map +1 -0
  99. package/dist/preview/internals/interactions.js +38 -0
  100. package/dist/preview/internals/interactions.js.map +1 -0
  101. package/dist/preview/internals/locales.d.ts +9 -0
  102. package/dist/preview/internals/locales.d.ts.map +1 -0
  103. package/dist/preview/internals/locales.js +24 -0
  104. package/dist/preview/internals/locales.js.map +1 -0
  105. package/dist/preview/internals/state.d.ts +35 -0
  106. package/dist/preview/internals/state.d.ts.map +1 -0
  107. package/dist/preview/internals/state.js +65 -0
  108. package/dist/preview/internals/state.js.map +1 -0
  109. package/dist/preview/internals/styles.d.ts +8 -0
  110. package/dist/preview/internals/styles.d.ts.map +1 -0
  111. package/dist/preview/internals/styles.js +28 -0
  112. package/dist/preview/internals/styles.js.map +1 -0
  113. package/dist/preview/internals/types.d.ts +49 -0
  114. package/dist/preview/internals/types.d.ts.map +1 -0
  115. package/dist/preview/internals/types.js +5 -0
  116. package/dist/preview/internals/types.js.map +1 -0
  117. package/dist/scaffold/index.d.ts +3 -0
  118. package/dist/scaffold/index.d.ts.map +1 -0
  119. package/dist/scaffold/index.js +3 -0
  120. package/dist/scaffold/index.js.map +1 -0
  121. package/dist/scaffold/intenrals/scaffold.d.ts +7 -0
  122. package/dist/scaffold/intenrals/scaffold.d.ts.map +1 -0
  123. package/dist/scaffold/intenrals/scaffold.js +34 -0
  124. package/dist/scaffold/intenrals/scaffold.js.map +1 -0
  125. package/dist/scaffold/intenrals/templates.d.ts +10 -0
  126. package/dist/scaffold/intenrals/templates.d.ts.map +1 -0
  127. package/dist/{scaffold.js → scaffold/intenrals/templates.js} +10 -38
  128. package/dist/scaffold/intenrals/templates.js.map +1 -0
  129. package/dist/{scaffold.d.ts → scaffold/intenrals/types.d.ts} +4 -2
  130. package/dist/scaffold/intenrals/types.d.ts.map +1 -0
  131. package/dist/scaffold/intenrals/types.js +5 -0
  132. package/dist/scaffold/intenrals/types.js.map +1 -0
  133. package/package.json +7 -7
  134. package/schema.json +64 -0
  135. package/dist/cli-entry.d.ts +0 -3
  136. package/dist/cli-entry.d.ts.map +0 -1
  137. package/dist/cli-entry.js +0 -390
  138. package/dist/cli-entry.js.map +0 -1
  139. package/dist/cli.d.ts +0 -16
  140. package/dist/cli.d.ts.map +0 -1
  141. package/dist/cli.js +0 -16
  142. package/dist/cli.js.map +0 -1
  143. package/dist/load-config.d.ts.map +0 -1
  144. package/dist/load-config.js +0 -24
  145. package/dist/load-config.js.map +0 -1
  146. package/dist/preview.d.ts +0 -88
  147. package/dist/preview.d.ts.map +0 -1
  148. package/dist/preview.js +0 -461
  149. package/dist/preview.js.map +0 -1
  150. package/dist/resolve-config.d.ts +0 -15
  151. package/dist/resolve-config.d.ts.map +0 -1
  152. package/dist/resolve-config.js.map +0 -1
  153. package/dist/scaffold.d.ts.map +0 -1
  154. package/dist/scaffold.js.map +0 -1
  155. package/dist/scanner.d.ts +0 -77
  156. package/dist/scanner.d.ts.map +0 -1
  157. package/dist/scanner.js +0 -555
  158. package/dist/scanner.js.map +0 -1
  159. package/dist/sync.d.ts.map +0 -1
  160. package/dist/sync.js +0 -383
  161. package/dist/sync.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../../src/core/api-internals/pull.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAuC9C;;;GAGG;AACH,wBAAsB,gBAAgB,CAClC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,WAAW,GAClB,OAAO,CAAC,IAAI,CAAC,CAgHf"}
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Pull (fetch) published translations from CMS to local JSON files.
3
+ */
4
+ import fs from 'fs';
5
+ import path from 'path';
6
+ import { getLastPulledTime, saveLastPulledTime, PULL_META_FILE, DEFAULT_PULL_TTL_MS, } from '../cache.js';
7
+ /**
8
+ * Converts a flat `{ "namespace:key": value }` object into
9
+ * `{ namespace: { key: value } }`, with dot-notation key support.
10
+ */
11
+ function nestTranslationKeys(flat) {
12
+ const nested = {};
13
+ for (const [key, value] of Object.entries(flat)) {
14
+ const colon = key.indexOf(':');
15
+ if (colon === -1)
16
+ continue;
17
+ const ns = key.slice(0, colon);
18
+ const k = key.slice(colon + 1);
19
+ if (!nested[ns])
20
+ nested[ns] = {};
21
+ const parts = k.split('.');
22
+ let current = nested[ns];
23
+ for (let i = 0; i < parts.length - 1; i++) {
24
+ const part = parts[i];
25
+ if (part && !current[part])
26
+ current[part] = {};
27
+ if (part)
28
+ current = current[part];
29
+ }
30
+ const lastPart = parts[parts.length - 1];
31
+ if (lastPart)
32
+ current[lastPart] = value;
33
+ }
34
+ return nested;
35
+ }
36
+ /**
37
+ * Fetch published translations from the CMS and write them to local JSON files.
38
+ * Supports caching with TTL and force refresh.
39
+ */
40
+ export async function pullTranslations(config, opts) {
41
+ const ttl = opts.ttlMs ?? DEFAULT_PULL_TTL_MS;
42
+ console.log(`[CMS] Checking for ${PULL_META_FILE}...`);
43
+ if (!opts.force) {
44
+ const lastPulled = getLastPulledTime(opts.outputDir);
45
+ if (lastPulled !== null) {
46
+ const age = Date.now() - lastPulled;
47
+ const ageS = Math.round(age / 1000);
48
+ const ttlS = Math.round(ttl / 1000);
49
+ console.log(`[CMS] ${PULL_META_FILE} found: ${new Date(lastPulled).toISOString()}`);
50
+ if (age < ttl) {
51
+ console.log(`[CMS] ✓ Translations fresh (age: ${ageS}s < TTL: ${ttlS}s) — using local files`);
52
+ return;
53
+ }
54
+ console.log(`[CMS] ⟳ Translations stale (age: ${ageS}s ≥ TTL: ${ttlS}s) — refreshing...`);
55
+ }
56
+ else {
57
+ console.log(`[CMS] ${PULL_META_FILE} not found, will refresh`);
58
+ }
59
+ }
60
+ else {
61
+ console.log(`[CMS] --force flag detected, refreshing...`);
62
+ }
63
+ let url = `${config.cmsUrl.replace(/\/$/, '')}/api/translations/${config.projectId}`;
64
+ if (opts.env) {
65
+ url += `?env=${encodeURIComponent(opts.env)}`;
66
+ console.log(`[CMS] Environment: ${opts.env}`);
67
+ }
68
+ console.log(`[CMS] Fetching from: ${url}`);
69
+ const response = await fetch(url, {
70
+ headers: { 'x-api-key': config.apiKey },
71
+ });
72
+ if (!response.ok) {
73
+ console.error(`[CMS] ✗ Pull failed: ${response.status} ${response.statusText}`);
74
+ process.exit(1);
75
+ }
76
+ const data = (await response.json());
77
+ const processed = {};
78
+ for (const [locale, content] of Object.entries(data)) {
79
+ if (typeof content !== 'object' || content === null)
80
+ continue;
81
+ const obj = content;
82
+ const firstVal = Object.values(obj)[0];
83
+ processed[locale] =
84
+ typeof firstVal === 'string'
85
+ ? nestTranslationKeys(obj)
86
+ : obj;
87
+ }
88
+ fs.mkdirSync(opts.outputDir, { recursive: true });
89
+ const writtenFiles = new Set();
90
+ let fileCount = 0;
91
+ // Write one file per locale: {outputDir}/{locale}.json
92
+ // Structure: { namespace: { key: value } }
93
+ // Compatible with i18next-resources-to-backend
94
+ for (const [locale, namespaces] of Object.entries(processed)) {
95
+ const filePath = path.join(opts.outputDir, `${locale}.json`);
96
+ fs.writeFileSync(filePath, JSON.stringify(namespaces, null, 2), 'utf-8');
97
+ writtenFiles.add(filePath);
98
+ fileCount++;
99
+ }
100
+ // Empty locale files that no longer exist in CMS (don't delete — static imports would break)
101
+ let emptied = 0;
102
+ for (const entry of fs.readdirSync(opts.outputDir, {
103
+ withFileTypes: true,
104
+ })) {
105
+ if (entry.name === PULL_META_FILE)
106
+ continue;
107
+ if (!entry.isFile() || !entry.name.endsWith('.json'))
108
+ continue;
109
+ const filePath = path.join(opts.outputDir, entry.name);
110
+ if (!writtenFiles.has(filePath)) {
111
+ fs.writeFileSync(filePath, '{}\n', 'utf-8');
112
+ console.log(`[CMS] ○ Emptied: ${entry.name} (no data in CMS)`);
113
+ emptied++;
114
+ }
115
+ }
116
+ saveLastPulledTime(opts.outputDir);
117
+ if (emptied > 0) {
118
+ console.log(`[CMS] ✓ Refresh complete: wrote ${fileCount} files, emptied ${emptied} stale files`);
119
+ }
120
+ else {
121
+ console.log(`[CMS] ✓ Refresh complete: wrote ${fileCount} JSON files, updated ${PULL_META_FILE}`);
122
+ }
123
+ }
124
+ //# sourceMappingURL=pull.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull.js","sourceRoot":"","sources":["../../../src/core/api-internals/pull.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Fetch preview route configuration from CMS.
3
+ */
4
+ import type { Config } from '../../config/resolve-config.js';
5
+ /**
6
+ * Fetches the project's preview route config from the CMS and returns it as
7
+ * a routeParams Record (route pattern → params), ready to pass to scanProject.
8
+ *
9
+ * Returns an empty object when the CMS doesn't have any routes configured or
10
+ * when the request fails (non-fatal — a warning is printed instead).
11
+ */
12
+ export declare function fetchRouteParams(config: Config): Promise<Record<string, Record<string, string>>>;
13
+ //# sourceMappingURL=route-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-config.d.ts","sourceRoot":"","sources":["../../../src/core/api-internals/route-config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gCAAgC,CAAC;AAE7D;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAClC,MAAM,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CA8BjD"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Fetch preview route configuration from CMS.
3
+ */
4
+ /**
5
+ * Fetches the project's preview route config from the CMS and returns it as
6
+ * a routeParams Record (route pattern → params), ready to pass to scanProject.
7
+ *
8
+ * Returns an empty object when the CMS doesn't have any routes configured or
9
+ * when the request fails (non-fatal — a warning is printed instead).
10
+ */
11
+ export async function fetchRouteParams(config) {
12
+ const url = `${config.cmsUrl.replace(/\/$/, '')}/api/sync/${config.projectId}`;
13
+ try {
14
+ const response = await fetch(url, {
15
+ headers: { 'x-api-key': config.apiKey },
16
+ });
17
+ if (!response.ok) {
18
+ console.warn(`[CMS] Could not fetch route config (${response.status}) — using local routeParams only`);
19
+ return {};
20
+ }
21
+ const data = (await response.json());
22
+ const routeParams = data.routeParams ?? {};
23
+ const count = Object.keys(routeParams).length;
24
+ if (count > 0) {
25
+ console.log(`[CMS] Loaded ${count} preview route(s) from CMS config`);
26
+ }
27
+ return routeParams;
28
+ }
29
+ catch (err) {
30
+ console.warn(`[CMS] Could not fetch route config — using local routeParams only:`, err instanceof Error ? err.message : String(err));
31
+ return {};
32
+ }
33
+ }
34
+ //# sourceMappingURL=route-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-config.js","sourceRoot":"","sources":["../../../src/core/api-internals/route-config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAClC,MAAc;IAEd,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,aAAa,MAAM,CAAC,SAAS,EAAE,CAAC;IAC/E,IAAI,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC9B,OAAO,EAAE,EAAE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE;SAC1C,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CACR,uCAAuC,QAAQ,CAAC,MAAM,kCAAkC,CAC3F,CAAC;YACF,OAAO,EAAE,CAAC;QACd,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAElC,CAAC;QACF,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC;QAC3C,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC;QAC9C,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACZ,OAAO,CAAC,GAAG,CACP,gBAAgB,KAAK,mCAAmC,CAC3D,CAAC;QACN,CAAC;QACD,OAAO,WAAW,CAAC;IACvB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACX,OAAO,CAAC,IAAI,CACR,oEAAoE,EACpE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CACnD,CAAC;QACF,OAAO,EAAE,CAAC;IACd,CAAC;AACL,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Sync (push) translation keys to CMS.
3
+ */
4
+ import type { Config } from '../../config/resolve-config.js';
5
+ import type { NamespaceMap } from '../scanner.js';
6
+ import type { PostToSyncOptions } from './types.js';
7
+ /**
8
+ * Push translation keys to the CMS for syncing.
9
+ * Optionally supports dry-run mode and report generation.
10
+ */
11
+ export declare function postToSync(config: Config, namespaces: NamespaceMap, opts?: PostToSyncOptions): Promise<void>;
12
+ //# sourceMappingURL=sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../src/core/api-internals/sync.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAgB,MAAM,YAAY,CAAC;AAalE;;;GAGG;AACH,wBAAsB,UAAU,CAC5B,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,YAAY,EACxB,IAAI,GAAE,iBAA2C,GAClD,OAAO,CAAC,IAAI,CAAC,CA+Hf"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Sync (push) translation keys to CMS.
3
+ */
4
+ import { loadSyncCache, saveSyncCache, isSyncNeeded, computeDiff, writeReport, serializeNamespaces, formatPreviewRoutes, } from '../cache.js';
5
+ import { resolveReportPath } from './helpers.js';
6
+ /**
7
+ * Push translation keys to the CMS for syncing.
8
+ * Optionally supports dry-run mode and report generation.
9
+ */
10
+ export async function postToSync(config, namespaces, opts = { root: process.cwd() }) {
11
+ const { serialized, totalKeys } = serializeNamespaces(namespaces);
12
+ const namespaceCount = Object.keys(serialized).length;
13
+ console.log(`Found ${totalKeys} key(s) across ${namespaceCount} namespace(s): ${Object.keys(serialized).join(', ')}`);
14
+ if (totalKeys === 0) {
15
+ console.log('Nothing to sync.');
16
+ return;
17
+ }
18
+ const cached = loadSyncCache(opts.root);
19
+ // ---- Dry-run: print diff and return without posting --------------------
20
+ if (opts.dryRun) {
21
+ const diff = computeDiff(serialized, cached);
22
+ console.log('\n[dry-run] Would sync to CMS (not actually posting):');
23
+ console.log(` + ${diff.added.length} new key(s)`);
24
+ console.log(` - ${diff.removed.length} removed key(s)`);
25
+ console.log(` ~ ${diff.routesChanged.length} route update(s)`);
26
+ console.log(` = ${diff.unchanged} unchanged`);
27
+ if (diff.added.length > 0) {
28
+ console.log('\nNew keys:');
29
+ for (const { namespace, key, routes } of diff.added) {
30
+ console.log(` + ${namespace}:${key} (${formatPreviewRoutes(routes)})`);
31
+ }
32
+ }
33
+ if (diff.removed.length > 0) {
34
+ console.log('\nRemoved keys:');
35
+ for (const { namespace, key } of diff.removed) {
36
+ console.log(` - ${namespace}:${key}`);
37
+ }
38
+ }
39
+ if (diff.routesChanged.length > 0) {
40
+ console.log('\nRoute updates:');
41
+ for (const { namespace, key, before, after, } of diff.routesChanged) {
42
+ console.log(` ~ ${namespace}:${key} [${formatPreviewRoutes(before)}] -> [${formatPreviewRoutes(after)}]`);
43
+ }
44
+ }
45
+ if (opts.reportPath) {
46
+ writeReport(resolveReportPath(opts.root, opts.reportPath), serialized, diff);
47
+ }
48
+ return;
49
+ }
50
+ // ---- Skip if no changes ------------------------------------------------
51
+ if (!opts.force && !isSyncNeeded(serialized, cached)) {
52
+ console.log('No changes detected — skipping sync. Use --force to override.');
53
+ if (opts.reportPath) {
54
+ writeReport(resolveReportPath(opts.root, opts.reportPath), serialized);
55
+ }
56
+ return;
57
+ }
58
+ // ---- Post to CMS -------------------------------------------------------
59
+ const url = `${config.cmsUrl.replace(/\/$/, '')}/api/sync/${config.projectId}`;
60
+ console.log(`Posting to ${url}...`);
61
+ const response = await fetch(url, {
62
+ method: 'POST',
63
+ headers: {
64
+ 'Content-Type': 'application/json',
65
+ 'x-api-key': config.apiKey,
66
+ },
67
+ body: JSON.stringify({ namespaces: serialized }),
68
+ });
69
+ const contentType = response.headers.get('content-type') ?? '';
70
+ const isJson = contentType.includes('application/json');
71
+ if (!response.ok) {
72
+ console.error(`Sync failed: ${response.status} ${response.statusText}`);
73
+ if (!isJson) {
74
+ console.error(`The CMS returned HTML instead of JSON. Is the sync endpoint available at ${url}?`);
75
+ }
76
+ else {
77
+ console.error(JSON.stringify(await response.json()));
78
+ }
79
+ process.exit(1);
80
+ }
81
+ if (!isJson) {
82
+ console.error(`The CMS returned HTML instead of JSON. Is the sync endpoint available at ${url}?`);
83
+ process.exit(1);
84
+ }
85
+ const data = (await response.json());
86
+ console.log(`Synced: ${data.created} created, ${data.updated ?? 0} routes updated, ${data.existing} existing`);
87
+ if (data.message)
88
+ console.log(data.message);
89
+ saveSyncCache(opts.root, serialized);
90
+ if (opts.reportPath) {
91
+ const diff = computeDiff(serialized, cached);
92
+ writeReport(resolveReportPath(opts.root, opts.reportPath), serialized, diff);
93
+ }
94
+ }
95
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../../src/core/api-internals/sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * TypeScript types for sync API.
3
+ */
4
+ export interface SyncResponse {
5
+ created: number;
6
+ updated?: number;
7
+ existing: number;
8
+ message?: string;
9
+ }
10
+ export interface PostToSyncOptions {
11
+ root: string;
12
+ force?: boolean;
13
+ /** Preview what would be synced without posting to the CMS. */
14
+ dryRun?: boolean;
15
+ /** Write a JSON scan report to this file path. */
16
+ reportPath?: string;
17
+ }
18
+ export interface PullOptions {
19
+ outputDir: string;
20
+ force?: boolean;
21
+ ttlMs?: number;
22
+ /** Pull from a specific environment (e.g. "staging"). */
23
+ env?: string;
24
+ }
25
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/api-internals/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,YAAY;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,+DAA+D;IAC/D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,GAAG,CAAC,EAAE,MAAM,CAAC;CAChB"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * TypeScript types for sync API.
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/api-internals/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * CMS Sync API — Orchestrator
3
+ *
4
+ * Coordinates pushing translation keys to the CMS and pulling published
5
+ * translations back to local JSON files.
6
+ */
7
+ export type { SyncResponse, PostToSyncOptions, PullOptions, } from './api-internals/types.js';
8
+ export { fetchRouteParams } from './api-internals/route-config.js';
9
+ export { postToSync } from './api-internals/sync.js';
10
+ export { pullTranslations } from './api-internals/pull.js';
11
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/core/api.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,YAAY,EACR,YAAY,EACZ,iBAAiB,EACjB,WAAW,GACd,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * CMS Sync API — Orchestrator
3
+ *
4
+ * Coordinates pushing translation keys to the CMS and pulling published
5
+ * translations back to local JSON files.
6
+ */
7
+ // Re-export public functions
8
+ export { fetchRouteParams } from './api-internals/route-config.js';
9
+ export { postToSync } from './api-internals/sync.js';
10
+ export { pullTranslations } from './api-internals/pull.js';
11
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/core/api.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,6BAA6B;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC"}
@@ -1,15 +1,8 @@
1
- import type { Config } from './resolve-config.js';
2
1
  import type { NamespaceMap, PreviewRoute } from './scanner.js';
3
2
  export type SerializedNamespaces = Record<string, Array<{
4
3
  key: string;
5
4
  previewRoutes: PreviewRoute[];
6
5
  }>>;
7
- export interface SyncResponse {
8
- created: number;
9
- updated?: number;
10
- existing: number;
11
- message?: string;
12
- }
13
6
  export interface SyncDiff {
14
7
  added: Array<{
15
8
  namespace: string;
@@ -28,21 +21,6 @@ export interface SyncDiff {
28
21
  }>;
29
22
  unchanged: number;
30
23
  }
31
- export interface PullOptions {
32
- outputDir: string;
33
- force?: boolean;
34
- ttlMs?: number;
35
- /** Pull from a specific environment (e.g. "staging"). Requires CMS support. */
36
- env?: string;
37
- }
38
- export interface PostToSyncOptions {
39
- root: string;
40
- force?: boolean;
41
- /** Preview what would be synced without posting to the CMS. */
42
- dryRun?: boolean;
43
- /** Write a JSON scan report to this file (absolute or relative to root). */
44
- reportPath?: string;
45
- }
46
24
  export declare function loadSyncCache(root: string): SerializedNamespaces | null;
47
25
  export declare function saveSyncCache(root: string, data: SerializedNamespaces): void;
48
26
  export declare function isSyncNeeded(current: SerializedNamespaces, cached: SerializedNamespaces | null): boolean;
@@ -52,16 +30,10 @@ export declare function serializeNamespaces(namespaces: NamespaceMap): {
52
30
  serialized: SerializedNamespaces;
53
31
  totalKeys: number;
54
32
  };
33
+ export declare const PULL_META_FILE = ".last-pulled";
34
+ export declare const DEFAULT_PULL_TTL_MS: number;
35
+ export declare function getLastPulledTime(outputDir: string): number | null;
36
+ export declare function saveLastPulledTime(outputDir: string): void;
55
37
  export declare function formatPreviewRoute(route: PreviewRoute): string;
56
38
  export declare function formatPreviewRoutes(routes: PreviewRoute[]): string;
57
- /**
58
- * Fetches the project's preview route config from the CMS and returns it as
59
- * a routeParams Record (route pattern → params), ready to pass to scanProject.
60
- *
61
- * Returns an empty object when the CMS doesn't have any routes configured or
62
- * when the request fails (non-fatal — a warning is printed instead).
63
- */
64
- export declare function fetchRouteParams(config: Config): Promise<Record<string, Record<string, string>>>;
65
- export declare function postToSync(config: Config, namespaces: NamespaceMap, opts?: PostToSyncOptions): Promise<void>;
66
- export declare function pullTranslations(config: Config, opts: PullOptions): Promise<void>;
67
- //# sourceMappingURL=sync.d.ts.map
39
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/core/cache.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAM/D,MAAM,MAAM,oBAAoB,GAAG,MAAM,CACrC,MAAM,EACN,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,YAAY,EAAE,CAAA;CAAE,CAAC,CACxD,CAAC;AAEF,MAAM,WAAW,QAAQ;IACrB,KAAK,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,YAAY,EAAE,CAAA;KAAE,CAAC,CAAC;IACzE,OAAO,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnD,aAAa,EAAE,KAAK,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,EAAE,YAAY,EAAE,CAAC;QACvB,KAAK,EAAE,YAAY,EAAE,CAAC;KACzB,CAAC,CAAC;IACH,SAAS,EAAE,MAAM,CAAC;CACrB;AAQD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI,CAQvE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,oBAAoB,GAAG,IAAI,CAM5E;AAED,wBAAgB,YAAY,CACxB,OAAO,EAAE,oBAAoB,EAC7B,MAAM,EAAE,oBAAoB,GAAG,IAAI,GACpC,OAAO,CAGT;AAMD,wBAAgB,WAAW,CACvB,OAAO,EAAE,oBAAoB,EAC7B,MAAM,EAAE,oBAAoB,GAAG,IAAI,GACpC,QAAQ,CA6CV;AAMD,wBAAgB,WAAW,CACvB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,oBAAoB,EAChC,IAAI,CAAC,EAAE,QAAQ,GAChB,IAAI,CASN;AAMD,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,YAAY,GAAG;IAC3D,UAAU,EAAE,oBAAoB,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;CACrB,CAYA;AAMD,eAAO,MAAM,cAAc,iBAAiB,CAAC;AAC7C,eAAO,MAAM,mBAAmB,QAAgB,CAAC;AAEjD,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASlE;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAO1D;AAUD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAQ9D;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,CAGlE"}
@@ -0,0 +1,143 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ // ---------------------------------------------------------------------------
4
+ // Sync cache (.cms-sync-cache.json)
5
+ // ---------------------------------------------------------------------------
6
+ const CACHE_FILE = '.cms-sync-cache.json';
7
+ export function loadSyncCache(root) {
8
+ const p = path.join(root, CACHE_FILE);
9
+ if (!fs.existsSync(p))
10
+ return null;
11
+ try {
12
+ return JSON.parse(fs.readFileSync(p, 'utf-8'));
13
+ }
14
+ catch {
15
+ return null;
16
+ }
17
+ }
18
+ export function saveSyncCache(root, data) {
19
+ fs.writeFileSync(path.join(root, CACHE_FILE), JSON.stringify(data, null, 2), 'utf-8');
20
+ }
21
+ export function isSyncNeeded(current, cached) {
22
+ if (!cached)
23
+ return true;
24
+ return JSON.stringify(current) !== JSON.stringify(cached);
25
+ }
26
+ // ---------------------------------------------------------------------------
27
+ // Diff
28
+ // ---------------------------------------------------------------------------
29
+ export function computeDiff(current, cached) {
30
+ const added = [];
31
+ const removed = [];
32
+ const routesChanged = [];
33
+ let unchanged = 0;
34
+ for (const [ns, keys] of Object.entries(current)) {
35
+ for (const { key, previewRoutes } of keys) {
36
+ const cachedEntry = cached?.[ns]?.find(k => k.key === key);
37
+ if (!cachedEntry) {
38
+ added.push({ namespace: ns, key, routes: previewRoutes });
39
+ }
40
+ else {
41
+ const before = [...cachedEntry.previewRoutes]
42
+ .map(routeToString)
43
+ .sort()
44
+ .join(',');
45
+ const after = [...previewRoutes]
46
+ .map(routeToString)
47
+ .sort()
48
+ .join(',');
49
+ if (before !== after) {
50
+ routesChanged.push({
51
+ namespace: ns,
52
+ key,
53
+ before: cachedEntry.previewRoutes,
54
+ after: previewRoutes,
55
+ });
56
+ }
57
+ else {
58
+ unchanged++;
59
+ }
60
+ }
61
+ }
62
+ }
63
+ if (cached) {
64
+ for (const [ns, keys] of Object.entries(cached)) {
65
+ for (const { key } of keys) {
66
+ if (!(current[ns] ?? []).some(k => k.key === key)) {
67
+ removed.push({ namespace: ns, key });
68
+ }
69
+ }
70
+ }
71
+ }
72
+ return { added, removed, routesChanged, unchanged };
73
+ }
74
+ // ---------------------------------------------------------------------------
75
+ // Report
76
+ // ---------------------------------------------------------------------------
77
+ export function writeReport(reportPath, namespaces, diff) {
78
+ const report = {
79
+ generatedAt: new Date().toISOString(),
80
+ namespaces,
81
+ };
82
+ if (diff)
83
+ report['diff'] = diff;
84
+ fs.writeFileSync(reportPath, JSON.stringify(report, null, 2), 'utf-8');
85
+ console.log(`[report] Written to ${reportPath}`);
86
+ }
87
+ // ---------------------------------------------------------------------------
88
+ // Serialization
89
+ // ---------------------------------------------------------------------------
90
+ export function serializeNamespaces(namespaces) {
91
+ const serialized = {};
92
+ let totalKeys = 0;
93
+ for (const [ns, keyMap] of Object.entries(namespaces)) {
94
+ serialized[ns] = [...keyMap.entries()]
95
+ .map(([key, previewRoutes]) => ({ key, previewRoutes }))
96
+ .sort((a, b) => a.key.localeCompare(b.key));
97
+ totalKeys += keyMap.size;
98
+ }
99
+ return { serialized, totalKeys };
100
+ }
101
+ // ---------------------------------------------------------------------------
102
+ // Pull cache (.last-pulled)
103
+ // ---------------------------------------------------------------------------
104
+ export const PULL_META_FILE = '.last-pulled';
105
+ export const DEFAULT_PULL_TTL_MS = 5 * 60 * 1000; // 5 minutes
106
+ export function getLastPulledTime(outputDir) {
107
+ const p = path.join(outputDir, PULL_META_FILE);
108
+ if (!fs.existsSync(p))
109
+ return null;
110
+ try {
111
+ const ts = new Date(fs.readFileSync(p, 'utf-8').trim()).getTime();
112
+ return isNaN(ts) ? null : ts;
113
+ }
114
+ catch {
115
+ return null;
116
+ }
117
+ }
118
+ export function saveLastPulledTime(outputDir) {
119
+ fs.mkdirSync(outputDir, { recursive: true });
120
+ fs.writeFileSync(path.join(outputDir, PULL_META_FILE), new Date().toISOString(), 'utf-8');
121
+ }
122
+ // ---------------------------------------------------------------------------
123
+ // Format helpers
124
+ // ---------------------------------------------------------------------------
125
+ function routeToString(r) {
126
+ return typeof r === 'string' ? r : JSON.stringify(r);
127
+ }
128
+ export function formatPreviewRoute(route) {
129
+ if (typeof route === 'string')
130
+ return route;
131
+ const params = route.params
132
+ ? ` (${Object.entries(route.params)
133
+ .map(([k, v]) => `${k}=${v}`)
134
+ .join(', ')})`
135
+ : '';
136
+ return `${route.route}${params}`;
137
+ }
138
+ export function formatPreviewRoutes(routes) {
139
+ if (routes.length === 0)
140
+ return 'no route';
141
+ return routes.map(formatPreviewRoute).join(', ');
142
+ }
143
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/core/cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * AST parsing and traversal utilities.
3
+ */
4
+ import type { AstNode } from './types.js';
5
+ /**
6
+ * Walk an AST tree depth-first, calling visit() for each node.
7
+ */
8
+ export declare function walk(node: unknown, visit: (node: AstNode) => void): void;
9
+ /**
10
+ * Parse source code using Babel with appropriate plugins based on file extension.
11
+ */
12
+ export declare function parseSource(filePath: string, source: string): unknown;
13
+ /**
14
+ * Returns the string value of a StringLiteral or no-expression TemplateLiteral node.
15
+ */
16
+ export declare function stringValue(node: unknown): string | null;
17
+ /**
18
+ * Extracts namespace string(s) from a useTranslation/getTranslation argument.
19
+ * Handles both single strings and arrays of strings.
20
+ */
21
+ export declare function namespacesFromArg(node: unknown): string[];
22
+ //# sourceMappingURL=ast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../../src/core/scanner-internals/ast.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C;;GAEG;AACH,wBAAgB,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAWxE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAUrE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAgBxD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,EAAE,CAWzD"}