@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,51 @@
1
+ /**
2
+ * YAML adapter — follows the Rails convention where the top-level key is the
3
+ * locale (`en:` → translations). On parse we descend into the locale root; on
4
+ * serialize we wrap the nested tree under the target locale. Nested keys
5
+ * flatten to dot notation, like the JSON adapter.
6
+ *
7
+ * (Plain locale-less YAML — e.g. some Vue-i18n setups — is best served by the
8
+ * JSON adapter; this adapter assumes the Rails/locale-rooted shape.)
9
+ */
10
+ import { parse as parseYaml, stringify as stringifyYaml } from 'yaml';
11
+ import { flattenObject, unflattenEntries } from './nested.js';
12
+ function isObject(v) {
13
+ return v !== null && typeof v === 'object' && !Array.isArray(v);
14
+ }
15
+ export class YamlAdapter {
16
+ format = 'yaml';
17
+ parse(content, options) {
18
+ let data;
19
+ try {
20
+ data = parseYaml(content);
21
+ }
22
+ catch (err) {
23
+ throw new Error(`Invalid YAML: ${err instanceof Error ? err.message : String(err)}`);
24
+ }
25
+ if (data === null || data === undefined)
26
+ return [];
27
+ if (!isObject(data))
28
+ throw new Error('Expected a YAML mapping of translation keys.');
29
+ // Descend into the locale root: prefer the requested locale, else a single
30
+ // top-level mapping key (the file's own locale), else treat the doc as-is.
31
+ let root = data;
32
+ if (options?.locale && isObject(data[options.locale])) {
33
+ root = data[options.locale];
34
+ }
35
+ else {
36
+ const keys = Object.keys(data);
37
+ if (keys.length === 1 && isObject(data[keys[0]])) {
38
+ root = data[keys[0]];
39
+ }
40
+ }
41
+ const out = [];
42
+ flattenObject(root, '', out);
43
+ return out;
44
+ }
45
+ serialize(entries, options) {
46
+ const nested = unflattenEntries(entries);
47
+ const doc = options?.locale ? { [options.locale]: nested } : nested;
48
+ return stringifyYaml(doc);
49
+ }
50
+ }
51
+ //# sourceMappingURL=yaml.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yaml.js","sourceRoot":"","sources":["../../src/adapters/yaml.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,MAAM,CAAC;AAEtE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE9D,SAAS,QAAQ,CAAC,CAAU;IAC1B,OAAO,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,OAAO,WAAW;IACb,MAAM,GAAG,MAAe,CAAC;IAElC,KAAK,CAAC,OAAe,EAAE,OAAsB;QAC3C,IAAI,IAAa,CAAC;QAClB,IAAI,CAAC;YACH,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;QAC5B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,iBAAiB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACvF,CAAC;QACD,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,EAAE,CAAC;QACnD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAErF,2EAA2E;QAC3E,2EAA2E;QAC3E,IAAI,IAAI,GAA4B,IAAI,CAAC;QACzC,IAAI,OAAO,EAAE,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;YACtD,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAA4B,CAAC;QACzD,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC,EAAE,CAAC;gBAClD,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAE,CAA4B,CAAC;YACnD,CAAC;QACH,CAAC;QAED,MAAM,GAAG,GAAuB,EAAE,CAAC;QACnC,aAAa,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;QAC7B,OAAO,GAAG,CAAC;IACb,CAAC;IAED,SAAS,CAAC,OAA2B,EAAE,OAA0B;QAC/D,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;QACzC,MAAM,GAAG,GAAG,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;QACpE,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;CACF"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Typed client for the LionRapid integrations REST surface
3
+ * (`/api/integrations/*`). Ported from `tests/e2e/fixtures/tm-server-client.ts`
4
+ * — the canonical, in-repo reference for these endpoints — and trimmed to the
5
+ * verbs the CLI needs.
6
+ *
7
+ * Every call carries a Bearer token (project API key, `sk_eng_...` shape) and
8
+ * uses native `fetch`. `fetch` is injectable so the client is unit-testable
9
+ * without a live server.
10
+ */
11
+ import type { ContentUnit } from '@lionrapid/core';
12
+ /** A translation keyed by its *bare* name (e.g. `welcome_title` or `auto_xxx`). */
13
+ export interface KeyedTranslation {
14
+ key: string;
15
+ value: ContentUnit;
16
+ }
17
+ /** Result of a namespace pull. `notModified` is true on a 304 (ETag hit). */
18
+ export interface NamespaceBundle {
19
+ translations: Record<string, ContentUnit>;
20
+ version?: string;
21
+ notModified: boolean;
22
+ /** True on a 423 — the namespace exists but nothing is approved for delivery yet. */
23
+ locked: boolean;
24
+ }
25
+ export type FetchImpl = (input: string, init?: RequestInit) => Promise<Response>;
26
+ export interface ApiClientOptions {
27
+ baseUrl: string;
28
+ apiKey: string;
29
+ /**
30
+ * Editor session token (`es_...`) used for workflow transitions like
31
+ * `mark-ready`, which the integration key is not authorized to perform.
32
+ */
33
+ editorToken?: string;
34
+ /** Injectable fetch (defaults to global fetch). */
35
+ fetchImpl?: FetchImpl;
36
+ /**
37
+ * Number of *retry* attempts for transient failures (network error, 5xx,
38
+ * 429). Total attempts = retries + 1. Default {@link DEFAULT_RETRIES}; 0
39
+ * disables retrying.
40
+ */
41
+ retries?: number;
42
+ /** Injectable delay (defaults to real `setTimeout`). Tests pass a no-op. */
43
+ sleep?: (ms: number) => Promise<void>;
44
+ }
45
+ /** Default number of retries for transient failures. */
46
+ export declare const DEFAULT_RETRIES = 3;
47
+ /**
48
+ * Parse a `Retry-After` header → ms, or null if absent/unparseable. Accepts the
49
+ * delta-seconds form (`120`) and the HTTP-date form; clamps to
50
+ * {@link MAX_RETRY_AFTER_MS}. `now` is injectable so the date form is testable.
51
+ */
52
+ export declare function parseRetryAfter(header: string | null, now: number): number | null;
53
+ /** Thrown when the server returns a non-2xx (and non-304) response. */
54
+ export declare class ApiError extends Error {
55
+ readonly status: number;
56
+ readonly body: string;
57
+ constructor(method: string, path: string, status: number, body: string);
58
+ /** True for 401/403 — surfaced as an auth hint in commands. */
59
+ get isAuth(): boolean;
60
+ /** True for 5xx — a server-side problem, retryable (see A2). */
61
+ get isServerError(): boolean;
62
+ }
63
+ /**
64
+ * Thrown when the request never reached the server — DNS/connection/TLS failure
65
+ * or an abort. Distinct from {@link ApiError} (which means the server answered
66
+ * with a non-2xx). Carries the original failure as `cause`.
67
+ */
68
+ export declare class NetworkError extends Error {
69
+ constructor(method: string, path: string, cause: unknown);
70
+ }
71
+ export declare class LionRapidApiClient {
72
+ private readonly baseUrl;
73
+ private readonly apiKey;
74
+ private readonly editorToken?;
75
+ private readonly fetchImpl;
76
+ private readonly retries;
77
+ private readonly sleep;
78
+ constructor(opts: ApiClientOptions);
79
+ /** True when this client holds an editor token and can publish (mark-ready). */
80
+ get canPublish(): boolean;
81
+ /** Credential smoke test. GET /api/integrations/editor/workflow. */
82
+ ping(): Promise<{
83
+ isPmAdmin: boolean;
84
+ }>;
85
+ /**
86
+ * Register source-row text for `sourceLocale`. Mirrors what the edge does on
87
+ * first visit when it encounters a missing key. POST /api/integrations/sync/batch.
88
+ */
89
+ syncBatch(sourceLocale: string, namespace: string, items: KeyedTranslation[]): Promise<void>;
90
+ /**
91
+ * Write target-locale translations as drafts (editor-visible, not public
92
+ * until mark-ready). PUT /api/integrations/targets/batch.
93
+ */
94
+ targetsBatch(targetLocale: string, namespace: string, items: KeyedTranslation[]): Promise<void>;
95
+ /**
96
+ * Publish a single target row. POST /api/integrations/targets/{key}/mark-ready.
97
+ * Requires an editor session token (the integration key is not authorized).
98
+ */
99
+ markReady(targetLocale: string, namespace: string, key: string): Promise<void>;
100
+ /**
101
+ * Pull all public (mark-ready) translations for a locale/namespace.
102
+ * GET /api/integrations/translations/{locale}/{namespace}. Sends a conditional
103
+ * `If-None-Match` when `etag` is provided and reports `notModified` on 304.
104
+ */
105
+ getNamespace(locale: string, namespace: string, opts?: {
106
+ etag?: string;
107
+ }): Promise<NamespaceBundle>;
108
+ private request;
109
+ /**
110
+ * Single choke-point for every HTTP call. Normalizes fetch *rejections*
111
+ * (DNS/connection/TLS/abort) into a typed {@link NetworkError}, and retries
112
+ * transient failures — network errors, 5xx, and 429 — with exponential
113
+ * backoff (honoring `Retry-After` on a 429). Non-transient responses (2xx,
114
+ * 3xx, and other 4xx like 401/404/423) return on the first attempt; the
115
+ * caller maps a non-2xx into an {@link ApiError}.
116
+ *
117
+ * Retrying writes (POST/PUT) is safe here: the integration endpoints upsert by
118
+ * composite key (`sync/batch`, `targets/batch`) or are idempotent
119
+ * (`mark-ready`), and the string `init.body` is re-sendable across attempts.
120
+ */
121
+ private doFetch;
122
+ }
123
+ //# sourceMappingURL=api-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,236 @@
1
+ /**
2
+ * Typed client for the LionRapid integrations REST surface
3
+ * (`/api/integrations/*`). Ported from `tests/e2e/fixtures/tm-server-client.ts`
4
+ * — the canonical, in-repo reference for these endpoints — and trimmed to the
5
+ * verbs the CLI needs.
6
+ *
7
+ * Every call carries a Bearer token (project API key, `sk_eng_...` shape) and
8
+ * uses native `fetch`. `fetch` is injectable so the client is unit-testable
9
+ * without a live server.
10
+ */
11
+ /** Default number of retries for transient failures. */
12
+ export const DEFAULT_RETRIES = 3;
13
+ /** Base backoff in ms; grows exponentially per attempt, capped at {@link MAX_BACKOFF_MS}. */
14
+ const BASE_BACKOFF_MS = 300;
15
+ const MAX_BACKOFF_MS = 10_000;
16
+ /** Cap on an honored `Retry-After` so a hostile/misconfigured header can't hang the CLI. */
17
+ const MAX_RETRY_AFTER_MS = 30_000;
18
+ /** Transient statuses worth retrying: rate-limit (429) and any 5xx. */
19
+ function isRetryableStatus(status) {
20
+ return status === 429 || status >= 500;
21
+ }
22
+ /** Exponential backoff with full jitter for attempt N (0-based). */
23
+ function backoffMs(attempt, random) {
24
+ const ceiling = Math.min(BASE_BACKOFF_MS * 2 ** attempt, MAX_BACKOFF_MS);
25
+ return Math.round(ceiling * random()); // full jitter: [0, ceiling)
26
+ }
27
+ /**
28
+ * Parse a `Retry-After` header → ms, or null if absent/unparseable. Accepts the
29
+ * delta-seconds form (`120`) and the HTTP-date form; clamps to
30
+ * {@link MAX_RETRY_AFTER_MS}. `now` is injectable so the date form is testable.
31
+ */
32
+ export function parseRetryAfter(header, now) {
33
+ if (!header)
34
+ return null;
35
+ const trimmed = header.trim();
36
+ if (/^\d+$/.test(trimmed)) {
37
+ return Math.min(Number(trimmed) * 1000, MAX_RETRY_AFTER_MS);
38
+ }
39
+ const when = Date.parse(trimmed);
40
+ if (Number.isNaN(when))
41
+ return null;
42
+ return Math.min(Math.max(0, when - now), MAX_RETRY_AFTER_MS);
43
+ }
44
+ /** Thrown when the server returns a non-2xx (and non-304) response. */
45
+ export class ApiError extends Error {
46
+ status;
47
+ body;
48
+ constructor(method, path, status, body) {
49
+ super(`tm-server ${method} ${path} → ${status}: ${body.slice(0, 400)}`);
50
+ this.name = 'ApiError';
51
+ this.status = status;
52
+ this.body = body;
53
+ }
54
+ /** True for 401/403 — surfaced as an auth hint in commands. */
55
+ get isAuth() {
56
+ return this.status === 401 || this.status === 403;
57
+ }
58
+ /** True for 5xx — a server-side problem, retryable (see A2). */
59
+ get isServerError() {
60
+ return this.status >= 500;
61
+ }
62
+ }
63
+ /**
64
+ * Thrown when the request never reached the server — DNS/connection/TLS failure
65
+ * or an abort. Distinct from {@link ApiError} (which means the server answered
66
+ * with a non-2xx). Carries the original failure as `cause`.
67
+ */
68
+ export class NetworkError extends Error {
69
+ constructor(method, path, cause) {
70
+ super(`tm-server ${method} ${path} → network error: ${cause instanceof Error ? cause.message : String(cause)}`, { cause });
71
+ this.name = 'NetworkError';
72
+ }
73
+ }
74
+ function compositeKey(locale, namespace, key) {
75
+ return `${locale}:${namespace}:${key}`;
76
+ }
77
+ export class LionRapidApiClient {
78
+ baseUrl;
79
+ apiKey;
80
+ editorToken;
81
+ fetchImpl;
82
+ retries;
83
+ sleep;
84
+ constructor(opts) {
85
+ this.baseUrl = opts.baseUrl.replace(/\/$/, '');
86
+ this.apiKey = opts.apiKey;
87
+ this.editorToken = opts.editorToken;
88
+ this.fetchImpl = opts.fetchImpl ?? ((input, init) => fetch(input, init));
89
+ this.retries = Math.max(0, opts.retries ?? DEFAULT_RETRIES);
90
+ this.sleep =
91
+ opts.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
92
+ }
93
+ /** True when this client holds an editor token and can publish (mark-ready). */
94
+ get canPublish() {
95
+ return typeof this.editorToken === 'string' && this.editorToken.length > 0;
96
+ }
97
+ /** Credential smoke test. GET /api/integrations/editor/workflow. */
98
+ async ping() {
99
+ const res = (await this.request('GET', '/api/integrations/editor/workflow'));
100
+ return { isPmAdmin: !!res?.is_pm_admin };
101
+ }
102
+ /**
103
+ * Register source-row text for `sourceLocale`. Mirrors what the edge does on
104
+ * first visit when it encounters a missing key. POST /api/integrations/sync/batch.
105
+ */
106
+ async syncBatch(sourceLocale, namespace, items) {
107
+ const translations = items.map((it) => ({
108
+ key: compositeKey(sourceLocale, namespace, it.key),
109
+ value: it.value,
110
+ }));
111
+ await this.request('POST', '/api/integrations/sync/batch', {
112
+ translations,
113
+ format: 'contentunit',
114
+ });
115
+ }
116
+ /**
117
+ * Write target-locale translations as drafts (editor-visible, not public
118
+ * until mark-ready). PUT /api/integrations/targets/batch.
119
+ */
120
+ async targetsBatch(targetLocale, namespace, items) {
121
+ const translations = items.map((it) => ({
122
+ key: compositeKey(targetLocale, namespace, it.key),
123
+ value: it.value,
124
+ }));
125
+ await this.request('PUT', '/api/integrations/targets/batch', {
126
+ translations,
127
+ format: 'contentunit',
128
+ });
129
+ }
130
+ /**
131
+ * Publish a single target row. POST /api/integrations/targets/{key}/mark-ready.
132
+ * Requires an editor session token (the integration key is not authorized).
133
+ */
134
+ async markReady(targetLocale, namespace, key) {
135
+ const composite = compositeKey(targetLocale, namespace, key);
136
+ await this.request('POST', `/api/integrations/targets/${encodeURIComponent(composite)}/mark-ready`, {}, this.editorToken ?? this.apiKey);
137
+ }
138
+ /**
139
+ * Pull all public (mark-ready) translations for a locale/namespace.
140
+ * GET /api/integrations/translations/{locale}/{namespace}. Sends a conditional
141
+ * `If-None-Match` when `etag` is provided and reports `notModified` on 304.
142
+ */
143
+ async getNamespace(locale, namespace, opts = {}) {
144
+ const path = `/api/integrations/translations/${encodeURIComponent(locale)}/${encodeURIComponent(namespace)}`;
145
+ const headers = {};
146
+ if (opts.etag)
147
+ headers['If-None-Match'] = `W/"${opts.etag}"`;
148
+ const res = await this.doFetch('GET', path, {
149
+ method: 'GET',
150
+ headers: { Authorization: `Bearer ${this.apiKey}`, ...headers },
151
+ });
152
+ if (res.status === 304) {
153
+ return { translations: {}, notModified: true, locked: false };
154
+ }
155
+ // 423 NAMESPACE_LOCKED — the namespace exists but nothing is approved for
156
+ // delivery yet. That's a normal "pending" state, not an error: report it as
157
+ // empty + locked so pull skips (without clobbering) and validate flags gaps.
158
+ if (res.status === 423) {
159
+ return { translations: {}, notModified: false, locked: true };
160
+ }
161
+ if (!res.ok) {
162
+ throw new ApiError('GET', path, res.status, await safeText(res));
163
+ }
164
+ const data = (await res.json());
165
+ return {
166
+ translations: data.translations ?? {},
167
+ version: data.meta?.version != null ? String(data.meta.version) : undefined,
168
+ notModified: false,
169
+ locked: false,
170
+ };
171
+ }
172
+ async request(method, path, body, token = this.apiKey) {
173
+ const res = await this.doFetch(method, path, {
174
+ method,
175
+ headers: {
176
+ 'Content-Type': 'application/json',
177
+ Authorization: `Bearer ${token}`,
178
+ },
179
+ body: body === undefined ? undefined : JSON.stringify(body),
180
+ });
181
+ if (!res.ok) {
182
+ throw new ApiError(method, path, res.status, await safeText(res));
183
+ }
184
+ if (res.status === 204)
185
+ return null;
186
+ const ctype = res.headers.get('content-type') ?? '';
187
+ if (!ctype.includes('application/json'))
188
+ return null;
189
+ return res.json();
190
+ }
191
+ /**
192
+ * Single choke-point for every HTTP call. Normalizes fetch *rejections*
193
+ * (DNS/connection/TLS/abort) into a typed {@link NetworkError}, and retries
194
+ * transient failures — network errors, 5xx, and 429 — with exponential
195
+ * backoff (honoring `Retry-After` on a 429). Non-transient responses (2xx,
196
+ * 3xx, and other 4xx like 401/404/423) return on the first attempt; the
197
+ * caller maps a non-2xx into an {@link ApiError}.
198
+ *
199
+ * Retrying writes (POST/PUT) is safe here: the integration endpoints upsert by
200
+ * composite key (`sync/batch`, `targets/batch`) or are idempotent
201
+ * (`mark-ready`), and the string `init.body` is re-sendable across attempts.
202
+ */
203
+ async doFetch(method, path, init) {
204
+ for (let attempt = 0;; attempt++) {
205
+ let res;
206
+ let netErr;
207
+ try {
208
+ res = await this.fetchImpl(`${this.baseUrl}${path}`, init);
209
+ }
210
+ catch (err) {
211
+ netErr = new NetworkError(method, path, err);
212
+ }
213
+ // A non-transient response is the answer — let the caller interpret it.
214
+ if (res && !isRetryableStatus(res.status))
215
+ return res;
216
+ // Exhausted retries: surface the last response (→ ApiError) or rethrow.
217
+ if (attempt >= this.retries) {
218
+ if (res)
219
+ return res;
220
+ throw netErr;
221
+ }
222
+ const retryAfter = res?.status === 429 ? parseRetryAfter(res.headers.get('retry-after'), Date.now()) : null;
223
+ const delay = retryAfter ?? backoffMs(attempt, Math.random);
224
+ await this.sleep(delay);
225
+ }
226
+ }
227
+ }
228
+ async function safeText(res) {
229
+ try {
230
+ return await res.text();
231
+ }
232
+ catch {
233
+ return '';
234
+ }
235
+ }
236
+ //# sourceMappingURL=api-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @lionrapid/cli — sync translation files (iOS, Android, Flutter, JSON, YAML,
4
+ * PO) with the LionRapid backend.
5
+ *
6
+ * This file wires up the command surface. Each command's behaviour lives in
7
+ * `src/commands/*`; commands not yet implemented print a clear "not implemented
8
+ * yet" notice and exit non-zero so scripts never silently succeed.
9
+ */
10
+ import { Command } from 'commander';
11
+ /**
12
+ * Read the package version at runtime from package.json. We deliberately do
13
+ * NOT hardcode the version (the previous `@lionrapid/types` CLI did, and it
14
+ * drifted) — `../package.json` resolves correctly both from `dist/cli.js` and
15
+ * from `src/cli.ts` under vitest, since both sit one level below the package
16
+ * root.
17
+ */
18
+ export declare function readVersion(): string;
19
+ /**
20
+ * Build the commander program. Exported (rather than parsed inline) so tests
21
+ * can construct and inspect the program without executing it.
22
+ */
23
+ export declare function buildProgram(): Command;
24
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkBpC;;;;;;GAMG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAMpC;AAyBD;;;GAGG;AACH,wBAAgB,YAAY,IAAI,OAAO,CA0TtC"}