@lionrapid/cli 0.1.0

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 (130) hide show
  1. package/README.md +159 -0
  2. package/dist/adapters/android-xml.d.ts +20 -0
  3. package/dist/adapters/android-xml.d.ts.map +1 -0
  4. package/dist/adapters/android-xml.js +101 -0
  5. package/dist/adapters/android-xml.js.map +1 -0
  6. package/dist/adapters/arb.d.ts +17 -0
  7. package/dist/adapters/arb.d.ts.map +1 -0
  8. package/dist/adapters/arb.js +45 -0
  9. package/dist/adapters/arb.js.map +1 -0
  10. package/dist/adapters/content.d.ts +13 -0
  11. package/dist/adapters/content.d.ts.map +1 -0
  12. package/dist/adapters/content.js +24 -0
  13. package/dist/adapters/content.js.map +1 -0
  14. package/dist/adapters/index.d.ts +11 -0
  15. package/dist/adapters/index.d.ts.map +1 -0
  16. package/dist/adapters/index.js +34 -0
  17. package/dist/adapters/index.js.map +1 -0
  18. package/dist/adapters/ios-strings.d.ts +15 -0
  19. package/dist/adapters/ios-strings.d.ts.map +1 -0
  20. package/dist/adapters/ios-strings.js +54 -0
  21. package/dist/adapters/ios-strings.js.map +1 -0
  22. package/dist/adapters/json.d.ts +12 -0
  23. package/dist/adapters/json.d.ts.map +1 -0
  24. package/dist/adapters/json.js +31 -0
  25. package/dist/adapters/json.js.map +1 -0
  26. package/dist/adapters/nested.d.ts +9 -0
  27. package/dist/adapters/nested.d.ts.map +1 -0
  28. package/dist/adapters/nested.js +37 -0
  29. package/dist/adapters/nested.js.map +1 -0
  30. package/dist/adapters/po.d.ts +23 -0
  31. package/dist/adapters/po.d.ts.map +1 -0
  32. package/dist/adapters/po.js +197 -0
  33. package/dist/adapters/po.js.map +1 -0
  34. package/dist/adapters/types.d.ts +46 -0
  35. package/dist/adapters/types.d.ts.map +1 -0
  36. package/dist/adapters/types.js +16 -0
  37. package/dist/adapters/types.js.map +1 -0
  38. package/dist/adapters/xcstrings.d.ts +20 -0
  39. package/dist/adapters/xcstrings.d.ts.map +1 -0
  40. package/dist/adapters/xcstrings.js +77 -0
  41. package/dist/adapters/xcstrings.js.map +1 -0
  42. package/dist/adapters/xliff.d.ts +22 -0
  43. package/dist/adapters/xliff.d.ts.map +1 -0
  44. package/dist/adapters/xliff.js +83 -0
  45. package/dist/adapters/xliff.js.map +1 -0
  46. package/dist/adapters/yaml.d.ts +16 -0
  47. package/dist/adapters/yaml.d.ts.map +1 -0
  48. package/dist/adapters/yaml.js +51 -0
  49. package/dist/adapters/yaml.js.map +1 -0
  50. package/dist/api-client.d.ts +123 -0
  51. package/dist/api-client.d.ts.map +1 -0
  52. package/dist/api-client.js +236 -0
  53. package/dist/api-client.js.map +1 -0
  54. package/dist/cli.d.ts +24 -0
  55. package/dist/cli.d.ts.map +1 -0
  56. package/dist/cli.js +365 -0
  57. package/dist/cli.js.map +1 -0
  58. package/dist/commands/context.d.ts +38 -0
  59. package/dist/commands/context.d.ts.map +1 -0
  60. package/dist/commands/context.js +70 -0
  61. package/dist/commands/context.js.map +1 -0
  62. package/dist/commands/doctor.d.ts +27 -0
  63. package/dist/commands/doctor.d.ts.map +1 -0
  64. package/dist/commands/doctor.js +87 -0
  65. package/dist/commands/doctor.js.map +1 -0
  66. package/dist/commands/init.d.ts +36 -0
  67. package/dist/commands/init.d.ts.map +1 -0
  68. package/dist/commands/init.js +111 -0
  69. package/dist/commands/init.js.map +1 -0
  70. package/dist/commands/pull.d.ts +35 -0
  71. package/dist/commands/pull.d.ts.map +1 -0
  72. package/dist/commands/pull.js +123 -0
  73. package/dist/commands/pull.js.map +1 -0
  74. package/dist/commands/push.d.ts +37 -0
  75. package/dist/commands/push.d.ts.map +1 -0
  76. package/dist/commands/push.js +63 -0
  77. package/dist/commands/push.js.map +1 -0
  78. package/dist/commands/scan.d.ts +46 -0
  79. package/dist/commands/scan.d.ts.map +1 -0
  80. package/dist/commands/scan.js +68 -0
  81. package/dist/commands/scan.js.map +1 -0
  82. package/dist/commands/snapshot.d.ts +48 -0
  83. package/dist/commands/snapshot.d.ts.map +1 -0
  84. package/dist/commands/snapshot.js +52 -0
  85. package/dist/commands/snapshot.js.map +1 -0
  86. package/dist/commands/types.d.ts +38 -0
  87. package/dist/commands/types.d.ts.map +1 -0
  88. package/dist/commands/types.js +82 -0
  89. package/dist/commands/types.js.map +1 -0
  90. package/dist/commands/validate.d.ts +28 -0
  91. package/dist/commands/validate.d.ts.map +1 -0
  92. package/dist/commands/validate.js +48 -0
  93. package/dist/commands/validate.js.map +1 -0
  94. package/dist/config.d.ts +80 -0
  95. package/dist/config.d.ts.map +1 -0
  96. package/dist/config.js +279 -0
  97. package/dist/config.js.map +1 -0
  98. package/dist/exit-codes.d.ts +26 -0
  99. package/dist/exit-codes.d.ts.map +1 -0
  100. package/dist/exit-codes.js +42 -0
  101. package/dist/exit-codes.js.map +1 -0
  102. package/dist/index.d.ts +8 -0
  103. package/dist/index.d.ts.map +1 -0
  104. package/dist/index.js +8 -0
  105. package/dist/index.js.map +1 -0
  106. package/dist/output.d.ts +29 -0
  107. package/dist/output.d.ts.map +1 -0
  108. package/dist/output.js +38 -0
  109. package/dist/output.js.map +1 -0
  110. package/dist/scan/canonical.d.ts +33 -0
  111. package/dist/scan/canonical.d.ts.map +1 -0
  112. package/dist/scan/canonical.js +57 -0
  113. package/dist/scan/canonical.js.map +1 -0
  114. package/dist/scan/discover.d.ts +13 -0
  115. package/dist/scan/discover.d.ts.map +1 -0
  116. package/dist/scan/discover.js +95 -0
  117. package/dist/scan/discover.js.map +1 -0
  118. package/dist/scan/scanner.d.ts +32 -0
  119. package/dist/scan/scanner.d.ts.map +1 -0
  120. package/dist/scan/scanner.js +137 -0
  121. package/dist/scan/scanner.js.map +1 -0
  122. package/dist/types-gen/extract.d.ts +22 -0
  123. package/dist/types-gen/extract.d.ts.map +1 -0
  124. package/dist/types-gen/extract.js +148 -0
  125. package/dist/types-gen/extract.js.map +1 -0
  126. package/dist/types-gen/generate.d.ts +10 -0
  127. package/dist/types-gen/generate.d.ts.map +1 -0
  128. package/dist/types-gen/generate.js +39 -0
  129. package/dist/types-gen/generate.js.map +1 -0
  130. package/package.json +71 -0
@@ -0,0 +1,36 @@
1
+ /**
2
+ * `init` — scaffold a `lionrapid.yml` by detecting the project's stack.
3
+ *
4
+ * Detection is best-effort and additive: a repo with both an Android and an iOS
5
+ * project gets file entries for both. The config is emitted with the `yaml`
6
+ * serializer so paths that need quoting (e.g. a target starting with
7
+ * `{locale}`) are quoted correctly. The logic is pure/testable; the commander
8
+ * action only supplies overrides and prints next steps.
9
+ */
10
+ import type { FileFormat } from '../config.js';
11
+ interface DetectedFile {
12
+ format: FileFormat;
13
+ source: string;
14
+ target: string;
15
+ }
16
+ export interface DetectResult {
17
+ stacks: string[];
18
+ files: DetectedFile[];
19
+ }
20
+ /** Inspect the project for known i18n stacks and propose file mappings. */
21
+ export declare function detectProject(cwd: string): DetectResult;
22
+ export interface InitAnswers {
23
+ project?: string;
24
+ server?: string;
25
+ sourceLocale?: string;
26
+ targetLocales?: string[];
27
+ force?: boolean;
28
+ }
29
+ export interface InitResult {
30
+ configPath: string;
31
+ yaml: string;
32
+ detected: DetectResult;
33
+ }
34
+ export declare function runInit(cwd: string, answers?: InitAnswers): InitResult;
35
+ export {};
36
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG/C,UAAU,YAAY;IACpB,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AA4BD,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAuDvD;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,YAAY,CAAC;CACxB;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,UAAU,CAmB1E"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * `init` — scaffold a `lionrapid.yml` by detecting the project's stack.
3
+ *
4
+ * Detection is best-effort and additive: a repo with both an Android and an iOS
5
+ * project gets file entries for both. The config is emitted with the `yaml`
6
+ * serializer so paths that need quoting (e.g. a target starting with
7
+ * `{locale}`) are quoted correctly. The logic is pure/testable; the commander
8
+ * action only supplies overrides and prints next steps.
9
+ */
10
+ import { existsSync, readdirSync, writeFileSync } from 'node:fs';
11
+ import { join } from 'node:path';
12
+ import { stringify as stringifyYaml } from 'yaml';
13
+ import { ConfigError } from '../config.js';
14
+ function hasAny(cwd, names) {
15
+ return names.some((n) => existsSync(join(cwd, n)));
16
+ }
17
+ /** Shallow search (bounded depth) for a file matching `test`. */
18
+ function findShallow(cwd, test, maxDepth = 3) {
19
+ const skip = new Set(['node_modules', '.git', 'build', 'dist', 'Pods', '.dart_tool']);
20
+ const walk = (dir, depth) => {
21
+ let entries;
22
+ try {
23
+ entries = readdirSync(dir, { withFileTypes: true });
24
+ }
25
+ catch {
26
+ return false;
27
+ }
28
+ for (const e of entries) {
29
+ // Match files (e.g. *.xcstrings) and directories (e.g. *.xcodeproj).
30
+ if (test(e.name))
31
+ return true;
32
+ if (e.isDirectory() && depth < maxDepth && !skip.has(e.name)) {
33
+ if (walk(join(dir, e.name), depth + 1))
34
+ return true;
35
+ }
36
+ }
37
+ return false;
38
+ };
39
+ return walk(cwd, 0);
40
+ }
41
+ /** Inspect the project for known i18n stacks and propose file mappings. */
42
+ export function detectProject(cwd) {
43
+ const stacks = [];
44
+ const files = [];
45
+ if (existsSync(join(cwd, 'pubspec.yaml'))) {
46
+ stacks.push('Flutter');
47
+ files.push({
48
+ format: 'arb',
49
+ source: 'lib/l10n/app_en.arb',
50
+ target: 'lib/l10n/app_{locale}.arb',
51
+ });
52
+ }
53
+ if (hasAny(cwd, ['build.gradle', 'build.gradle.kts', 'settings.gradle', 'app/build.gradle'])) {
54
+ stacks.push('Android');
55
+ files.push({
56
+ format: 'android-xml',
57
+ source: 'app/src/main/res/values/strings.xml',
58
+ target: 'app/src/main/res/values-{locale}/strings.xml',
59
+ });
60
+ }
61
+ if (findShallow(cwd, (n) => n.endsWith('.xcodeproj') || n.endsWith('.xcstrings'), 2)) {
62
+ stacks.push('iOS');
63
+ if (findShallow(cwd, (n) => n.endsWith('.xcstrings'), 3)) {
64
+ files.push({
65
+ format: 'xcstrings',
66
+ source: 'Localizable.xcstrings',
67
+ target: 'Localizable.xcstrings',
68
+ });
69
+ }
70
+ else {
71
+ files.push({
72
+ format: 'ios-strings',
73
+ source: 'en.lproj/Localizable.strings',
74
+ target: '{locale}.lproj/Localizable.strings',
75
+ });
76
+ }
77
+ }
78
+ if (existsSync(join(cwd, 'config', 'locales'))) {
79
+ stacks.push('Rails');
80
+ files.push({
81
+ format: 'yaml',
82
+ source: 'config/locales/en.yml',
83
+ target: 'config/locales/{locale}.yml',
84
+ });
85
+ }
86
+ if (files.length === 0) {
87
+ // Default to JSON (covers React Native, node, Vue, generic).
88
+ stacks.push(existsSync(join(cwd, 'package.json')) ? 'JavaScript' : 'generic');
89
+ files.push({ format: 'json', source: 'locales/en.json', target: 'locales/{locale}.json' });
90
+ }
91
+ return { stacks, files };
92
+ }
93
+ export function runInit(cwd, answers = {}) {
94
+ const configPath = join(cwd, 'lionrapid.yml');
95
+ if (existsSync(configPath) && !answers.force) {
96
+ throw new ConfigError(`lionrapid.yml already exists at ${configPath} (use --force to overwrite).`);
97
+ }
98
+ const detected = detectProject(cwd);
99
+ const config = {
100
+ project: answers.project ?? 'YOUR_PROJECT_ID',
101
+ server: answers.server ?? 'https://api.lionrapid.com',
102
+ sourceLocale: answers.sourceLocale ?? 'en',
103
+ targetLocales: answers.targetLocales ?? ['es', 'fr'],
104
+ namespace: 'app',
105
+ files: detected.files,
106
+ };
107
+ const yaml = stringifyYaml(config);
108
+ writeFileSync(configPath, yaml);
109
+ return { configPath, yaml, detected };
110
+ }
111
+ //# 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,35 @@
1
+ /**
2
+ * `pull` — download published translations and write them into target files.
3
+ *
4
+ * Per-locale formats write one file per locale. Multi-locale catalog formats
5
+ * (e.g. .xcstrings) read a base catalog (existing target, else the source) and
6
+ * have every target locale merged into it, written once. Only `mark-ready`
7
+ * rows are returned by the public endpoint; we report how many source keys are
8
+ * still pending per locale.
9
+ */
10
+ import type { LionRapidConfig } from '../config.js';
11
+ import type { LionRapidApiClient } from '../api-client.js';
12
+ export interface PullOptions {
13
+ cwd: string;
14
+ /** Fetch + count what would be written, but write no files. */
15
+ dryRun?: boolean;
16
+ /** Progress callback, invoked as each namespace fetch completes. */
17
+ onProgress?: (done: number, total: number) => void;
18
+ }
19
+ export interface PullFileResult {
20
+ target: string;
21
+ count: number;
22
+ }
23
+ export interface PullLocaleResult {
24
+ locale: string;
25
+ files: PullFileResult[];
26
+ /** Source keys present but not yet translated/published for this locale. */
27
+ pending: number;
28
+ }
29
+ export interface PullResult {
30
+ locales: PullLocaleResult[];
31
+ /** True when this was a dry run — no files were written. */
32
+ dryRun?: boolean;
33
+ }
34
+ export declare function runPull(config: LionRapidConfig, client: LionRapidApiClient, opts: PullOptions): Promise<PullResult>;
35
+ //# sourceMappingURL=pull.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAa,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAI3D,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,+DAA+D;IAC/D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,oEAAoE;IACpE,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpD;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,4DAA4D;IAC5D,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAkBD,wBAAsB,OAAO,CAC3B,MAAM,EAAE,eAAe,EACvB,MAAM,EAAE,kBAAkB,EAC1B,IAAI,EAAE,WAAW,GAChB,OAAO,CAAC,UAAU,CAAC,CA+GrB"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * `pull` — download published translations and write them into target files.
3
+ *
4
+ * Per-locale formats write one file per locale. Multi-locale catalog formats
5
+ * (e.g. .xcstrings) read a base catalog (existing target, else the source) and
6
+ * have every target locale merged into it, written once. Only `mark-ready`
7
+ * rows are returned by the public endpoint; we report how many source keys are
8
+ * still pending per locale.
9
+ */
10
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
11
+ import { dirname, resolve } from 'node:path';
12
+ import { getAdapter } from '../adapters/index.js';
13
+ import { mapLimit, resolveConcurrency } from './context.js';
14
+ /** Union of source keys per namespace, for "pending" reporting. */
15
+ function sourceKeysByNamespace(config, cwd) {
16
+ const byNs = new Map();
17
+ for (const file of config.files) {
18
+ const ns = file.namespace ?? config.namespace;
19
+ const abs = resolve(cwd, file.source);
20
+ if (!existsSync(abs))
21
+ continue;
22
+ const set = byNs.get(ns) ?? new Set();
23
+ for (const entry of getAdapter(file.format).parse(readFileSync(abs, 'utf8'))) {
24
+ set.add(entry.key);
25
+ }
26
+ byNs.set(ns, set);
27
+ }
28
+ return byNs;
29
+ }
30
+ export async function runPull(config, client, opts) {
31
+ const sourceKeys = sourceKeysByNamespace(config, opts.cwd);
32
+ const perLocaleFiles = config.files.filter((f) => !getAdapter(f.format).multiLocale);
33
+ const multiFiles = config.files.filter((f) => getAdapter(f.format).multiLocale);
34
+ // Run-wide namespace cache, keyed `${locale}:${namespace}`.
35
+ const nsCache = new Map();
36
+ const fetchNs = async (locale, namespace) => {
37
+ const cacheKey = `${locale}:${namespace}`;
38
+ const hit = nsCache.get(cacheKey);
39
+ if (hit)
40
+ return hit;
41
+ const bundle = await client.getNamespace(locale, namespace);
42
+ nsCache.set(cacheKey, bundle.translations);
43
+ return bundle.translations;
44
+ };
45
+ // Pre-fetch every needed (locale, namespace) bundle concurrently so the slow
46
+ // network fan-out runs in parallel; the write loops below then read the warm
47
+ // cache. Output stays deterministic — only the fetch is parallelized.
48
+ const allNamespaces = new Set();
49
+ for (const file of config.files)
50
+ allNamespaces.add(file.namespace ?? config.namespace);
51
+ const pairs = config.targetLocales.flatMap((locale) => [...allNamespaces].map((namespace) => ({ locale, namespace })));
52
+ let fetched = 0;
53
+ await mapLimit(pairs, resolveConcurrency(), async ({ locale, namespace }) => {
54
+ await fetchNs(locale, namespace);
55
+ opts.onProgress?.(++fetched, pairs.length);
56
+ });
57
+ const toEntries = (translations) => Object.entries(translations).map(([key, value]) => ({ key, value }));
58
+ // Base content for each multi-locale catalog: prefer existing target, else source.
59
+ const catalogContent = new Map();
60
+ for (const file of multiFiles) {
61
+ const targetAbs = resolve(opts.cwd, file.target);
62
+ const sourceAbs = resolve(opts.cwd, file.source);
63
+ const base = existsSync(targetAbs)
64
+ ? readFileSync(targetAbs, 'utf8')
65
+ : existsSync(sourceAbs)
66
+ ? readFileSync(sourceAbs, 'utf8')
67
+ : null;
68
+ catalogContent.set(file, base);
69
+ }
70
+ const locales = [];
71
+ for (const locale of config.targetLocales) {
72
+ const fileResults = [];
73
+ const usedNamespaces = new Set();
74
+ for (const file of perLocaleFiles) {
75
+ const adapter = getAdapter(file.format);
76
+ const namespace = file.namespace ?? config.namespace;
77
+ usedNamespaces.add(namespace);
78
+ const entries = toEntries(await fetchNs(locale, namespace));
79
+ const relPath = file.target.replace('{locale}', locale);
80
+ // Don't clobber an existing target with an empty result (locked/pending).
81
+ // Dry run computes counts but writes nothing.
82
+ if (entries.length > 0 && !opts.dryRun) {
83
+ const absPath = resolve(opts.cwd, relPath);
84
+ mkdirSync(dirname(absPath), { recursive: true });
85
+ writeFileSync(absPath, adapter.serialize(entries, { locale, sourceLocale: config.sourceLocale }));
86
+ }
87
+ fileResults.push({ target: relPath, count: entries.length });
88
+ }
89
+ for (const file of multiFiles) {
90
+ const adapter = getAdapter(file.format);
91
+ const namespace = file.namespace ?? config.namespace;
92
+ usedNamespaces.add(namespace);
93
+ const entries = toEntries(await fetchNs(locale, namespace));
94
+ if (entries.length > 0) {
95
+ const merged = adapter.mergeLocale(catalogContent.get(file) ?? null, entries, locale);
96
+ catalogContent.set(file, merged);
97
+ }
98
+ fileResults.push({ target: file.target, count: entries.length });
99
+ }
100
+ let pending = 0;
101
+ for (const namespace of usedNamespaces) {
102
+ const have = new Set(Object.keys(nsCache.get(`${locale}:${namespace}`) ?? {}));
103
+ for (const key of sourceKeys.get(namespace) ?? new Set()) {
104
+ if (!have.has(key))
105
+ pending += 1;
106
+ }
107
+ }
108
+ locales.push({ locale, files: fileResults, pending });
109
+ }
110
+ // Write each accumulated multi-locale catalog once (skipped on a dry run).
111
+ if (!opts.dryRun) {
112
+ for (const file of multiFiles) {
113
+ const content = catalogContent.get(file);
114
+ if (content != null) {
115
+ const absPath = resolve(opts.cwd, file.target);
116
+ mkdirSync(dirname(absPath), { recursive: true });
117
+ writeFileSync(absPath, content);
118
+ }
119
+ }
120
+ }
121
+ return { locales, ...(opts.dryRun ? { dryRun: true } : {}) };
122
+ }
123
+ //# sourceMappingURL=pull.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull.js","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * `push` — upload local strings to the backend.
3
+ *
4
+ * Default (source) mode reads each entry's `source` file and registers source
5
+ * rows via `sync/batch`; the server then queues machine translation for the
6
+ * configured target locales.
7
+ *
8
+ * `--target <locale>` mode uploads an already-translated target file as drafts
9
+ * via `targets/batch`, optionally publishing them with `--publish`.
10
+ */
11
+ import type { LionRapidConfig } from '../config.js';
12
+ import type { LionRapidApiClient } from '../api-client.js';
13
+ export interface PushOptions {
14
+ cwd: string;
15
+ /** Push an already-translated target locale instead of the source. */
16
+ target?: string;
17
+ /** In target mode, mark every pushed row ready (public) after writing. */
18
+ publish?: boolean;
19
+ /** Parse + count what would be pushed, but make no network calls. */
20
+ dryRun?: boolean;
21
+ }
22
+ export interface PushFileResult {
23
+ file: string;
24
+ count: number;
25
+ skipped?: boolean;
26
+ }
27
+ export interface PushResult {
28
+ mode: 'source' | 'target';
29
+ pushed: number;
30
+ files: PushFileResult[];
31
+ /** True when `--publish` was requested but no editor token was available. */
32
+ publishSkipped?: boolean;
33
+ /** True when this was a dry run — nothing was sent to the server. */
34
+ dryRun?: boolean;
35
+ }
36
+ export declare function runPush(config: LionRapidConfig, client: LionRapidApiClient, opts: PushOptions): Promise<PushResult>;
37
+ //# sourceMappingURL=push.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../src/commands/push.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EAAE,kBAAkB,EAAoB,MAAM,kBAAkB,CAAC;AAM7E,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,sEAAsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,qEAAqE;IACrE,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,6EAA6E;IAC7E,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,qEAAqE;IACrE,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,OAAO,CAC3B,MAAM,EAAE,eAAe,EACvB,MAAM,EAAE,kBAAkB,EAC1B,IAAI,EAAE,WAAW,GAChB,OAAO,CAAC,UAAU,CAAC,CAoDrB"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * `push` — upload local strings to the backend.
3
+ *
4
+ * Default (source) mode reads each entry's `source` file and registers source
5
+ * rows via `sync/batch`; the server then queues machine translation for the
6
+ * configured target locales.
7
+ *
8
+ * `--target <locale>` mode uploads an already-translated target file as drafts
9
+ * via `targets/batch`, optionally publishing them with `--publish`.
10
+ */
11
+ import { existsSync, readFileSync } from 'node:fs';
12
+ import { resolve } from 'node:path';
13
+ import { getAdapter } from '../adapters/index.js';
14
+ import { chunk } from './context.js';
15
+ const BATCH = 500;
16
+ export async function runPush(config, client, opts) {
17
+ const mode = opts.target ? 'target' : 'source';
18
+ const files = [];
19
+ // Publishing (mark-ready) needs an editor token; if asked to publish without
20
+ // one, we still upload the drafts and report that publishing was skipped.
21
+ const canPublish = mode === 'target' && opts.publish === true && client.canPublish;
22
+ const publishSkipped = mode === 'target' && opts.publish === true && !client.canPublish;
23
+ let pushed = 0;
24
+ for (const file of config.files) {
25
+ const adapter = getAdapter(file.format);
26
+ const namespace = file.namespace ?? config.namespace;
27
+ const relPath = mode === 'source' ? file.source : file.target.replace('{locale}', opts.target);
28
+ const absPath = resolve(opts.cwd, relPath);
29
+ if (!existsSync(absPath)) {
30
+ files.push({ file: relPath, count: 0, skipped: true });
31
+ continue;
32
+ }
33
+ const parseLocale = mode === 'source' ? config.sourceLocale : opts.target;
34
+ const entries = adapter.parse(readFileSync(absPath, 'utf8'), { locale: parseLocale });
35
+ const items = entries.map((e) => ({ key: e.key, value: e.value }));
36
+ // Dry run: parse + count only, never touch the network.
37
+ if (!opts.dryRun) {
38
+ for (const batch of chunk(items, BATCH)) {
39
+ if (mode === 'source') {
40
+ await client.syncBatch(config.sourceLocale, namespace, batch);
41
+ }
42
+ else {
43
+ await client.targetsBatch(opts.target, namespace, batch);
44
+ if (canPublish) {
45
+ for (const it of batch) {
46
+ await client.markReady(opts.target, namespace, it.key);
47
+ }
48
+ }
49
+ }
50
+ }
51
+ }
52
+ pushed += items.length;
53
+ files.push({ file: relPath, count: items.length });
54
+ }
55
+ return {
56
+ mode,
57
+ pushed,
58
+ files,
59
+ ...(publishSkipped ? { publishSkipped: true } : {}),
60
+ ...(opts.dryRun ? { dryRun: true } : {}),
61
+ };
62
+ }
63
+ //# sourceMappingURL=push.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push.js","sourceRoot":"","sources":["../../src/commands/push.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * `scan` — discover candidate user-facing strings in source and produce an
3
+ * inventory keyed by content-hash auto_key. Offline; the deterministic half of
4
+ * the no-library localization flow. The judgment-heavy `review` candidates are
5
+ * handed to a human/agent; the safe `wrap` candidates can be auto-wrapped (N5)
6
+ * and seeded/pushed (N6).
7
+ */
8
+ import type { LionRapidConfig } from '../config.js';
9
+ import type { LionRapidApiClient } from '../api-client.js';
10
+ import { type Candidate } from '../scan/scanner.js';
11
+ export declare const DEFAULT_SCAN_INCLUDE: string[];
12
+ export declare const DEFAULT_SCAN_EXCLUDE: string[];
13
+ export interface ScanOptions {
14
+ cwd: string;
15
+ include?: string[];
16
+ exclude?: string[];
17
+ }
18
+ export interface ScanSummary {
19
+ files: number;
20
+ candidates: number;
21
+ wrap: number;
22
+ review: number;
23
+ uniqueKeys: number;
24
+ }
25
+ export interface ScanResult {
26
+ /** Namespace the discovered keys belong to (for the agent/human to wrap with). */
27
+ namespace: string;
28
+ summary: ScanSummary;
29
+ candidates: Candidate[];
30
+ }
31
+ export declare function runScan(config: LionRapidConfig, opts: ScanOptions): Promise<ScanResult>;
32
+ export interface SeedResult {
33
+ pushed: number;
34
+ }
35
+ /**
36
+ * Push the scan's `wrap` candidates to the backend as source rows keyed by their
37
+ * content-hash auto_key (composite `{sourceLocale}:{namespace}:auto_xxx`) — the
38
+ * same key the web/edge stack produces — so the backend can dedup them against
39
+ * the web TM. Only deterministic `wrap` candidates are seeded; `review`
40
+ * candidates are left for a human/agent.
41
+ */
42
+ export declare function seedFromScan(result: ScanResult, client: LionRapidApiClient, opts: {
43
+ sourceLocale: string;
44
+ namespace: string;
45
+ }): Promise<SeedResult>;
46
+ //# sourceMappingURL=scan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EAAoB,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE7E,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEhE,eAAO,MAAM,oBAAoB,UAA+B,CAAC;AACjE,eAAO,MAAM,oBAAoB,UAKhC,CAAC;AAEF,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,kFAAkF;IAClF,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,WAAW,CAAC;IACrB,UAAU,EAAE,SAAS,EAAE,CAAC;CACzB;AAED,wBAAsB,OAAO,CAC3B,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,WAAW,GAChB,OAAO,CAAC,UAAU,CAAC,CA8BrB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,kBAAkB,EAC1B,IAAI,EAAE;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAChD,OAAO,CAAC,UAAU,CAAC,CAerB"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * `scan` — discover candidate user-facing strings in source and produce an
3
+ * inventory keyed by content-hash auto_key. Offline; the deterministic half of
4
+ * the no-library localization flow. The judgment-heavy `review` candidates are
5
+ * handed to a human/agent; the safe `wrap` candidates can be auto-wrapped (N5)
6
+ * and seeded/pushed (N6).
7
+ */
8
+ import { readFileSync } from 'node:fs';
9
+ import { resolve } from 'node:path';
10
+ import { discoverFiles } from '../scan/discover.js';
11
+ import { scanSource } from '../scan/scanner.js';
12
+ export const DEFAULT_SCAN_INCLUDE = ['src/**/*.{ts,tsx,js,jsx}'];
13
+ export const DEFAULT_SCAN_EXCLUDE = [
14
+ '**/*.test.*',
15
+ '**/*.spec.*',
16
+ '**/*.d.ts',
17
+ '**/*.stories.*',
18
+ ];
19
+ export async function runScan(config, opts) {
20
+ const include = opts.include ??
21
+ (config.scan?.include.length ? config.scan.include : DEFAULT_SCAN_INCLUDE);
22
+ const exclude = opts.exclude ??
23
+ (config.scan?.exclude.length ? config.scan.exclude : DEFAULT_SCAN_EXCLUDE);
24
+ const files = discoverFiles(opts.cwd, { include, exclude });
25
+ const candidates = [];
26
+ for (const rel of files) {
27
+ const code = readFileSync(resolve(opts.cwd, rel), 'utf8');
28
+ candidates.push(...(await scanSource(code, rel)));
29
+ }
30
+ const wrap = candidates.filter((c) => c.action === 'wrap');
31
+ const review = candidates.filter((c) => c.action === 'review');
32
+ const uniqueKeys = new Set(wrap.map((c) => c.autoKey)).size;
33
+ return {
34
+ namespace: config.namespace,
35
+ summary: {
36
+ files: files.length,
37
+ candidates: candidates.length,
38
+ wrap: wrap.length,
39
+ review: review.length,
40
+ uniqueKeys,
41
+ },
42
+ candidates,
43
+ };
44
+ }
45
+ /**
46
+ * Push the scan's `wrap` candidates to the backend as source rows keyed by their
47
+ * content-hash auto_key (composite `{sourceLocale}:{namespace}:auto_xxx`) — the
48
+ * same key the web/edge stack produces — so the backend can dedup them against
49
+ * the web TM. Only deterministic `wrap` candidates are seeded; `review`
50
+ * candidates are left for a human/agent.
51
+ */
52
+ export async function seedFromScan(result, client, opts) {
53
+ const byKey = new Map();
54
+ for (const c of result.candidates) {
55
+ if (c.action === 'wrap' && c.autoKey && !byKey.has(c.autoKey)) {
56
+ byKey.set(c.autoKey, { text: c.text, styles: {} });
57
+ }
58
+ }
59
+ const items = [...byKey.entries()].map(([key, value]) => ({
60
+ key,
61
+ value,
62
+ }));
63
+ if (items.length > 0) {
64
+ await client.syncBatch(opts.sourceLocale, opts.namespace, items);
65
+ }
66
+ return { pushed: items.length };
67
+ }
68
+ //# sourceMappingURL=scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * `snapshot` — produce offline-resilience snapshot files: the RAW
3
+ * `bundle.translations` (`Record<key, ContentUnit>`) the backend returns,
4
+ * written verbatim per (locale, namespace).
5
+ *
6
+ * CRITICAL: this deliberately BYPASSES the format adapters. The pull/format
7
+ * adapters flatten ContentUnit to plain display strings (dropping the `styles`
8
+ * map) — fine for human-edited translation files, fatal for runtime seeding,
9
+ * because the runtime needs the full ContentUnit (text + styles) to render
10
+ * inline markup (`<1>…</1>`). The snapshot is byte-shaped exactly like
11
+ * `GET /api/integrations/translations/{locale}/{namespace}`, so it drops
12
+ * straight into `MemoryRepository.setNamespace` / `StaticRepository` on every
13
+ * surface with no re-derivation.
14
+ */
15
+ import type { ContentUnit } from '@lionrapid/core';
16
+ import type { LionRapidConfig } from '../config.js';
17
+ import type { LionRapidApiClient } from '../api-client.js';
18
+ export declare const DEFAULT_SNAPSHOT_DIR = "snapshots";
19
+ export interface SnapshotOptions {
20
+ cwd: string;
21
+ out?: string;
22
+ /** Stamp written into meta (caller supplies; omitted from golden comparisons). */
23
+ generatedAt?: string;
24
+ }
25
+ export interface SnapshotFileResult {
26
+ path: string;
27
+ locale: string;
28
+ namespace: string;
29
+ keys: number;
30
+ }
31
+ export interface SnapshotResult {
32
+ files: SnapshotFileResult[];
33
+ skipped: Array<{
34
+ locale: string;
35
+ namespace: string;
36
+ }>;
37
+ }
38
+ export interface SnapshotFile {
39
+ meta: {
40
+ locale: string;
41
+ namespace: string;
42
+ version?: string;
43
+ generatedAt?: string;
44
+ };
45
+ translations: Record<string, ContentUnit>;
46
+ }
47
+ export declare function runSnapshot(config: LionRapidConfig, client: LionRapidApiClient, opts: SnapshotOptions): Promise<SnapshotResult>;
48
+ //# sourceMappingURL=snapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../../src/commands/snapshot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE3D,eAAO,MAAM,oBAAoB,cAAc,CAAC;AAEhD,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kFAAkF;IAClF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,OAAO,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACvD;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpF,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CAC3C;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,eAAe,EACvB,MAAM,EAAE,kBAAkB,EAC1B,IAAI,EAAE,eAAe,GACpB,OAAO,CAAC,cAAc,CAAC,CAmCzB"}