@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.
- package/README.md +159 -0
- package/dist/adapters/android-xml.d.ts +20 -0
- package/dist/adapters/android-xml.d.ts.map +1 -0
- package/dist/adapters/android-xml.js +101 -0
- package/dist/adapters/android-xml.js.map +1 -0
- package/dist/adapters/arb.d.ts +17 -0
- package/dist/adapters/arb.d.ts.map +1 -0
- package/dist/adapters/arb.js +45 -0
- package/dist/adapters/arb.js.map +1 -0
- package/dist/adapters/content.d.ts +13 -0
- package/dist/adapters/content.d.ts.map +1 -0
- package/dist/adapters/content.js +24 -0
- package/dist/adapters/content.js.map +1 -0
- package/dist/adapters/index.d.ts +11 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +34 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/ios-strings.d.ts +15 -0
- package/dist/adapters/ios-strings.d.ts.map +1 -0
- package/dist/adapters/ios-strings.js +54 -0
- package/dist/adapters/ios-strings.js.map +1 -0
- package/dist/adapters/json.d.ts +12 -0
- package/dist/adapters/json.d.ts.map +1 -0
- package/dist/adapters/json.js +31 -0
- package/dist/adapters/json.js.map +1 -0
- package/dist/adapters/nested.d.ts +9 -0
- package/dist/adapters/nested.d.ts.map +1 -0
- package/dist/adapters/nested.js +37 -0
- package/dist/adapters/nested.js.map +1 -0
- package/dist/adapters/po.d.ts +23 -0
- package/dist/adapters/po.d.ts.map +1 -0
- package/dist/adapters/po.js +197 -0
- package/dist/adapters/po.js.map +1 -0
- package/dist/adapters/types.d.ts +46 -0
- package/dist/adapters/types.d.ts.map +1 -0
- package/dist/adapters/types.js +16 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/adapters/xcstrings.d.ts +20 -0
- package/dist/adapters/xcstrings.d.ts.map +1 -0
- package/dist/adapters/xcstrings.js +77 -0
- package/dist/adapters/xcstrings.js.map +1 -0
- package/dist/adapters/xliff.d.ts +22 -0
- package/dist/adapters/xliff.d.ts.map +1 -0
- package/dist/adapters/xliff.js +83 -0
- package/dist/adapters/xliff.js.map +1 -0
- package/dist/adapters/yaml.d.ts +16 -0
- package/dist/adapters/yaml.d.ts.map +1 -0
- package/dist/adapters/yaml.js +51 -0
- package/dist/adapters/yaml.js.map +1 -0
- package/dist/api-client.d.ts +123 -0
- package/dist/api-client.d.ts.map +1 -0
- package/dist/api-client.js +236 -0
- package/dist/api-client.js.map +1 -0
- package/dist/cli.d.ts +24 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +365 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/context.d.ts +38 -0
- package/dist/commands/context.d.ts.map +1 -0
- package/dist/commands/context.js +70 -0
- package/dist/commands/context.js.map +1 -0
- package/dist/commands/doctor.d.ts +27 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +87 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/init.d.ts +36 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +111 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/pull.d.ts +35 -0
- package/dist/commands/pull.d.ts.map +1 -0
- package/dist/commands/pull.js +123 -0
- package/dist/commands/pull.js.map +1 -0
- package/dist/commands/push.d.ts +37 -0
- package/dist/commands/push.d.ts.map +1 -0
- package/dist/commands/push.js +63 -0
- package/dist/commands/push.js.map +1 -0
- package/dist/commands/scan.d.ts +46 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +68 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/snapshot.d.ts +48 -0
- package/dist/commands/snapshot.d.ts.map +1 -0
- package/dist/commands/snapshot.js +52 -0
- package/dist/commands/snapshot.js.map +1 -0
- package/dist/commands/types.d.ts +38 -0
- package/dist/commands/types.d.ts.map +1 -0
- package/dist/commands/types.js +82 -0
- package/dist/commands/types.js.map +1 -0
- package/dist/commands/validate.d.ts +28 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +48 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/config.d.ts +80 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +279 -0
- package/dist/config.js.map +1 -0
- package/dist/exit-codes.d.ts +26 -0
- package/dist/exit-codes.d.ts.map +1 -0
- package/dist/exit-codes.js +42 -0
- package/dist/exit-codes.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/output.d.ts +29 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +38 -0
- package/dist/output.js.map +1 -0
- package/dist/scan/canonical.d.ts +33 -0
- package/dist/scan/canonical.d.ts.map +1 -0
- package/dist/scan/canonical.js +57 -0
- package/dist/scan/canonical.js.map +1 -0
- package/dist/scan/discover.d.ts +13 -0
- package/dist/scan/discover.d.ts.map +1 -0
- package/dist/scan/discover.js +95 -0
- package/dist/scan/discover.js.map +1 -0
- package/dist/scan/scanner.d.ts +32 -0
- package/dist/scan/scanner.d.ts.map +1 -0
- package/dist/scan/scanner.js +137 -0
- package/dist/scan/scanner.js.map +1 -0
- package/dist/types-gen/extract.d.ts +22 -0
- package/dist/types-gen/extract.d.ts.map +1 -0
- package/dist/types-gen/extract.js +148 -0
- package/dist/types-gen/extract.js.map +1 -0
- package/dist/types-gen/generate.d.ts +10 -0
- package/dist/types-gen/generate.d.ts.map +1 -0
- package/dist/types-gen/generate.js +39 -0
- package/dist/types-gen/generate.js.map +1 -0
- 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":"AAAA;;;;;;;;;GASG;AA4CH,wDAAwD;AACxD,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC;AAEjC,6FAA6F;AAC7F,MAAM,eAAe,GAAG,GAAG,CAAC;AAC5B,MAAM,cAAc,GAAG,MAAM,CAAC;AAC9B,4FAA4F;AAC5F,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAElC,uEAAuE;AACvE,SAAS,iBAAiB,CAAC,MAAc;IACvC,OAAO,MAAM,KAAK,GAAG,IAAI,MAAM,IAAI,GAAG,CAAC;AACzC,CAAC;AAED,oEAAoE;AACpE,SAAS,SAAS,CAAC,OAAe,EAAE,MAAoB;IACtD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,GAAG,CAAC,IAAI,OAAO,EAAE,cAAc,CAAC,CAAC;IACzE,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC,4BAA4B;AACrE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,MAAqB,EAAE,GAAW;IAChE,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,EAAE,kBAAkB,CAAC,CAAC;IAC9D,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACjC,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,GAAG,CAAC,EAAE,kBAAkB,CAAC,CAAC;AAC/D,CAAC;AAED,uEAAuE;AACvE,MAAM,OAAO,QAAS,SAAQ,KAAK;IACxB,MAAM,CAAS;IACf,IAAI,CAAS;IAEtB,YAAY,MAAc,EAAE,IAAY,EAAE,MAAc,EAAE,IAAY;QACpE,KAAK,CAAC,aAAa,MAAM,IAAI,IAAI,MAAM,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QACxE,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,+DAA+D;IAC/D,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,MAAM,KAAK,GAAG,CAAC;IACpD,CAAC;IAED,gEAAgE;IAChE,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC;IAC5B,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,YAAa,SAAQ,KAAK;IACrC,YAAY,MAAc,EAAE,IAAY,EAAE,KAAc;QACtD,KAAK,CACH,aAAa,MAAM,IAAI,IAAI,qBACzB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACvD,EAAE,EACF,EAAE,KAAK,EAAE,CACV,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AAED,SAAS,YAAY,CAAC,MAAc,EAAE,SAAiB,EAAE,GAAW;IAClE,OAAO,GAAG,MAAM,IAAI,SAAS,IAAI,GAAG,EAAE,CAAC;AACzC,CAAC;AAED,MAAM,OAAO,kBAAkB;IACZ,OAAO,CAAS;IAChB,MAAM,CAAS;IACf,WAAW,CAAU;IACrB,SAAS,CAAY;IACrB,OAAO,CAAS;IAChB,KAAK,CAAgC;IAEtD,YAAY,IAAsB;QAChC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC/C,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;QACpC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;QACzE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,IAAI,eAAe,CAAC,CAAC;QAC5D,IAAI,CAAC,KAAK;YACR,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IACpF,CAAC;IAED,gFAAgF;IAChF,IAAI,UAAU;QACZ,OAAO,OAAO,IAAI,CAAC,WAAW,KAAK,QAAQ,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;IAC7E,CAAC;IAED,oEAAoE;IACpE,KAAK,CAAC,IAAI;QACR,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,mCAAmC,CAAC,CAEnE,CAAC;QACT,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,GAAG,EAAE,WAAW,EAAE,CAAC;IAC3C,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,SAAS,CACb,YAAoB,EACpB,SAAiB,EACjB,KAAyB;QAEzB,MAAM,YAAY,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACtC,GAAG,EAAE,YAAY,CAAC,YAAY,EAAE,SAAS,EAAE,EAAE,CAAC,GAAG,CAAC;YAClD,KAAK,EAAE,EAAE,CAAC,KAAK;SAChB,CAAC,CAAC,CAAC;QACJ,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,8BAA8B,EAAE;YACzD,YAAY;YACZ,MAAM,EAAE,aAAa;SACtB,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,YAAY,CAChB,YAAoB,EACpB,SAAiB,EACjB,KAAyB;QAEzB,MAAM,YAAY,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACtC,GAAG,EAAE,YAAY,CAAC,YAAY,EAAE,SAAS,EAAE,EAAE,CAAC,GAAG,CAAC;YAClD,KAAK,EAAE,EAAE,CAAC,KAAK;SAChB,CAAC,CAAC,CAAC;QACJ,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,iCAAiC,EAAE;YAC3D,YAAY;YACZ,MAAM,EAAE,aAAa;SACtB,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,SAAS,CAAC,YAAoB,EAAE,SAAiB,EAAE,GAAW;QAClE,MAAM,SAAS,GAAG,YAAY,CAAC,YAAY,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;QAC7D,MAAM,IAAI,CAAC,OAAO,CAChB,MAAM,EACN,6BAA6B,kBAAkB,CAAC,SAAS,CAAC,aAAa,EACvE,EAAE,EACF,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,MAAM,CAChC,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,YAAY,CAChB,MAAc,EACd,SAAiB,EACjB,OAA0B,EAAE;QAE5B,MAAM,IAAI,GAAG,kCAAkC,kBAAkB,CAC/D,MAAM,CACP,IAAI,kBAAkB,CAAC,SAAS,CAAC,EAAE,CAAC;QACrC,MAAM,OAAO,GAA2B,EAAE,CAAC;QAC3C,IAAI,IAAI,CAAC,IAAI;YAAE,OAAO,CAAC,eAAe,CAAC,GAAG,MAAM,IAAI,CAAC,IAAI,GAAG,CAAC;QAE7D,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE;YAC1C,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE,EAAE,GAAG,OAAO,EAAE;SAChE,CAAC,CAAC;QAEH,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,OAAO,EAAE,YAAY,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QAChE,CAAC;QACD,0EAA0E;QAC1E,4EAA4E;QAC5E,6EAA6E;QAC7E,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,OAAO,EAAE,YAAY,EAAE,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAChE,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;QACnE,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAG7B,CAAC;QACF,OAAO;YACL,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,EAAE;YACrC,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS;YAC3E,WAAW,EAAE,KAAK;YAClB,MAAM,EAAE,KAAK;SACd,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,OAAO,CACnB,MAA8B,EAC9B,IAAY,EACZ,IAAc,EACd,QAAgB,IAAI,CAAC,MAAM;QAE3B,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE;YAC3C,MAAM;YACN,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,KAAK,EAAE;aACjC;YACD,IAAI,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC5D,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;QACpE,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QACpC,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;QACpD,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,kBAAkB,CAAC;YAAE,OAAO,IAAI,CAAC;QACrD,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;IACpB,CAAC;IAED;;;;;;;;;;;OAWG;IACK,KAAK,CAAC,OAAO,CACnB,MAAc,EACd,IAAY,EACZ,IAAiB;QAEjB,KAAK,IAAI,OAAO,GAAG,CAAC,GAAI,OAAO,EAAE,EAAE,CAAC;YAClC,IAAI,GAAyB,CAAC;YAC9B,IAAI,MAAgC,CAAC;YACrC,IAAI,CAAC;gBACH,GAAG,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;YAC7D,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,GAAG,IAAI,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;YAC/C,CAAC;YAED,wEAAwE;YACxE,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC;gBAAE,OAAO,GAAG,CAAC;YAEtD,wEAAwE;YACxE,IAAI,OAAO,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBAC5B,IAAI,GAAG;oBAAE,OAAO,GAAG,CAAC;gBACpB,MAAM,MAAsB,CAAC;YAC/B,CAAC;YAED,MAAM,UAAU,GACd,GAAG,EAAE,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC3F,MAAM,KAAK,GAAG,UAAU,IAAI,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YAC5D,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;CACF;AAED,KAAK,UAAU,QAAQ,CAAC,GAAa;IACnC,IAAI,CAAC;QACH,OAAO,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
|
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"}
|