experimental-ciao-core 1.0.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 +63 -0
- package/dist/index.cjs +352 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +161 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +161 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +316 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +61 -0
package/README.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# @ciao-tools/core
|
|
2
|
+
|
|
3
|
+
Core utilities for Ciao Tools - API client, config loading, and string extraction.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @ciao-tools/core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
This package is typically used internally by `@ciao-tools/cli`. You don't need to install it directly unless building custom tooling.
|
|
12
|
+
|
|
13
|
+
## Exports
|
|
14
|
+
|
|
15
|
+
### Configuration
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { loadConfig, defineCiaoConfig, DEFAULT_CONFIG } from "@ciao-tools/core";
|
|
19
|
+
|
|
20
|
+
const config = await loadConfig();
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### API Client
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { CiaoApiClient } from "@ciao-tools/core";
|
|
27
|
+
|
|
28
|
+
const client = new CiaoApiClient({
|
|
29
|
+
apiKey: process.env.CIAO_API_KEY,
|
|
30
|
+
});
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### String Extraction
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import { extractStringsFromProject } from "@ciao-tools/core";
|
|
37
|
+
|
|
38
|
+
const result = await extractStringsFromProject({
|
|
39
|
+
include: ["src/**/*.tsx"],
|
|
40
|
+
exclude: ["node_modules"],
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Manifest Generation
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
import { generateManifestFile } from "@ciao-tools/core";
|
|
48
|
+
|
|
49
|
+
await generateManifestFile({
|
|
50
|
+
outputPath: "./public/ciao-manifest.json",
|
|
51
|
+
projectId: "your-project-id",
|
|
52
|
+
languages: ["en", "es", "fr"],
|
|
53
|
+
cdnUrls: { ... },
|
|
54
|
+
});
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Documentation
|
|
58
|
+
|
|
59
|
+
See [docs.ciao-tools.com/api/core](https://docs.ciao-tools.com/api/core) for full documentation.
|
|
60
|
+
|
|
61
|
+
## License
|
|
62
|
+
|
|
63
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
//#region rolldown:runtime
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
+
key = keys[i];
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except) {
|
|
13
|
+
__defProp(to, key, {
|
|
14
|
+
get: ((k) => from[k]).bind(null, key),
|
|
15
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return to;
|
|
21
|
+
};
|
|
22
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
23
|
+
value: mod,
|
|
24
|
+
enumerable: true
|
|
25
|
+
}) : target, mod));
|
|
26
|
+
|
|
27
|
+
//#endregion
|
|
28
|
+
let node_fs = require("node:fs");
|
|
29
|
+
node_fs = __toESM(node_fs);
|
|
30
|
+
let node_path = require("node:path");
|
|
31
|
+
node_path = __toESM(node_path);
|
|
32
|
+
let __babel_core = require("@babel/core");
|
|
33
|
+
__babel_core = __toESM(__babel_core);
|
|
34
|
+
let experimental_ciao_core = require("experimental-ciao-core");
|
|
35
|
+
let glob = require("glob");
|
|
36
|
+
|
|
37
|
+
//#region src/api/client.ts
|
|
38
|
+
var CiaoApiClient = class {
|
|
39
|
+
baseUrl;
|
|
40
|
+
apiKey;
|
|
41
|
+
timeout;
|
|
42
|
+
constructor(options) {
|
|
43
|
+
this.baseUrl = options.baseUrl.replace(/\/$/, "");
|
|
44
|
+
this.apiKey = options.apiKey;
|
|
45
|
+
this.timeout = options.timeout ?? 3e4;
|
|
46
|
+
}
|
|
47
|
+
async request(method, path, body) {
|
|
48
|
+
const url = `${this.baseUrl}${path}`;
|
|
49
|
+
const controller = new AbortController();
|
|
50
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
51
|
+
try {
|
|
52
|
+
const response = await fetch(url, {
|
|
53
|
+
method,
|
|
54
|
+
headers: {
|
|
55
|
+
"Content-Type": "application/json",
|
|
56
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
57
|
+
},
|
|
58
|
+
body: body ? JSON.stringify(body) : void 0,
|
|
59
|
+
signal: controller.signal
|
|
60
|
+
});
|
|
61
|
+
clearTimeout(timeoutId);
|
|
62
|
+
if (!response.ok) {
|
|
63
|
+
let errorData;
|
|
64
|
+
try {
|
|
65
|
+
errorData = await response.json();
|
|
66
|
+
} catch {
|
|
67
|
+
errorData = {
|
|
68
|
+
code: `HTTP_${response.status}`,
|
|
69
|
+
message: response.statusText
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
throw new CiaoApiError(errorData.message, errorData.code, response.status, errorData.details);
|
|
73
|
+
}
|
|
74
|
+
return response.json();
|
|
75
|
+
} catch (error) {
|
|
76
|
+
clearTimeout(timeoutId);
|
|
77
|
+
if (error instanceof CiaoApiError) throw error;
|
|
78
|
+
if (error instanceof Error) {
|
|
79
|
+
if (error.name === "AbortError") throw new CiaoApiError("Request timed out", "TIMEOUT", 0);
|
|
80
|
+
throw new CiaoApiError(error.message, "NETWORK_ERROR", 0);
|
|
81
|
+
}
|
|
82
|
+
throw new CiaoApiError("Unknown error", "UNKNOWN", 0);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async submitBuildSchema(buildSchema) {
|
|
86
|
+
return this.request("POST", "/api/translation/translate-strings", { buildSchema });
|
|
87
|
+
}
|
|
88
|
+
async getJobStatus(jobId) {
|
|
89
|
+
return this.request("GET", `/api/translation/job/${jobId}`);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
var CiaoApiError = class extends Error {
|
|
93
|
+
constructor(message, code, statusCode, details) {
|
|
94
|
+
super(message);
|
|
95
|
+
this.code = code;
|
|
96
|
+
this.statusCode = statusCode;
|
|
97
|
+
this.details = details;
|
|
98
|
+
this.name = "CiaoApiError";
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
//#endregion
|
|
103
|
+
//#region src/api/polling.ts
|
|
104
|
+
const DEFAULT_OPTIONS = {
|
|
105
|
+
initialInterval: 1e3,
|
|
106
|
+
maxInterval: 1e4,
|
|
107
|
+
maxAttempts: 120,
|
|
108
|
+
backoffMultiplier: 1.5
|
|
109
|
+
};
|
|
110
|
+
async function pollJobUntilComplete(client, jobId, options = {}) {
|
|
111
|
+
const { initialInterval, maxInterval, maxAttempts, backoffMultiplier } = {
|
|
112
|
+
...DEFAULT_OPTIONS,
|
|
113
|
+
...options
|
|
114
|
+
};
|
|
115
|
+
const { onProgress } = options;
|
|
116
|
+
let currentInterval = initialInterval;
|
|
117
|
+
let attempts = 0;
|
|
118
|
+
while (attempts < maxAttempts) {
|
|
119
|
+
const status = await client.getJobStatus(jobId);
|
|
120
|
+
if (onProgress) onProgress(status);
|
|
121
|
+
if (status.status === "completed") return status;
|
|
122
|
+
if (status.status === "failed") throw new Error(status.error ?? "Job failed with unknown error");
|
|
123
|
+
await sleep(currentInterval);
|
|
124
|
+
currentInterval = Math.min(currentInterval * backoffMultiplier, maxInterval);
|
|
125
|
+
attempts++;
|
|
126
|
+
}
|
|
127
|
+
throw new Error(`Job polling timed out after ${maxAttempts} attempts`);
|
|
128
|
+
}
|
|
129
|
+
function sleep(ms) {
|
|
130
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
//#endregion
|
|
134
|
+
//#region src/config/defaults.ts
|
|
135
|
+
const DEFAULT_CONFIG = {
|
|
136
|
+
include: [
|
|
137
|
+
"src/**/*.{ts,tsx,js,jsx}",
|
|
138
|
+
"app/**/*.{ts,tsx,js,jsx}",
|
|
139
|
+
"pages/**/*.{ts,tsx,js,jsx}",
|
|
140
|
+
"components/**/*.{ts,tsx,js,jsx}"
|
|
141
|
+
],
|
|
142
|
+
exclude: [
|
|
143
|
+
"**/node_modules/**",
|
|
144
|
+
"**/*.test.{ts,tsx,js,jsx}",
|
|
145
|
+
"**/*.spec.{ts,tsx,js,jsx}",
|
|
146
|
+
"**/__tests__/**",
|
|
147
|
+
"**/dist/**",
|
|
148
|
+
"**/.next/**"
|
|
149
|
+
],
|
|
150
|
+
outputDir: "__generated__",
|
|
151
|
+
serverUrl: "https://server.ciao-tools.com"
|
|
152
|
+
};
|
|
153
|
+
const CONFIG_FILE_NAMES = [
|
|
154
|
+
"ciao.config.ts",
|
|
155
|
+
"ciao.config.js",
|
|
156
|
+
"ciao.config.mjs"
|
|
157
|
+
];
|
|
158
|
+
|
|
159
|
+
//#endregion
|
|
160
|
+
//#region src/config/loader.ts
|
|
161
|
+
async function loadConfig(options = {}) {
|
|
162
|
+
const cwd = options.cwd ?? process.cwd();
|
|
163
|
+
let configPath = options.configPath;
|
|
164
|
+
if (!configPath) for (const fileName of CONFIG_FILE_NAMES) {
|
|
165
|
+
const candidate = node_path.join(cwd, fileName);
|
|
166
|
+
if (node_fs.existsSync(candidate)) {
|
|
167
|
+
configPath = candidate;
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (!configPath) throw new ConfigNotFoundError(`No ciao.config.ts found. Run 'ciao init' to create one.`);
|
|
172
|
+
const absolutePath = node_path.isAbsolute(configPath) ? configPath : node_path.join(cwd, configPath);
|
|
173
|
+
if (!node_fs.existsSync(absolutePath)) throw new ConfigNotFoundError(`Config file not found: ${absolutePath}`);
|
|
174
|
+
return resolveConfig(await importConfig(absolutePath), cwd);
|
|
175
|
+
}
|
|
176
|
+
async function importConfig(configPath) {
|
|
177
|
+
try {
|
|
178
|
+
const module$1 = await (configPath.startsWith("file://") ? import(configPath) : import(`file://${configPath}`));
|
|
179
|
+
const config = module$1.default ?? module$1;
|
|
180
|
+
if (!config || typeof config !== "object") throw new ConfigValidationError("Config file must export an object");
|
|
181
|
+
return config;
|
|
182
|
+
} catch (error) {
|
|
183
|
+
if (error instanceof ConfigValidationError) throw error;
|
|
184
|
+
if (error instanceof Error) throw new ConfigValidationError(`Failed to load config file (${configPath}): ${error.message}`);
|
|
185
|
+
throw new ConfigValidationError(`Failed to load config file: ${configPath}`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function resolveConfig(config, cwd) {
|
|
189
|
+
if (!config.projectId) throw new ConfigValidationError("projectId is required in ciao.config.ts");
|
|
190
|
+
const outputDir = config.outputDir ?? DEFAULT_CONFIG.outputDir;
|
|
191
|
+
const resolvedOutputDir = node_path.isAbsolute(outputDir) ? outputDir : node_path.join(cwd, outputDir);
|
|
192
|
+
return {
|
|
193
|
+
projectId: config.projectId,
|
|
194
|
+
styleId: config.styleId,
|
|
195
|
+
include: config.include ?? DEFAULT_CONFIG.include,
|
|
196
|
+
exclude: config.exclude ?? DEFAULT_CONFIG.exclude,
|
|
197
|
+
outputDir: resolvedOutputDir,
|
|
198
|
+
serverUrl: config.serverUrl ?? DEFAULT_CONFIG.serverUrl
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
var ConfigNotFoundError = class extends Error {
|
|
202
|
+
constructor(message) {
|
|
203
|
+
super(message);
|
|
204
|
+
this.name = "ConfigNotFoundError";
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
var ConfigValidationError = class extends Error {
|
|
208
|
+
constructor(message) {
|
|
209
|
+
super(message);
|
|
210
|
+
this.name = "ConfigValidationError";
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
//#endregion
|
|
215
|
+
//#region src/config/types.ts
|
|
216
|
+
function defineCiaoConfig(config) {
|
|
217
|
+
return config;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
//#endregion
|
|
221
|
+
//#region src/manifest/generator.ts
|
|
222
|
+
async function generateManifestFile(options) {
|
|
223
|
+
const { outputDir, data } = options;
|
|
224
|
+
if (!node_fs.existsSync(outputDir)) node_fs.mkdirSync(outputDir, { recursive: true });
|
|
225
|
+
const manifestPath = node_path.join(outputDir, "ciao-manifest.ts");
|
|
226
|
+
const content = generateManifestContent(data);
|
|
227
|
+
node_fs.writeFileSync(manifestPath, content, "utf-8");
|
|
228
|
+
return manifestPath;
|
|
229
|
+
}
|
|
230
|
+
function generateManifestContent(data) {
|
|
231
|
+
const cdnUrlsEntries = Object.entries(data.cdnUrls).map(([lang, url]) => `\t"${lang}": "${url}"`).join(",\n");
|
|
232
|
+
const languagesArray = data.languages.map((l) => `"${l}"`).join(", ");
|
|
233
|
+
return `// This file is auto-generated by ciao-tools. Do not edit manually.
|
|
234
|
+
// Generated at: ${data.generatedAt}
|
|
235
|
+
|
|
236
|
+
export const ciaoManifest = {
|
|
237
|
+
version: "${data.version}",
|
|
238
|
+
projectId: "${data.projectId}",
|
|
239
|
+
sourceLanguage: "${data.sourceLanguage}",
|
|
240
|
+
languages: [${languagesArray}] as const,
|
|
241
|
+
cdnUrls: {
|
|
242
|
+
${cdnUrlsEntries}
|
|
243
|
+
} as const,
|
|
244
|
+
generatedAt: "${data.generatedAt}",
|
|
245
|
+
} as const;
|
|
246
|
+
|
|
247
|
+
export type CiaoLanguage = (typeof ciaoManifest.languages)[number];
|
|
248
|
+
|
|
249
|
+
export type CiaoManifest = typeof ciaoManifest;
|
|
250
|
+
`;
|
|
251
|
+
}
|
|
252
|
+
function createManifestData(projectId, sourceLanguage, languages, cdnUrls, version) {
|
|
253
|
+
return {
|
|
254
|
+
version,
|
|
255
|
+
projectId,
|
|
256
|
+
sourceLanguage,
|
|
257
|
+
languages,
|
|
258
|
+
cdnUrls,
|
|
259
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
//#endregion
|
|
264
|
+
//#region src/extraction/runner.ts
|
|
265
|
+
async function extractStringsFromProject(options) {
|
|
266
|
+
const cwd = options.cwd ?? process.cwd();
|
|
267
|
+
const allStrings = [];
|
|
268
|
+
const allContextBlocks = [];
|
|
269
|
+
let filesProcessed = 0;
|
|
270
|
+
const files = await (0, glob.glob)(options.include, {
|
|
271
|
+
cwd,
|
|
272
|
+
ignore: options.exclude,
|
|
273
|
+
absolute: true,
|
|
274
|
+
nodir: true
|
|
275
|
+
});
|
|
276
|
+
for (const filePath of files) {
|
|
277
|
+
const result = await extractStringsFromFile(filePath);
|
|
278
|
+
if (result) {
|
|
279
|
+
mergeStrings(allStrings, result.strings);
|
|
280
|
+
mergeContextBlocks(allContextBlocks, result.contextBlocks);
|
|
281
|
+
filesProcessed++;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return {
|
|
285
|
+
strings: allStrings,
|
|
286
|
+
contextBlocks: allContextBlocks,
|
|
287
|
+
filesProcessed,
|
|
288
|
+
totalStrings: allStrings.length
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
async function extractStringsFromFile(filePath) {
|
|
292
|
+
const code = node_fs.readFileSync(filePath, "utf-8");
|
|
293
|
+
const ext = node_path.extname(filePath);
|
|
294
|
+
if (![
|
|
295
|
+
".ts",
|
|
296
|
+
".tsx",
|
|
297
|
+
".js",
|
|
298
|
+
".jsx"
|
|
299
|
+
].includes(ext)) return null;
|
|
300
|
+
const isTypeScript = ext === ".ts" || ext === ".tsx";
|
|
301
|
+
const isJSX = ext === ".tsx" || ext === ".jsx";
|
|
302
|
+
let extractedStrings = [];
|
|
303
|
+
let extractedContextBlocks = [];
|
|
304
|
+
const extractionPlugin = (0, experimental_ciao_core.createExtractionPlugin)({ onComplete: (result) => {
|
|
305
|
+
extractedStrings = result.strings;
|
|
306
|
+
extractedContextBlocks = result.contextBlocks;
|
|
307
|
+
} });
|
|
308
|
+
const presets = [];
|
|
309
|
+
if (isTypeScript) presets.push([require.resolve("@babel/preset-typescript"), {
|
|
310
|
+
isTSX: isJSX,
|
|
311
|
+
allExtensions: true
|
|
312
|
+
}]);
|
|
313
|
+
if (isJSX) presets.push([require.resolve("@babel/preset-react"), { runtime: "automatic" }]);
|
|
314
|
+
try {
|
|
315
|
+
await __babel_core.transformAsync(code, {
|
|
316
|
+
filename: filePath,
|
|
317
|
+
presets,
|
|
318
|
+
plugins: [extractionPlugin],
|
|
319
|
+
babelrc: false,
|
|
320
|
+
configFile: false
|
|
321
|
+
});
|
|
322
|
+
if (extractedStrings.length === 0 && extractedContextBlocks.length === 0) return null;
|
|
323
|
+
return {
|
|
324
|
+
strings: extractedStrings,
|
|
325
|
+
contextBlocks: extractedContextBlocks
|
|
326
|
+
};
|
|
327
|
+
} catch (error) {
|
|
328
|
+
console.warn(`[ciao-tools] Warning: Failed to parse ${filePath}:`, error);
|
|
329
|
+
return null;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
function mergeStrings(target, source) {
|
|
333
|
+
for (const str of source) if (!target.some((s) => s.text === str.text && s.context === str.context && s.parentContextBlockId === str.parentContextBlockId)) target.push(str);
|
|
334
|
+
}
|
|
335
|
+
function mergeContextBlocks(target, source) {
|
|
336
|
+
for (const block of source) if (!target.some((b) => b.id === block.id)) target.push(block);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
//#endregion
|
|
340
|
+
exports.CONFIG_FILE_NAMES = CONFIG_FILE_NAMES;
|
|
341
|
+
exports.CiaoApiClient = CiaoApiClient;
|
|
342
|
+
exports.CiaoApiError = CiaoApiError;
|
|
343
|
+
exports.ConfigNotFoundError = ConfigNotFoundError;
|
|
344
|
+
exports.ConfigValidationError = ConfigValidationError;
|
|
345
|
+
exports.DEFAULT_CONFIG = DEFAULT_CONFIG;
|
|
346
|
+
exports.createManifestData = createManifestData;
|
|
347
|
+
exports.defineCiaoConfig = defineCiaoConfig;
|
|
348
|
+
exports.extractStringsFromProject = extractStringsFromProject;
|
|
349
|
+
exports.generateManifestFile = generateManifestFile;
|
|
350
|
+
exports.loadConfig = loadConfig;
|
|
351
|
+
exports.pollJobUntilComplete = pollJobUntilComplete;
|
|
352
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["errorData: ApiError","code: string","statusCode: number","details?: unknown","DEFAULT_OPTIONS: Required<Omit<PollingOptions, \"onProgress\">>","DEFAULT_CONFIG: Omit<ResolvedCiaoConfig, \"projectId\">","path","fs","module","fs","path","allStrings: TranslatableString[]","allContextBlocks: ContextBlock[]","fs","path","extractedStrings: TranslatableString[]","extractedContextBlocks: ContextBlock[]","presets: babel.PluginItem[]","babel"],"sources":["../src/api/client.ts","../src/api/polling.ts","../src/config/defaults.ts","../src/config/loader.ts","../src/config/types.ts","../src/manifest/generator.ts","../src/extraction/runner.ts"],"sourcesContent":["import type {\n\tApiClientOptions,\n\tApiError,\n\tBuildSchemaRequest,\n\tJobStatusResponse,\n\tTranslationResponse,\n} from \"./types\";\n\nexport class CiaoApiClient {\n\tprivate baseUrl: string;\n\tprivate apiKey: string;\n\tprivate timeout: number;\n\n\tconstructor(options: ApiClientOptions) {\n\t\tthis.baseUrl = options.baseUrl.replace(/\\/$/, \"\");\n\t\tthis.apiKey = options.apiKey;\n\t\tthis.timeout = options.timeout ?? 30000;\n\t}\n\n\tprivate async request<T>(\n\t\tmethod: string,\n\t\tpath: string,\n\t\tbody?: unknown,\n\t): Promise<T> {\n\t\tconst url = `${this.baseUrl}${path}`;\n\t\tconst controller = new AbortController();\n\t\tconst timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n\t\ttry {\n\t\t\tconst response = await fetch(url, {\n\t\t\t\tmethod,\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\tAuthorization: `Bearer ${this.apiKey}`,\n\t\t\t\t},\n\t\t\t\tbody: body ? JSON.stringify(body) : undefined,\n\t\t\t\tsignal: controller.signal,\n\t\t\t});\n\n\t\t\tclearTimeout(timeoutId);\n\n\t\t\tif (!response.ok) {\n\t\t\t\tlet errorData: ApiError;\n\t\t\t\ttry {\n\t\t\t\t\terrorData = await response.json();\n\t\t\t\t} catch {\n\t\t\t\t\terrorData = {\n\t\t\t\t\t\tcode: `HTTP_${response.status}`,\n\t\t\t\t\t\tmessage: response.statusText,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tthrow new CiaoApiError(\n\t\t\t\t\terrorData.message,\n\t\t\t\t\terrorData.code,\n\t\t\t\t\tresponse.status,\n\t\t\t\t\terrorData.details,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn response.json() as Promise<T>;\n\t\t} catch (error) {\n\t\t\tclearTimeout(timeoutId);\n\t\t\tif (error instanceof CiaoApiError) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tif (error instanceof Error) {\n\t\t\t\tif (error.name === \"AbortError\") {\n\t\t\t\t\tthrow new CiaoApiError(\"Request timed out\", \"TIMEOUT\", 0);\n\t\t\t\t}\n\t\t\t\tthrow new CiaoApiError(error.message, \"NETWORK_ERROR\", 0);\n\t\t\t}\n\t\t\tthrow new CiaoApiError(\"Unknown error\", \"UNKNOWN\", 0);\n\t\t}\n\t}\n\n\tasync submitBuildSchema(\n\t\tbuildSchema: BuildSchemaRequest,\n\t): Promise<TranslationResponse> {\n\t\treturn this.request<TranslationResponse>(\n\t\t\t\"POST\",\n\t\t\t\"/api/translation/translate-strings\",\n\t\t\t{ buildSchema },\n\t\t);\n\t}\n\n\tasync getJobStatus(jobId: string): Promise<JobStatusResponse> {\n\t\treturn this.request<JobStatusResponse>(\n\t\t\t\"GET\",\n\t\t\t`/api/translation/job/${jobId}`,\n\t\t);\n\t}\n}\n\nexport class CiaoApiError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic code: string,\n\t\tpublic statusCode: number,\n\t\tpublic details?: unknown,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"CiaoApiError\";\n\t}\n}\n","import type { CiaoApiClient } from \"./client\";\nimport type { JobStatusResponse } from \"./types\";\n\nexport interface PollingOptions {\n\tinitialInterval?: number;\n\tmaxInterval?: number;\n\tmaxAttempts?: number;\n\tbackoffMultiplier?: number;\n\tonProgress?: (status: JobStatusResponse) => void;\n}\n\nconst DEFAULT_OPTIONS: Required<Omit<PollingOptions, \"onProgress\">> = {\n\tinitialInterval: 1000,\n\tmaxInterval: 10000,\n\tmaxAttempts: 120,\n\tbackoffMultiplier: 1.5,\n};\n\nexport async function pollJobUntilComplete(\n\tclient: CiaoApiClient,\n\tjobId: string,\n\toptions: PollingOptions = {},\n): Promise<JobStatusResponse> {\n\tconst { initialInterval, maxInterval, maxAttempts, backoffMultiplier } = {\n\t\t...DEFAULT_OPTIONS,\n\t\t...options,\n\t};\n\tconst { onProgress } = options;\n\n\tlet currentInterval = initialInterval;\n\tlet attempts = 0;\n\n\twhile (attempts < maxAttempts) {\n\t\tconst status = await client.getJobStatus(jobId);\n\n\t\tif (onProgress) {\n\t\t\tonProgress(status);\n\t\t}\n\n\t\tif (status.status === \"completed\") {\n\t\t\treturn status;\n\t\t}\n\n\t\tif (status.status === \"failed\") {\n\t\t\tthrow new Error(status.error ?? \"Job failed with unknown error\");\n\t\t}\n\n\t\tawait sleep(currentInterval);\n\t\tcurrentInterval = Math.min(\n\t\t\tcurrentInterval * backoffMultiplier,\n\t\t\tmaxInterval,\n\t\t);\n\t\tattempts++;\n\t}\n\n\tthrow new Error(`Job polling timed out after ${maxAttempts} attempts`);\n}\n\nfunction sleep(ms: number): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import type { ResolvedCiaoConfig } from \"./types\";\n\nexport const DEFAULT_CONFIG: Omit<ResolvedCiaoConfig, \"projectId\"> = {\n\tinclude: [\n\t\t\"src/**/*.{ts,tsx,js,jsx}\",\n\t\t\"app/**/*.{ts,tsx,js,jsx}\",\n\t\t\"pages/**/*.{ts,tsx,js,jsx}\",\n\t\t\"components/**/*.{ts,tsx,js,jsx}\",\n\t],\n\texclude: [\n\t\t\"**/node_modules/**\",\n\t\t\"**/*.test.{ts,tsx,js,jsx}\",\n\t\t\"**/*.spec.{ts,tsx,js,jsx}\",\n\t\t\"**/__tests__/**\",\n\t\t\"**/dist/**\",\n\t\t\"**/.next/**\",\n\t],\n\toutputDir: \"__generated__\",\n\tserverUrl: \"https://server.ciao-tools.com\",\n};\n\nexport const CONFIG_FILE_NAMES = [\n\t\"ciao.config.ts\",\n\t\"ciao.config.js\",\n\t\"ciao.config.mjs\",\n] as const;\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { CONFIG_FILE_NAMES, DEFAULT_CONFIG } from \"./defaults\";\nimport type { CiaoConfig, ResolvedCiaoConfig } from \"./types\";\n\nexport interface LoadConfigOptions {\n\tcwd?: string;\n\tconfigPath?: string;\n}\n\nexport async function loadConfig(\n\toptions: LoadConfigOptions = {},\n): Promise<ResolvedCiaoConfig> {\n\tconst cwd = options.cwd ?? process.cwd();\n\tlet configPath = options.configPath;\n\n\tif (!configPath) {\n\t\tfor (const fileName of CONFIG_FILE_NAMES) {\n\t\t\tconst candidate = path.join(cwd, fileName);\n\t\t\tif (fs.existsSync(candidate)) {\n\t\t\t\tconfigPath = candidate;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!configPath) {\n\t\tthrow new ConfigNotFoundError(\n\t\t\t`No ciao.config.ts found. Run 'ciao init' to create one.`,\n\t\t);\n\t}\n\n\tconst absolutePath = path.isAbsolute(configPath)\n\t\t? configPath\n\t\t: path.join(cwd, configPath);\n\n\tif (!fs.existsSync(absolutePath)) {\n\t\tthrow new ConfigNotFoundError(`Config file not found: ${absolutePath}`);\n\t}\n\n\tconst config = await importConfig(absolutePath);\n\treturn resolveConfig(config, cwd);\n}\n\nasync function importConfig(configPath: string): Promise<CiaoConfig> {\n\ttry {\n\t\t// Use file:// URL for ESM compatibility\n\t\tconst fileUrl = configPath.startsWith(\"file://\")\n\t\t\t? configPath\n\t\t\t: `file://${configPath}`;\n\t\tconst module = await import(fileUrl);\n\t\tconst config = module.default ?? module;\n\n\t\tif (!config || typeof config !== \"object\") {\n\t\t\tthrow new ConfigValidationError(\"Config file must export an object\");\n\t\t}\n\n\t\treturn config as CiaoConfig;\n\t} catch (error) {\n\t\tif (error instanceof ConfigValidationError) {\n\t\t\tthrow error;\n\t\t}\n\t\tif (error instanceof Error) {\n\t\t\tthrow new ConfigValidationError(\n\t\t\t\t`Failed to load config file (${configPath}): ${error.message}`,\n\t\t\t);\n\t\t}\n\t\tthrow new ConfigValidationError(\n\t\t\t`Failed to load config file: ${configPath}`,\n\t\t);\n\t}\n}\n\nfunction resolveConfig(config: CiaoConfig, cwd: string): ResolvedCiaoConfig {\n\tif (!config.projectId) {\n\t\tthrow new ConfigValidationError(\"projectId is required in ciao.config.ts\");\n\t}\n\n\tconst outputDir = config.outputDir ?? DEFAULT_CONFIG.outputDir;\n\tconst resolvedOutputDir = path.isAbsolute(outputDir)\n\t\t? outputDir\n\t\t: path.join(cwd, outputDir);\n\n\treturn {\n\t\tprojectId: config.projectId,\n\t\tstyleId: config.styleId,\n\t\tinclude: config.include ?? DEFAULT_CONFIG.include,\n\t\texclude: config.exclude ?? DEFAULT_CONFIG.exclude,\n\t\toutputDir: resolvedOutputDir,\n\t\tserverUrl: config.serverUrl ?? DEFAULT_CONFIG.serverUrl,\n\t};\n}\n\nexport class ConfigNotFoundError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"ConfigNotFoundError\";\n\t}\n}\n\nexport class ConfigValidationError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"ConfigValidationError\";\n\t}\n}\n","export interface CiaoConfig {\n\tprojectId: string;\n\tstyleId?: string;\n\tinclude?: string[];\n\texclude?: string[];\n\toutputDir?: string;\n\tserverUrl?: string;\n}\n\nexport interface ResolvedCiaoConfig {\n\tprojectId: string;\n\tstyleId?: string;\n\tinclude: string[];\n\texclude: string[];\n\toutputDir: string;\n\tserverUrl: string;\n}\n\nexport function defineCiaoConfig(config: CiaoConfig): CiaoConfig {\n\treturn config;\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { GenerateManifestOptions, ManifestData } from \"./types\";\n\nexport async function generateManifestFile(\n\toptions: GenerateManifestOptions,\n): Promise<string> {\n\tconst { outputDir, data } = options;\n\n\tif (!fs.existsSync(outputDir)) {\n\t\tfs.mkdirSync(outputDir, { recursive: true });\n\t}\n\n\tconst manifestPath = path.join(outputDir, \"ciao-manifest.ts\");\n\tconst content = generateManifestContent(data);\n\n\tfs.writeFileSync(manifestPath, content, \"utf-8\");\n\n\treturn manifestPath;\n}\n\nfunction generateManifestContent(data: ManifestData): string {\n\tconst cdnUrlsEntries = Object.entries(data.cdnUrls)\n\t\t.map(([lang, url]) => `\\t\"${lang}\": \"${url}\"`)\n\t\t.join(\",\\n\");\n\n\tconst languagesArray = data.languages.map((l) => `\"${l}\"`).join(\", \");\n\n\treturn `// This file is auto-generated by ciao-tools. Do not edit manually.\n// Generated at: ${data.generatedAt}\n\nexport const ciaoManifest = {\n\tversion: \"${data.version}\",\n\tprojectId: \"${data.projectId}\",\n\tsourceLanguage: \"${data.sourceLanguage}\",\n\tlanguages: [${languagesArray}] as const,\n\tcdnUrls: {\n${cdnUrlsEntries}\n\t} as const,\n\tgeneratedAt: \"${data.generatedAt}\",\n} as const;\n\nexport type CiaoLanguage = (typeof ciaoManifest.languages)[number];\n\nexport type CiaoManifest = typeof ciaoManifest;\n`;\n}\n\nexport function createManifestData(\n\tprojectId: string,\n\tsourceLanguage: string,\n\tlanguages: string[],\n\tcdnUrls: Record<string, string>,\n\tversion: string,\n): ManifestData {\n\treturn {\n\t\tversion,\n\t\tprojectId,\n\t\tsourceLanguage,\n\t\tlanguages,\n\t\tcdnUrls,\n\t\tgeneratedAt: new Date().toISOString(),\n\t};\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as babel from \"@babel/core\";\nimport { createExtractionPlugin } from \"experimental-ciao-core\";\nimport { glob } from \"glob\";\nimport type {\n\tContextBlock,\n\tExtractionOptions,\n\tProjectExtractionResult,\n\tTranslatableString,\n} from \"./types\";\n\nexport async function extractStringsFromProject(\n\toptions: ExtractionOptions,\n): Promise<ProjectExtractionResult> {\n\tconst cwd = options.cwd ?? process.cwd();\n\tconst allStrings: TranslatableString[] = [];\n\tconst allContextBlocks: ContextBlock[] = [];\n\tlet filesProcessed = 0;\n\n\tconst files = await glob(options.include, {\n\t\tcwd,\n\t\tignore: options.exclude,\n\t\tabsolute: true,\n\t\tnodir: true,\n\t});\n\n\tfor (const filePath of files) {\n\t\tconst result = await extractStringsFromFile(filePath);\n\t\tif (result) {\n\t\t\tmergeStrings(allStrings, result.strings);\n\t\t\tmergeContextBlocks(allContextBlocks, result.contextBlocks);\n\t\t\tfilesProcessed++;\n\t\t}\n\t}\n\n\treturn {\n\t\tstrings: allStrings,\n\t\tcontextBlocks: allContextBlocks,\n\t\tfilesProcessed,\n\t\ttotalStrings: allStrings.length,\n\t};\n}\n\nasync function extractStringsFromFile(\n\tfilePath: string,\n): Promise<{\n\tstrings: TranslatableString[];\n\tcontextBlocks: ContextBlock[];\n} | null> {\n\tconst code = fs.readFileSync(filePath, \"utf-8\");\n\tconst ext = path.extname(filePath);\n\n\tif (![\".ts\", \".tsx\", \".js\", \".jsx\"].includes(ext)) {\n\t\treturn null;\n\t}\n\n\tconst isTypeScript = ext === \".ts\" || ext === \".tsx\";\n\tconst isJSX = ext === \".tsx\" || ext === \".jsx\";\n\n\tlet extractedStrings: TranslatableString[] = [];\n\tlet extractedContextBlocks: ContextBlock[] = [];\n\n\tconst extractionPlugin = createExtractionPlugin({\n\t\tonComplete: (result) => {\n\t\t\textractedStrings = result.strings;\n\t\t\textractedContextBlocks = result.contextBlocks;\n\t\t},\n\t});\n\n\tconst presets: babel.PluginItem[] = [];\n\n\tif (isTypeScript) {\n\t\tpresets.push([\n\t\t\trequire.resolve(\"@babel/preset-typescript\"),\n\t\t\t{ isTSX: isJSX, allExtensions: true },\n\t\t]);\n\t}\n\n\tif (isJSX) {\n\t\tpresets.push([\n\t\t\trequire.resolve(\"@babel/preset-react\"),\n\t\t\t{ runtime: \"automatic\" },\n\t\t]);\n\t}\n\n\ttry {\n\t\tawait babel.transformAsync(code, {\n\t\t\tfilename: filePath,\n\t\t\tpresets,\n\t\t\tplugins: [extractionPlugin],\n\t\t\tbabelrc: false,\n\t\t\tconfigFile: false,\n\t\t});\n\n\t\tif (extractedStrings.length === 0 && extractedContextBlocks.length === 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn {\n\t\t\tstrings: extractedStrings,\n\t\t\tcontextBlocks: extractedContextBlocks,\n\t\t};\n\t} catch (error) {\n\t\tconsole.warn(`[ciao-tools] Warning: Failed to parse ${filePath}:`, error);\n\t\treturn null;\n\t}\n}\n\nfunction mergeStrings(\n\ttarget: TranslatableString[],\n\tsource: TranslatableString[],\n): void {\n\tfor (const str of source) {\n\t\tconst isDuplicate = target.some(\n\t\t\t(s) =>\n\t\t\t\ts.text === str.text &&\n\t\t\t\ts.context === str.context &&\n\t\t\t\ts.parentContextBlockId === str.parentContextBlockId,\n\t\t);\n\t\tif (!isDuplicate) {\n\t\t\ttarget.push(str);\n\t\t}\n\t}\n}\n\nfunction mergeContextBlocks(\n\ttarget: ContextBlock[],\n\tsource: ContextBlock[],\n): void {\n\tfor (const block of source) {\n\t\tconst isDuplicate = target.some((b) => b.id === block.id);\n\t\tif (!isDuplicate) {\n\t\t\ttarget.push(block);\n\t\t}\n\t}\n}\n"],"mappings":"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"}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { ContextBlock as ContextBlock$1, ExtractionResult, TranslatableString as TranslatableString$1 } from "experimental-ciao-core";
|
|
2
|
+
|
|
3
|
+
//#region src/api/types.d.ts
|
|
4
|
+
interface TranslatableString {
|
|
5
|
+
text: string;
|
|
6
|
+
context?: string;
|
|
7
|
+
parentContextBlockId?: string;
|
|
8
|
+
}
|
|
9
|
+
interface ContextBlock {
|
|
10
|
+
id: string;
|
|
11
|
+
}
|
|
12
|
+
interface BuildSchemaMetadata {
|
|
13
|
+
generatedAt: string;
|
|
14
|
+
totalStrings: number;
|
|
15
|
+
totalContextBlocks: number;
|
|
16
|
+
}
|
|
17
|
+
interface BuildSchemaRequest {
|
|
18
|
+
version: "1.0";
|
|
19
|
+
projectId: string;
|
|
20
|
+
styleId?: string;
|
|
21
|
+
strings: TranslatableString[];
|
|
22
|
+
contextBlocks: ContextBlock[];
|
|
23
|
+
metadata: BuildSchemaMetadata;
|
|
24
|
+
}
|
|
25
|
+
interface TargetLanguage {
|
|
26
|
+
language: string;
|
|
27
|
+
filename: string;
|
|
28
|
+
url?: string;
|
|
29
|
+
}
|
|
30
|
+
interface OutputConfig {
|
|
31
|
+
version: "1.0";
|
|
32
|
+
projectId: string;
|
|
33
|
+
sourceLanguage: string;
|
|
34
|
+
generatedAt: string;
|
|
35
|
+
targetLanguages: TargetLanguage[];
|
|
36
|
+
}
|
|
37
|
+
interface TranslationResponse {
|
|
38
|
+
outputConfig: OutputConfig;
|
|
39
|
+
jobId?: string;
|
|
40
|
+
status: "pending" | "processing" | "completed";
|
|
41
|
+
translatedLanguages?: Record<string, Record<string, string>>;
|
|
42
|
+
}
|
|
43
|
+
interface JobStatusResponse {
|
|
44
|
+
jobId: string;
|
|
45
|
+
status: "pending" | "processing" | "completed" | "failed";
|
|
46
|
+
progress?: number;
|
|
47
|
+
outputUrls?: Record<string, string>;
|
|
48
|
+
error?: string;
|
|
49
|
+
createdAt: string;
|
|
50
|
+
completedAt?: string;
|
|
51
|
+
}
|
|
52
|
+
interface ApiError {
|
|
53
|
+
code: string;
|
|
54
|
+
message: string;
|
|
55
|
+
details?: unknown;
|
|
56
|
+
}
|
|
57
|
+
interface ApiClientOptions {
|
|
58
|
+
baseUrl: string;
|
|
59
|
+
apiKey: string;
|
|
60
|
+
timeout?: number;
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region src/api/client.d.ts
|
|
64
|
+
declare class CiaoApiClient {
|
|
65
|
+
private baseUrl;
|
|
66
|
+
private apiKey;
|
|
67
|
+
private timeout;
|
|
68
|
+
constructor(options: ApiClientOptions);
|
|
69
|
+
private request;
|
|
70
|
+
submitBuildSchema(buildSchema: BuildSchemaRequest): Promise<TranslationResponse>;
|
|
71
|
+
getJobStatus(jobId: string): Promise<JobStatusResponse>;
|
|
72
|
+
}
|
|
73
|
+
declare class CiaoApiError extends Error {
|
|
74
|
+
code: string;
|
|
75
|
+
statusCode: number;
|
|
76
|
+
details?: unknown | undefined;
|
|
77
|
+
constructor(message: string, code: string, statusCode: number, details?: unknown | undefined);
|
|
78
|
+
}
|
|
79
|
+
//#endregion
|
|
80
|
+
//#region src/api/polling.d.ts
|
|
81
|
+
interface PollingOptions {
|
|
82
|
+
initialInterval?: number;
|
|
83
|
+
maxInterval?: number;
|
|
84
|
+
maxAttempts?: number;
|
|
85
|
+
backoffMultiplier?: number;
|
|
86
|
+
onProgress?: (status: JobStatusResponse) => void;
|
|
87
|
+
}
|
|
88
|
+
declare function pollJobUntilComplete(client: CiaoApiClient, jobId: string, options?: PollingOptions): Promise<JobStatusResponse>;
|
|
89
|
+
//#endregion
|
|
90
|
+
//#region src/config/types.d.ts
|
|
91
|
+
interface CiaoConfig {
|
|
92
|
+
projectId: string;
|
|
93
|
+
styleId?: string;
|
|
94
|
+
include?: string[];
|
|
95
|
+
exclude?: string[];
|
|
96
|
+
outputDir?: string;
|
|
97
|
+
serverUrl?: string;
|
|
98
|
+
}
|
|
99
|
+
interface ResolvedCiaoConfig {
|
|
100
|
+
projectId: string;
|
|
101
|
+
styleId?: string;
|
|
102
|
+
include: string[];
|
|
103
|
+
exclude: string[];
|
|
104
|
+
outputDir: string;
|
|
105
|
+
serverUrl: string;
|
|
106
|
+
}
|
|
107
|
+
declare function defineCiaoConfig(config: CiaoConfig): CiaoConfig;
|
|
108
|
+
//#endregion
|
|
109
|
+
//#region src/config/loader.d.ts
|
|
110
|
+
interface LoadConfigOptions {
|
|
111
|
+
cwd?: string;
|
|
112
|
+
configPath?: string;
|
|
113
|
+
}
|
|
114
|
+
declare function loadConfig(options?: LoadConfigOptions): Promise<ResolvedCiaoConfig>;
|
|
115
|
+
declare class ConfigNotFoundError extends Error {
|
|
116
|
+
constructor(message: string);
|
|
117
|
+
}
|
|
118
|
+
declare class ConfigValidationError extends Error {
|
|
119
|
+
constructor(message: string);
|
|
120
|
+
}
|
|
121
|
+
//#endregion
|
|
122
|
+
//#region src/config/defaults.d.ts
|
|
123
|
+
declare const DEFAULT_CONFIG: Omit<ResolvedCiaoConfig, "projectId">;
|
|
124
|
+
declare const CONFIG_FILE_NAMES: readonly ["ciao.config.ts", "ciao.config.js", "ciao.config.mjs"];
|
|
125
|
+
//#endregion
|
|
126
|
+
//#region src/manifest/types.d.ts
|
|
127
|
+
interface ManifestData {
|
|
128
|
+
version: string;
|
|
129
|
+
projectId: string;
|
|
130
|
+
sourceLanguage: string;
|
|
131
|
+
languages: string[];
|
|
132
|
+
cdnUrls: Record<string, string>;
|
|
133
|
+
generatedAt: string;
|
|
134
|
+
}
|
|
135
|
+
interface GenerateManifestOptions {
|
|
136
|
+
outputDir: string;
|
|
137
|
+
data: ManifestData;
|
|
138
|
+
}
|
|
139
|
+
//#endregion
|
|
140
|
+
//#region src/manifest/generator.d.ts
|
|
141
|
+
declare function generateManifestFile(options: GenerateManifestOptions): Promise<string>;
|
|
142
|
+
declare function createManifestData(projectId: string, sourceLanguage: string, languages: string[], cdnUrls: Record<string, string>, version: string): ManifestData;
|
|
143
|
+
//#endregion
|
|
144
|
+
//#region src/extraction/types.d.ts
|
|
145
|
+
interface ExtractionOptions {
|
|
146
|
+
include: string[];
|
|
147
|
+
exclude: string[];
|
|
148
|
+
cwd?: string;
|
|
149
|
+
}
|
|
150
|
+
interface ProjectExtractionResult {
|
|
151
|
+
strings: TranslatableString$1[];
|
|
152
|
+
contextBlocks: ContextBlock$1[];
|
|
153
|
+
filesProcessed: number;
|
|
154
|
+
totalStrings: number;
|
|
155
|
+
}
|
|
156
|
+
//#endregion
|
|
157
|
+
//#region src/extraction/runner.d.ts
|
|
158
|
+
declare function extractStringsFromProject(options: ExtractionOptions): Promise<ProjectExtractionResult>;
|
|
159
|
+
//#endregion
|
|
160
|
+
export { type ApiClientOptions, type ContextBlock as ApiContextBlock, type ApiError, type TranslatableString as ApiTranslatableString, type BuildSchemaMetadata, type BuildSchemaRequest, CONFIG_FILE_NAMES, CiaoApiClient, CiaoApiError, type CiaoConfig, ConfigNotFoundError, ConfigValidationError, type ContextBlock$1 as ContextBlock, DEFAULT_CONFIG, type ExtractionOptions, type ExtractionResult, type GenerateManifestOptions, type JobStatusResponse, type LoadConfigOptions, type ManifestData, type OutputConfig, type PollingOptions, type ProjectExtractionResult, type ResolvedCiaoConfig, type TargetLanguage, type TranslatableString$1 as TranslatableString, type TranslationResponse, createManifestData, defineCiaoConfig, extractStringsFromProject, generateManifestFile, loadConfig, pollJobUntilComplete };
|
|
161
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/api/types.ts","../src/api/client.ts","../src/api/polling.ts","../src/config/types.ts","../src/config/loader.ts","../src/config/defaults.ts","../src/manifest/types.ts","../src/manifest/generator.ts","../src/extraction/types.ts","../src/extraction/runner.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { ContextBlock as ContextBlock$1, ExtractionResult, TranslatableString as TranslatableString$1 } from "experimental-ciao-core";
|
|
2
|
+
|
|
3
|
+
//#region src/api/types.d.ts
|
|
4
|
+
interface TranslatableString {
|
|
5
|
+
text: string;
|
|
6
|
+
context?: string;
|
|
7
|
+
parentContextBlockId?: string;
|
|
8
|
+
}
|
|
9
|
+
interface ContextBlock {
|
|
10
|
+
id: string;
|
|
11
|
+
}
|
|
12
|
+
interface BuildSchemaMetadata {
|
|
13
|
+
generatedAt: string;
|
|
14
|
+
totalStrings: number;
|
|
15
|
+
totalContextBlocks: number;
|
|
16
|
+
}
|
|
17
|
+
interface BuildSchemaRequest {
|
|
18
|
+
version: "1.0";
|
|
19
|
+
projectId: string;
|
|
20
|
+
styleId?: string;
|
|
21
|
+
strings: TranslatableString[];
|
|
22
|
+
contextBlocks: ContextBlock[];
|
|
23
|
+
metadata: BuildSchemaMetadata;
|
|
24
|
+
}
|
|
25
|
+
interface TargetLanguage {
|
|
26
|
+
language: string;
|
|
27
|
+
filename: string;
|
|
28
|
+
url?: string;
|
|
29
|
+
}
|
|
30
|
+
interface OutputConfig {
|
|
31
|
+
version: "1.0";
|
|
32
|
+
projectId: string;
|
|
33
|
+
sourceLanguage: string;
|
|
34
|
+
generatedAt: string;
|
|
35
|
+
targetLanguages: TargetLanguage[];
|
|
36
|
+
}
|
|
37
|
+
interface TranslationResponse {
|
|
38
|
+
outputConfig: OutputConfig;
|
|
39
|
+
jobId?: string;
|
|
40
|
+
status: "pending" | "processing" | "completed";
|
|
41
|
+
translatedLanguages?: Record<string, Record<string, string>>;
|
|
42
|
+
}
|
|
43
|
+
interface JobStatusResponse {
|
|
44
|
+
jobId: string;
|
|
45
|
+
status: "pending" | "processing" | "completed" | "failed";
|
|
46
|
+
progress?: number;
|
|
47
|
+
outputUrls?: Record<string, string>;
|
|
48
|
+
error?: string;
|
|
49
|
+
createdAt: string;
|
|
50
|
+
completedAt?: string;
|
|
51
|
+
}
|
|
52
|
+
interface ApiError {
|
|
53
|
+
code: string;
|
|
54
|
+
message: string;
|
|
55
|
+
details?: unknown;
|
|
56
|
+
}
|
|
57
|
+
interface ApiClientOptions {
|
|
58
|
+
baseUrl: string;
|
|
59
|
+
apiKey: string;
|
|
60
|
+
timeout?: number;
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region src/api/client.d.ts
|
|
64
|
+
declare class CiaoApiClient {
|
|
65
|
+
private baseUrl;
|
|
66
|
+
private apiKey;
|
|
67
|
+
private timeout;
|
|
68
|
+
constructor(options: ApiClientOptions);
|
|
69
|
+
private request;
|
|
70
|
+
submitBuildSchema(buildSchema: BuildSchemaRequest): Promise<TranslationResponse>;
|
|
71
|
+
getJobStatus(jobId: string): Promise<JobStatusResponse>;
|
|
72
|
+
}
|
|
73
|
+
declare class CiaoApiError extends Error {
|
|
74
|
+
code: string;
|
|
75
|
+
statusCode: number;
|
|
76
|
+
details?: unknown | undefined;
|
|
77
|
+
constructor(message: string, code: string, statusCode: number, details?: unknown | undefined);
|
|
78
|
+
}
|
|
79
|
+
//#endregion
|
|
80
|
+
//#region src/api/polling.d.ts
|
|
81
|
+
interface PollingOptions {
|
|
82
|
+
initialInterval?: number;
|
|
83
|
+
maxInterval?: number;
|
|
84
|
+
maxAttempts?: number;
|
|
85
|
+
backoffMultiplier?: number;
|
|
86
|
+
onProgress?: (status: JobStatusResponse) => void;
|
|
87
|
+
}
|
|
88
|
+
declare function pollJobUntilComplete(client: CiaoApiClient, jobId: string, options?: PollingOptions): Promise<JobStatusResponse>;
|
|
89
|
+
//#endregion
|
|
90
|
+
//#region src/config/types.d.ts
|
|
91
|
+
interface CiaoConfig {
|
|
92
|
+
projectId: string;
|
|
93
|
+
styleId?: string;
|
|
94
|
+
include?: string[];
|
|
95
|
+
exclude?: string[];
|
|
96
|
+
outputDir?: string;
|
|
97
|
+
serverUrl?: string;
|
|
98
|
+
}
|
|
99
|
+
interface ResolvedCiaoConfig {
|
|
100
|
+
projectId: string;
|
|
101
|
+
styleId?: string;
|
|
102
|
+
include: string[];
|
|
103
|
+
exclude: string[];
|
|
104
|
+
outputDir: string;
|
|
105
|
+
serverUrl: string;
|
|
106
|
+
}
|
|
107
|
+
declare function defineCiaoConfig(config: CiaoConfig): CiaoConfig;
|
|
108
|
+
//#endregion
|
|
109
|
+
//#region src/config/loader.d.ts
|
|
110
|
+
interface LoadConfigOptions {
|
|
111
|
+
cwd?: string;
|
|
112
|
+
configPath?: string;
|
|
113
|
+
}
|
|
114
|
+
declare function loadConfig(options?: LoadConfigOptions): Promise<ResolvedCiaoConfig>;
|
|
115
|
+
declare class ConfigNotFoundError extends Error {
|
|
116
|
+
constructor(message: string);
|
|
117
|
+
}
|
|
118
|
+
declare class ConfigValidationError extends Error {
|
|
119
|
+
constructor(message: string);
|
|
120
|
+
}
|
|
121
|
+
//#endregion
|
|
122
|
+
//#region src/config/defaults.d.ts
|
|
123
|
+
declare const DEFAULT_CONFIG: Omit<ResolvedCiaoConfig, "projectId">;
|
|
124
|
+
declare const CONFIG_FILE_NAMES: readonly ["ciao.config.ts", "ciao.config.js", "ciao.config.mjs"];
|
|
125
|
+
//#endregion
|
|
126
|
+
//#region src/manifest/types.d.ts
|
|
127
|
+
interface ManifestData {
|
|
128
|
+
version: string;
|
|
129
|
+
projectId: string;
|
|
130
|
+
sourceLanguage: string;
|
|
131
|
+
languages: string[];
|
|
132
|
+
cdnUrls: Record<string, string>;
|
|
133
|
+
generatedAt: string;
|
|
134
|
+
}
|
|
135
|
+
interface GenerateManifestOptions {
|
|
136
|
+
outputDir: string;
|
|
137
|
+
data: ManifestData;
|
|
138
|
+
}
|
|
139
|
+
//#endregion
|
|
140
|
+
//#region src/manifest/generator.d.ts
|
|
141
|
+
declare function generateManifestFile(options: GenerateManifestOptions): Promise<string>;
|
|
142
|
+
declare function createManifestData(projectId: string, sourceLanguage: string, languages: string[], cdnUrls: Record<string, string>, version: string): ManifestData;
|
|
143
|
+
//#endregion
|
|
144
|
+
//#region src/extraction/types.d.ts
|
|
145
|
+
interface ExtractionOptions {
|
|
146
|
+
include: string[];
|
|
147
|
+
exclude: string[];
|
|
148
|
+
cwd?: string;
|
|
149
|
+
}
|
|
150
|
+
interface ProjectExtractionResult {
|
|
151
|
+
strings: TranslatableString$1[];
|
|
152
|
+
contextBlocks: ContextBlock$1[];
|
|
153
|
+
filesProcessed: number;
|
|
154
|
+
totalStrings: number;
|
|
155
|
+
}
|
|
156
|
+
//#endregion
|
|
157
|
+
//#region src/extraction/runner.d.ts
|
|
158
|
+
declare function extractStringsFromProject(options: ExtractionOptions): Promise<ProjectExtractionResult>;
|
|
159
|
+
//#endregion
|
|
160
|
+
export { type ApiClientOptions, type ContextBlock as ApiContextBlock, type ApiError, type TranslatableString as ApiTranslatableString, type BuildSchemaMetadata, type BuildSchemaRequest, CONFIG_FILE_NAMES, CiaoApiClient, CiaoApiError, type CiaoConfig, ConfigNotFoundError, ConfigValidationError, type ContextBlock$1 as ContextBlock, DEFAULT_CONFIG, type ExtractionOptions, type ExtractionResult, type GenerateManifestOptions, type JobStatusResponse, type LoadConfigOptions, type ManifestData, type OutputConfig, type PollingOptions, type ProjectExtractionResult, type ResolvedCiaoConfig, type TargetLanguage, type TranslatableString$1 as TranslatableString, type TranslationResponse, createManifestData, defineCiaoConfig, extractStringsFromProject, generateManifestFile, loadConfig, pollJobUntilComplete };
|
|
161
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/api/types.ts","../src/api/client.ts","../src/api/polling.ts","../src/config/types.ts","../src/config/loader.ts","../src/config/defaults.ts","../src/manifest/types.ts","../src/manifest/generator.ts","../src/extraction/types.ts","../src/extraction/runner.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import * as babel from "@babel/core";
|
|
5
|
+
import { createExtractionPlugin } from "experimental-ciao-core";
|
|
6
|
+
import { glob } from "glob";
|
|
7
|
+
|
|
8
|
+
//#region rolldown:runtime
|
|
9
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
10
|
+
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/api/client.ts
|
|
13
|
+
var CiaoApiClient = class {
|
|
14
|
+
baseUrl;
|
|
15
|
+
apiKey;
|
|
16
|
+
timeout;
|
|
17
|
+
constructor(options) {
|
|
18
|
+
this.baseUrl = options.baseUrl.replace(/\/$/, "");
|
|
19
|
+
this.apiKey = options.apiKey;
|
|
20
|
+
this.timeout = options.timeout ?? 3e4;
|
|
21
|
+
}
|
|
22
|
+
async request(method, path$1, body) {
|
|
23
|
+
const url = `${this.baseUrl}${path$1}`;
|
|
24
|
+
const controller = new AbortController();
|
|
25
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
26
|
+
try {
|
|
27
|
+
const response = await fetch(url, {
|
|
28
|
+
method,
|
|
29
|
+
headers: {
|
|
30
|
+
"Content-Type": "application/json",
|
|
31
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
32
|
+
},
|
|
33
|
+
body: body ? JSON.stringify(body) : void 0,
|
|
34
|
+
signal: controller.signal
|
|
35
|
+
});
|
|
36
|
+
clearTimeout(timeoutId);
|
|
37
|
+
if (!response.ok) {
|
|
38
|
+
let errorData;
|
|
39
|
+
try {
|
|
40
|
+
errorData = await response.json();
|
|
41
|
+
} catch {
|
|
42
|
+
errorData = {
|
|
43
|
+
code: `HTTP_${response.status}`,
|
|
44
|
+
message: response.statusText
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
throw new CiaoApiError(errorData.message, errorData.code, response.status, errorData.details);
|
|
48
|
+
}
|
|
49
|
+
return response.json();
|
|
50
|
+
} catch (error) {
|
|
51
|
+
clearTimeout(timeoutId);
|
|
52
|
+
if (error instanceof CiaoApiError) throw error;
|
|
53
|
+
if (error instanceof Error) {
|
|
54
|
+
if (error.name === "AbortError") throw new CiaoApiError("Request timed out", "TIMEOUT", 0);
|
|
55
|
+
throw new CiaoApiError(error.message, "NETWORK_ERROR", 0);
|
|
56
|
+
}
|
|
57
|
+
throw new CiaoApiError("Unknown error", "UNKNOWN", 0);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async submitBuildSchema(buildSchema) {
|
|
61
|
+
return this.request("POST", "/api/translation/translate-strings", { buildSchema });
|
|
62
|
+
}
|
|
63
|
+
async getJobStatus(jobId) {
|
|
64
|
+
return this.request("GET", `/api/translation/job/${jobId}`);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
var CiaoApiError = class extends Error {
|
|
68
|
+
constructor(message, code, statusCode, details) {
|
|
69
|
+
super(message);
|
|
70
|
+
this.code = code;
|
|
71
|
+
this.statusCode = statusCode;
|
|
72
|
+
this.details = details;
|
|
73
|
+
this.name = "CiaoApiError";
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
//#endregion
|
|
78
|
+
//#region src/api/polling.ts
|
|
79
|
+
const DEFAULT_OPTIONS = {
|
|
80
|
+
initialInterval: 1e3,
|
|
81
|
+
maxInterval: 1e4,
|
|
82
|
+
maxAttempts: 120,
|
|
83
|
+
backoffMultiplier: 1.5
|
|
84
|
+
};
|
|
85
|
+
async function pollJobUntilComplete(client, jobId, options = {}) {
|
|
86
|
+
const { initialInterval, maxInterval, maxAttempts, backoffMultiplier } = {
|
|
87
|
+
...DEFAULT_OPTIONS,
|
|
88
|
+
...options
|
|
89
|
+
};
|
|
90
|
+
const { onProgress } = options;
|
|
91
|
+
let currentInterval = initialInterval;
|
|
92
|
+
let attempts = 0;
|
|
93
|
+
while (attempts < maxAttempts) {
|
|
94
|
+
const status = await client.getJobStatus(jobId);
|
|
95
|
+
if (onProgress) onProgress(status);
|
|
96
|
+
if (status.status === "completed") return status;
|
|
97
|
+
if (status.status === "failed") throw new Error(status.error ?? "Job failed with unknown error");
|
|
98
|
+
await sleep(currentInterval);
|
|
99
|
+
currentInterval = Math.min(currentInterval * backoffMultiplier, maxInterval);
|
|
100
|
+
attempts++;
|
|
101
|
+
}
|
|
102
|
+
throw new Error(`Job polling timed out after ${maxAttempts} attempts`);
|
|
103
|
+
}
|
|
104
|
+
function sleep(ms) {
|
|
105
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
//#endregion
|
|
109
|
+
//#region src/config/defaults.ts
|
|
110
|
+
const DEFAULT_CONFIG = {
|
|
111
|
+
include: [
|
|
112
|
+
"src/**/*.{ts,tsx,js,jsx}",
|
|
113
|
+
"app/**/*.{ts,tsx,js,jsx}",
|
|
114
|
+
"pages/**/*.{ts,tsx,js,jsx}",
|
|
115
|
+
"components/**/*.{ts,tsx,js,jsx}"
|
|
116
|
+
],
|
|
117
|
+
exclude: [
|
|
118
|
+
"**/node_modules/**",
|
|
119
|
+
"**/*.test.{ts,tsx,js,jsx}",
|
|
120
|
+
"**/*.spec.{ts,tsx,js,jsx}",
|
|
121
|
+
"**/__tests__/**",
|
|
122
|
+
"**/dist/**",
|
|
123
|
+
"**/.next/**"
|
|
124
|
+
],
|
|
125
|
+
outputDir: "__generated__",
|
|
126
|
+
serverUrl: "https://server.ciao-tools.com"
|
|
127
|
+
};
|
|
128
|
+
const CONFIG_FILE_NAMES = [
|
|
129
|
+
"ciao.config.ts",
|
|
130
|
+
"ciao.config.js",
|
|
131
|
+
"ciao.config.mjs"
|
|
132
|
+
];
|
|
133
|
+
|
|
134
|
+
//#endregion
|
|
135
|
+
//#region src/config/loader.ts
|
|
136
|
+
async function loadConfig(options = {}) {
|
|
137
|
+
const cwd = options.cwd ?? process.cwd();
|
|
138
|
+
let configPath = options.configPath;
|
|
139
|
+
if (!configPath) for (const fileName of CONFIG_FILE_NAMES) {
|
|
140
|
+
const candidate = path.join(cwd, fileName);
|
|
141
|
+
if (fs.existsSync(candidate)) {
|
|
142
|
+
configPath = candidate;
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (!configPath) throw new ConfigNotFoundError(`No ciao.config.ts found. Run 'ciao init' to create one.`);
|
|
147
|
+
const absolutePath = path.isAbsolute(configPath) ? configPath : path.join(cwd, configPath);
|
|
148
|
+
if (!fs.existsSync(absolutePath)) throw new ConfigNotFoundError(`Config file not found: ${absolutePath}`);
|
|
149
|
+
return resolveConfig(await importConfig(absolutePath), cwd);
|
|
150
|
+
}
|
|
151
|
+
async function importConfig(configPath) {
|
|
152
|
+
try {
|
|
153
|
+
const module = await (configPath.startsWith("file://") ? import(configPath) : import(`file://${configPath}`));
|
|
154
|
+
const config = module.default ?? module;
|
|
155
|
+
if (!config || typeof config !== "object") throw new ConfigValidationError("Config file must export an object");
|
|
156
|
+
return config;
|
|
157
|
+
} catch (error) {
|
|
158
|
+
if (error instanceof ConfigValidationError) throw error;
|
|
159
|
+
if (error instanceof Error) throw new ConfigValidationError(`Failed to load config file (${configPath}): ${error.message}`);
|
|
160
|
+
throw new ConfigValidationError(`Failed to load config file: ${configPath}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function resolveConfig(config, cwd) {
|
|
164
|
+
if (!config.projectId) throw new ConfigValidationError("projectId is required in ciao.config.ts");
|
|
165
|
+
const outputDir = config.outputDir ?? DEFAULT_CONFIG.outputDir;
|
|
166
|
+
const resolvedOutputDir = path.isAbsolute(outputDir) ? outputDir : path.join(cwd, outputDir);
|
|
167
|
+
return {
|
|
168
|
+
projectId: config.projectId,
|
|
169
|
+
styleId: config.styleId,
|
|
170
|
+
include: config.include ?? DEFAULT_CONFIG.include,
|
|
171
|
+
exclude: config.exclude ?? DEFAULT_CONFIG.exclude,
|
|
172
|
+
outputDir: resolvedOutputDir,
|
|
173
|
+
serverUrl: config.serverUrl ?? DEFAULT_CONFIG.serverUrl
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
var ConfigNotFoundError = class extends Error {
|
|
177
|
+
constructor(message) {
|
|
178
|
+
super(message);
|
|
179
|
+
this.name = "ConfigNotFoundError";
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
var ConfigValidationError = class extends Error {
|
|
183
|
+
constructor(message) {
|
|
184
|
+
super(message);
|
|
185
|
+
this.name = "ConfigValidationError";
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
//#endregion
|
|
190
|
+
//#region src/config/types.ts
|
|
191
|
+
function defineCiaoConfig(config) {
|
|
192
|
+
return config;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
//#endregion
|
|
196
|
+
//#region src/manifest/generator.ts
|
|
197
|
+
async function generateManifestFile(options) {
|
|
198
|
+
const { outputDir, data } = options;
|
|
199
|
+
if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir, { recursive: true });
|
|
200
|
+
const manifestPath = path.join(outputDir, "ciao-manifest.ts");
|
|
201
|
+
const content = generateManifestContent(data);
|
|
202
|
+
fs.writeFileSync(manifestPath, content, "utf-8");
|
|
203
|
+
return manifestPath;
|
|
204
|
+
}
|
|
205
|
+
function generateManifestContent(data) {
|
|
206
|
+
const cdnUrlsEntries = Object.entries(data.cdnUrls).map(([lang, url]) => `\t"${lang}": "${url}"`).join(",\n");
|
|
207
|
+
const languagesArray = data.languages.map((l) => `"${l}"`).join(", ");
|
|
208
|
+
return `// This file is auto-generated by ciao-tools. Do not edit manually.
|
|
209
|
+
// Generated at: ${data.generatedAt}
|
|
210
|
+
|
|
211
|
+
export const ciaoManifest = {
|
|
212
|
+
version: "${data.version}",
|
|
213
|
+
projectId: "${data.projectId}",
|
|
214
|
+
sourceLanguage: "${data.sourceLanguage}",
|
|
215
|
+
languages: [${languagesArray}] as const,
|
|
216
|
+
cdnUrls: {
|
|
217
|
+
${cdnUrlsEntries}
|
|
218
|
+
} as const,
|
|
219
|
+
generatedAt: "${data.generatedAt}",
|
|
220
|
+
} as const;
|
|
221
|
+
|
|
222
|
+
export type CiaoLanguage = (typeof ciaoManifest.languages)[number];
|
|
223
|
+
|
|
224
|
+
export type CiaoManifest = typeof ciaoManifest;
|
|
225
|
+
`;
|
|
226
|
+
}
|
|
227
|
+
function createManifestData(projectId, sourceLanguage, languages, cdnUrls, version) {
|
|
228
|
+
return {
|
|
229
|
+
version,
|
|
230
|
+
projectId,
|
|
231
|
+
sourceLanguage,
|
|
232
|
+
languages,
|
|
233
|
+
cdnUrls,
|
|
234
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
//#endregion
|
|
239
|
+
//#region src/extraction/runner.ts
|
|
240
|
+
async function extractStringsFromProject(options) {
|
|
241
|
+
const cwd = options.cwd ?? process.cwd();
|
|
242
|
+
const allStrings = [];
|
|
243
|
+
const allContextBlocks = [];
|
|
244
|
+
let filesProcessed = 0;
|
|
245
|
+
const files = await glob(options.include, {
|
|
246
|
+
cwd,
|
|
247
|
+
ignore: options.exclude,
|
|
248
|
+
absolute: true,
|
|
249
|
+
nodir: true
|
|
250
|
+
});
|
|
251
|
+
for (const filePath of files) {
|
|
252
|
+
const result = await extractStringsFromFile(filePath);
|
|
253
|
+
if (result) {
|
|
254
|
+
mergeStrings(allStrings, result.strings);
|
|
255
|
+
mergeContextBlocks(allContextBlocks, result.contextBlocks);
|
|
256
|
+
filesProcessed++;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return {
|
|
260
|
+
strings: allStrings,
|
|
261
|
+
contextBlocks: allContextBlocks,
|
|
262
|
+
filesProcessed,
|
|
263
|
+
totalStrings: allStrings.length
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
async function extractStringsFromFile(filePath) {
|
|
267
|
+
const code = fs.readFileSync(filePath, "utf-8");
|
|
268
|
+
const ext = path.extname(filePath);
|
|
269
|
+
if (![
|
|
270
|
+
".ts",
|
|
271
|
+
".tsx",
|
|
272
|
+
".js",
|
|
273
|
+
".jsx"
|
|
274
|
+
].includes(ext)) return null;
|
|
275
|
+
const isTypeScript = ext === ".ts" || ext === ".tsx";
|
|
276
|
+
const isJSX = ext === ".tsx" || ext === ".jsx";
|
|
277
|
+
let extractedStrings = [];
|
|
278
|
+
let extractedContextBlocks = [];
|
|
279
|
+
const extractionPlugin = createExtractionPlugin({ onComplete: (result) => {
|
|
280
|
+
extractedStrings = result.strings;
|
|
281
|
+
extractedContextBlocks = result.contextBlocks;
|
|
282
|
+
} });
|
|
283
|
+
const presets = [];
|
|
284
|
+
if (isTypeScript) presets.push([__require.resolve("@babel/preset-typescript"), {
|
|
285
|
+
isTSX: isJSX,
|
|
286
|
+
allExtensions: true
|
|
287
|
+
}]);
|
|
288
|
+
if (isJSX) presets.push([__require.resolve("@babel/preset-react"), { runtime: "automatic" }]);
|
|
289
|
+
try {
|
|
290
|
+
await babel.transformAsync(code, {
|
|
291
|
+
filename: filePath,
|
|
292
|
+
presets,
|
|
293
|
+
plugins: [extractionPlugin],
|
|
294
|
+
babelrc: false,
|
|
295
|
+
configFile: false
|
|
296
|
+
});
|
|
297
|
+
if (extractedStrings.length === 0 && extractedContextBlocks.length === 0) return null;
|
|
298
|
+
return {
|
|
299
|
+
strings: extractedStrings,
|
|
300
|
+
contextBlocks: extractedContextBlocks
|
|
301
|
+
};
|
|
302
|
+
} catch (error) {
|
|
303
|
+
console.warn(`[ciao-tools] Warning: Failed to parse ${filePath}:`, error);
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
function mergeStrings(target, source) {
|
|
308
|
+
for (const str of source) if (!target.some((s) => s.text === str.text && s.context === str.context && s.parentContextBlockId === str.parentContextBlockId)) target.push(str);
|
|
309
|
+
}
|
|
310
|
+
function mergeContextBlocks(target, source) {
|
|
311
|
+
for (const block of source) if (!target.some((b) => b.id === block.id)) target.push(block);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
//#endregion
|
|
315
|
+
export { CONFIG_FILE_NAMES, CiaoApiClient, CiaoApiError, ConfigNotFoundError, ConfigValidationError, DEFAULT_CONFIG, createManifestData, defineCiaoConfig, extractStringsFromProject, generateManifestFile, loadConfig, pollJobUntilComplete };
|
|
316
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["path","errorData: ApiError","code: string","statusCode: number","details?: unknown","DEFAULT_OPTIONS: Required<Omit<PollingOptions, \"onProgress\">>","DEFAULT_CONFIG: Omit<ResolvedCiaoConfig, \"projectId\">","allStrings: TranslatableString[]","allContextBlocks: ContextBlock[]","extractedStrings: TranslatableString[]","extractedContextBlocks: ContextBlock[]","presets: babel.PluginItem[]"],"sources":["../src/api/client.ts","../src/api/polling.ts","../src/config/defaults.ts","../src/config/loader.ts","../src/config/types.ts","../src/manifest/generator.ts","../src/extraction/runner.ts"],"sourcesContent":["import type {\n\tApiClientOptions,\n\tApiError,\n\tBuildSchemaRequest,\n\tJobStatusResponse,\n\tTranslationResponse,\n} from \"./types\";\n\nexport class CiaoApiClient {\n\tprivate baseUrl: string;\n\tprivate apiKey: string;\n\tprivate timeout: number;\n\n\tconstructor(options: ApiClientOptions) {\n\t\tthis.baseUrl = options.baseUrl.replace(/\\/$/, \"\");\n\t\tthis.apiKey = options.apiKey;\n\t\tthis.timeout = options.timeout ?? 30000;\n\t}\n\n\tprivate async request<T>(\n\t\tmethod: string,\n\t\tpath: string,\n\t\tbody?: unknown,\n\t): Promise<T> {\n\t\tconst url = `${this.baseUrl}${path}`;\n\t\tconst controller = new AbortController();\n\t\tconst timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n\t\ttry {\n\t\t\tconst response = await fetch(url, {\n\t\t\t\tmethod,\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\tAuthorization: `Bearer ${this.apiKey}`,\n\t\t\t\t},\n\t\t\t\tbody: body ? JSON.stringify(body) : undefined,\n\t\t\t\tsignal: controller.signal,\n\t\t\t});\n\n\t\t\tclearTimeout(timeoutId);\n\n\t\t\tif (!response.ok) {\n\t\t\t\tlet errorData: ApiError;\n\t\t\t\ttry {\n\t\t\t\t\terrorData = await response.json();\n\t\t\t\t} catch {\n\t\t\t\t\terrorData = {\n\t\t\t\t\t\tcode: `HTTP_${response.status}`,\n\t\t\t\t\t\tmessage: response.statusText,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tthrow new CiaoApiError(\n\t\t\t\t\terrorData.message,\n\t\t\t\t\terrorData.code,\n\t\t\t\t\tresponse.status,\n\t\t\t\t\terrorData.details,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn response.json() as Promise<T>;\n\t\t} catch (error) {\n\t\t\tclearTimeout(timeoutId);\n\t\t\tif (error instanceof CiaoApiError) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tif (error instanceof Error) {\n\t\t\t\tif (error.name === \"AbortError\") {\n\t\t\t\t\tthrow new CiaoApiError(\"Request timed out\", \"TIMEOUT\", 0);\n\t\t\t\t}\n\t\t\t\tthrow new CiaoApiError(error.message, \"NETWORK_ERROR\", 0);\n\t\t\t}\n\t\t\tthrow new CiaoApiError(\"Unknown error\", \"UNKNOWN\", 0);\n\t\t}\n\t}\n\n\tasync submitBuildSchema(\n\t\tbuildSchema: BuildSchemaRequest,\n\t): Promise<TranslationResponse> {\n\t\treturn this.request<TranslationResponse>(\n\t\t\t\"POST\",\n\t\t\t\"/api/translation/translate-strings\",\n\t\t\t{ buildSchema },\n\t\t);\n\t}\n\n\tasync getJobStatus(jobId: string): Promise<JobStatusResponse> {\n\t\treturn this.request<JobStatusResponse>(\n\t\t\t\"GET\",\n\t\t\t`/api/translation/job/${jobId}`,\n\t\t);\n\t}\n}\n\nexport class CiaoApiError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic code: string,\n\t\tpublic statusCode: number,\n\t\tpublic details?: unknown,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"CiaoApiError\";\n\t}\n}\n","import type { CiaoApiClient } from \"./client\";\nimport type { JobStatusResponse } from \"./types\";\n\nexport interface PollingOptions {\n\tinitialInterval?: number;\n\tmaxInterval?: number;\n\tmaxAttempts?: number;\n\tbackoffMultiplier?: number;\n\tonProgress?: (status: JobStatusResponse) => void;\n}\n\nconst DEFAULT_OPTIONS: Required<Omit<PollingOptions, \"onProgress\">> = {\n\tinitialInterval: 1000,\n\tmaxInterval: 10000,\n\tmaxAttempts: 120,\n\tbackoffMultiplier: 1.5,\n};\n\nexport async function pollJobUntilComplete(\n\tclient: CiaoApiClient,\n\tjobId: string,\n\toptions: PollingOptions = {},\n): Promise<JobStatusResponse> {\n\tconst { initialInterval, maxInterval, maxAttempts, backoffMultiplier } = {\n\t\t...DEFAULT_OPTIONS,\n\t\t...options,\n\t};\n\tconst { onProgress } = options;\n\n\tlet currentInterval = initialInterval;\n\tlet attempts = 0;\n\n\twhile (attempts < maxAttempts) {\n\t\tconst status = await client.getJobStatus(jobId);\n\n\t\tif (onProgress) {\n\t\t\tonProgress(status);\n\t\t}\n\n\t\tif (status.status === \"completed\") {\n\t\t\treturn status;\n\t\t}\n\n\t\tif (status.status === \"failed\") {\n\t\t\tthrow new Error(status.error ?? \"Job failed with unknown error\");\n\t\t}\n\n\t\tawait sleep(currentInterval);\n\t\tcurrentInterval = Math.min(\n\t\t\tcurrentInterval * backoffMultiplier,\n\t\t\tmaxInterval,\n\t\t);\n\t\tattempts++;\n\t}\n\n\tthrow new Error(`Job polling timed out after ${maxAttempts} attempts`);\n}\n\nfunction sleep(ms: number): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import type { ResolvedCiaoConfig } from \"./types\";\n\nexport const DEFAULT_CONFIG: Omit<ResolvedCiaoConfig, \"projectId\"> = {\n\tinclude: [\n\t\t\"src/**/*.{ts,tsx,js,jsx}\",\n\t\t\"app/**/*.{ts,tsx,js,jsx}\",\n\t\t\"pages/**/*.{ts,tsx,js,jsx}\",\n\t\t\"components/**/*.{ts,tsx,js,jsx}\",\n\t],\n\texclude: [\n\t\t\"**/node_modules/**\",\n\t\t\"**/*.test.{ts,tsx,js,jsx}\",\n\t\t\"**/*.spec.{ts,tsx,js,jsx}\",\n\t\t\"**/__tests__/**\",\n\t\t\"**/dist/**\",\n\t\t\"**/.next/**\",\n\t],\n\toutputDir: \"__generated__\",\n\tserverUrl: \"https://server.ciao-tools.com\",\n};\n\nexport const CONFIG_FILE_NAMES = [\n\t\"ciao.config.ts\",\n\t\"ciao.config.js\",\n\t\"ciao.config.mjs\",\n] as const;\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { CONFIG_FILE_NAMES, DEFAULT_CONFIG } from \"./defaults\";\nimport type { CiaoConfig, ResolvedCiaoConfig } from \"./types\";\n\nexport interface LoadConfigOptions {\n\tcwd?: string;\n\tconfigPath?: string;\n}\n\nexport async function loadConfig(\n\toptions: LoadConfigOptions = {},\n): Promise<ResolvedCiaoConfig> {\n\tconst cwd = options.cwd ?? process.cwd();\n\tlet configPath = options.configPath;\n\n\tif (!configPath) {\n\t\tfor (const fileName of CONFIG_FILE_NAMES) {\n\t\t\tconst candidate = path.join(cwd, fileName);\n\t\t\tif (fs.existsSync(candidate)) {\n\t\t\t\tconfigPath = candidate;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!configPath) {\n\t\tthrow new ConfigNotFoundError(\n\t\t\t`No ciao.config.ts found. Run 'ciao init' to create one.`,\n\t\t);\n\t}\n\n\tconst absolutePath = path.isAbsolute(configPath)\n\t\t? configPath\n\t\t: path.join(cwd, configPath);\n\n\tif (!fs.existsSync(absolutePath)) {\n\t\tthrow new ConfigNotFoundError(`Config file not found: ${absolutePath}`);\n\t}\n\n\tconst config = await importConfig(absolutePath);\n\treturn resolveConfig(config, cwd);\n}\n\nasync function importConfig(configPath: string): Promise<CiaoConfig> {\n\ttry {\n\t\t// Use file:// URL for ESM compatibility\n\t\tconst fileUrl = configPath.startsWith(\"file://\")\n\t\t\t? configPath\n\t\t\t: `file://${configPath}`;\n\t\tconst module = await import(fileUrl);\n\t\tconst config = module.default ?? module;\n\n\t\tif (!config || typeof config !== \"object\") {\n\t\t\tthrow new ConfigValidationError(\"Config file must export an object\");\n\t\t}\n\n\t\treturn config as CiaoConfig;\n\t} catch (error) {\n\t\tif (error instanceof ConfigValidationError) {\n\t\t\tthrow error;\n\t\t}\n\t\tif (error instanceof Error) {\n\t\t\tthrow new ConfigValidationError(\n\t\t\t\t`Failed to load config file (${configPath}): ${error.message}`,\n\t\t\t);\n\t\t}\n\t\tthrow new ConfigValidationError(\n\t\t\t`Failed to load config file: ${configPath}`,\n\t\t);\n\t}\n}\n\nfunction resolveConfig(config: CiaoConfig, cwd: string): ResolvedCiaoConfig {\n\tif (!config.projectId) {\n\t\tthrow new ConfigValidationError(\"projectId is required in ciao.config.ts\");\n\t}\n\n\tconst outputDir = config.outputDir ?? DEFAULT_CONFIG.outputDir;\n\tconst resolvedOutputDir = path.isAbsolute(outputDir)\n\t\t? outputDir\n\t\t: path.join(cwd, outputDir);\n\n\treturn {\n\t\tprojectId: config.projectId,\n\t\tstyleId: config.styleId,\n\t\tinclude: config.include ?? DEFAULT_CONFIG.include,\n\t\texclude: config.exclude ?? DEFAULT_CONFIG.exclude,\n\t\toutputDir: resolvedOutputDir,\n\t\tserverUrl: config.serverUrl ?? DEFAULT_CONFIG.serverUrl,\n\t};\n}\n\nexport class ConfigNotFoundError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"ConfigNotFoundError\";\n\t}\n}\n\nexport class ConfigValidationError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"ConfigValidationError\";\n\t}\n}\n","export interface CiaoConfig {\n\tprojectId: string;\n\tstyleId?: string;\n\tinclude?: string[];\n\texclude?: string[];\n\toutputDir?: string;\n\tserverUrl?: string;\n}\n\nexport interface ResolvedCiaoConfig {\n\tprojectId: string;\n\tstyleId?: string;\n\tinclude: string[];\n\texclude: string[];\n\toutputDir: string;\n\tserverUrl: string;\n}\n\nexport function defineCiaoConfig(config: CiaoConfig): CiaoConfig {\n\treturn config;\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { GenerateManifestOptions, ManifestData } from \"./types\";\n\nexport async function generateManifestFile(\n\toptions: GenerateManifestOptions,\n): Promise<string> {\n\tconst { outputDir, data } = options;\n\n\tif (!fs.existsSync(outputDir)) {\n\t\tfs.mkdirSync(outputDir, { recursive: true });\n\t}\n\n\tconst manifestPath = path.join(outputDir, \"ciao-manifest.ts\");\n\tconst content = generateManifestContent(data);\n\n\tfs.writeFileSync(manifestPath, content, \"utf-8\");\n\n\treturn manifestPath;\n}\n\nfunction generateManifestContent(data: ManifestData): string {\n\tconst cdnUrlsEntries = Object.entries(data.cdnUrls)\n\t\t.map(([lang, url]) => `\\t\"${lang}\": \"${url}\"`)\n\t\t.join(\",\\n\");\n\n\tconst languagesArray = data.languages.map((l) => `\"${l}\"`).join(\", \");\n\n\treturn `// This file is auto-generated by ciao-tools. Do not edit manually.\n// Generated at: ${data.generatedAt}\n\nexport const ciaoManifest = {\n\tversion: \"${data.version}\",\n\tprojectId: \"${data.projectId}\",\n\tsourceLanguage: \"${data.sourceLanguage}\",\n\tlanguages: [${languagesArray}] as const,\n\tcdnUrls: {\n${cdnUrlsEntries}\n\t} as const,\n\tgeneratedAt: \"${data.generatedAt}\",\n} as const;\n\nexport type CiaoLanguage = (typeof ciaoManifest.languages)[number];\n\nexport type CiaoManifest = typeof ciaoManifest;\n`;\n}\n\nexport function createManifestData(\n\tprojectId: string,\n\tsourceLanguage: string,\n\tlanguages: string[],\n\tcdnUrls: Record<string, string>,\n\tversion: string,\n): ManifestData {\n\treturn {\n\t\tversion,\n\t\tprojectId,\n\t\tsourceLanguage,\n\t\tlanguages,\n\t\tcdnUrls,\n\t\tgeneratedAt: new Date().toISOString(),\n\t};\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as babel from \"@babel/core\";\nimport { createExtractionPlugin } from \"experimental-ciao-core\";\nimport { glob } from \"glob\";\nimport type {\n\tContextBlock,\n\tExtractionOptions,\n\tProjectExtractionResult,\n\tTranslatableString,\n} from \"./types\";\n\nexport async function extractStringsFromProject(\n\toptions: ExtractionOptions,\n): Promise<ProjectExtractionResult> {\n\tconst cwd = options.cwd ?? process.cwd();\n\tconst allStrings: TranslatableString[] = [];\n\tconst allContextBlocks: ContextBlock[] = [];\n\tlet filesProcessed = 0;\n\n\tconst files = await glob(options.include, {\n\t\tcwd,\n\t\tignore: options.exclude,\n\t\tabsolute: true,\n\t\tnodir: true,\n\t});\n\n\tfor (const filePath of files) {\n\t\tconst result = await extractStringsFromFile(filePath);\n\t\tif (result) {\n\t\t\tmergeStrings(allStrings, result.strings);\n\t\t\tmergeContextBlocks(allContextBlocks, result.contextBlocks);\n\t\t\tfilesProcessed++;\n\t\t}\n\t}\n\n\treturn {\n\t\tstrings: allStrings,\n\t\tcontextBlocks: allContextBlocks,\n\t\tfilesProcessed,\n\t\ttotalStrings: allStrings.length,\n\t};\n}\n\nasync function extractStringsFromFile(\n\tfilePath: string,\n): Promise<{\n\tstrings: TranslatableString[];\n\tcontextBlocks: ContextBlock[];\n} | null> {\n\tconst code = fs.readFileSync(filePath, \"utf-8\");\n\tconst ext = path.extname(filePath);\n\n\tif (![\".ts\", \".tsx\", \".js\", \".jsx\"].includes(ext)) {\n\t\treturn null;\n\t}\n\n\tconst isTypeScript = ext === \".ts\" || ext === \".tsx\";\n\tconst isJSX = ext === \".tsx\" || ext === \".jsx\";\n\n\tlet extractedStrings: TranslatableString[] = [];\n\tlet extractedContextBlocks: ContextBlock[] = [];\n\n\tconst extractionPlugin = createExtractionPlugin({\n\t\tonComplete: (result) => {\n\t\t\textractedStrings = result.strings;\n\t\t\textractedContextBlocks = result.contextBlocks;\n\t\t},\n\t});\n\n\tconst presets: babel.PluginItem[] = [];\n\n\tif (isTypeScript) {\n\t\tpresets.push([\n\t\t\trequire.resolve(\"@babel/preset-typescript\"),\n\t\t\t{ isTSX: isJSX, allExtensions: true },\n\t\t]);\n\t}\n\n\tif (isJSX) {\n\t\tpresets.push([\n\t\t\trequire.resolve(\"@babel/preset-react\"),\n\t\t\t{ runtime: \"automatic\" },\n\t\t]);\n\t}\n\n\ttry {\n\t\tawait babel.transformAsync(code, {\n\t\t\tfilename: filePath,\n\t\t\tpresets,\n\t\t\tplugins: [extractionPlugin],\n\t\t\tbabelrc: false,\n\t\t\tconfigFile: false,\n\t\t});\n\n\t\tif (extractedStrings.length === 0 && extractedContextBlocks.length === 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn {\n\t\t\tstrings: extractedStrings,\n\t\t\tcontextBlocks: extractedContextBlocks,\n\t\t};\n\t} catch (error) {\n\t\tconsole.warn(`[ciao-tools] Warning: Failed to parse ${filePath}:`, error);\n\t\treturn null;\n\t}\n}\n\nfunction mergeStrings(\n\ttarget: TranslatableString[],\n\tsource: TranslatableString[],\n): void {\n\tfor (const str of source) {\n\t\tconst isDuplicate = target.some(\n\t\t\t(s) =>\n\t\t\t\ts.text === str.text &&\n\t\t\t\ts.context === str.context &&\n\t\t\t\ts.parentContextBlockId === str.parentContextBlockId,\n\t\t);\n\t\tif (!isDuplicate) {\n\t\t\ttarget.push(str);\n\t\t}\n\t}\n}\n\nfunction mergeContextBlocks(\n\ttarget: ContextBlock[],\n\tsource: ContextBlock[],\n): void {\n\tfor (const block of source) {\n\t\tconst isDuplicate = target.some((b) => b.id === block.id);\n\t\tif (!isDuplicate) {\n\t\t\ttarget.push(block);\n\t\t}\n\t}\n}\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "experimental-ciao-core",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Core utilities for ciao-tools - API client, config loading, manifest generation, and string extraction",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.mjs",
|
|
8
|
+
"types": "./dist/index.d.mts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.mts",
|
|
12
|
+
"import": "./dist/index.mjs",
|
|
13
|
+
"require": {
|
|
14
|
+
"types": "./dist/index.d.cts",
|
|
15
|
+
"default": "./dist/index.cjs"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsdown",
|
|
24
|
+
"dev": "tsdown --watch",
|
|
25
|
+
"clean": "rm -rf dist",
|
|
26
|
+
"test": "bun test"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"ciao-tools",
|
|
30
|
+
"i18n",
|
|
31
|
+
"translation",
|
|
32
|
+
"core"
|
|
33
|
+
],
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"author": "Ciao Tools",
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "https://github.com/ciao-tools/core.git",
|
|
39
|
+
"directory": "packages/core"
|
|
40
|
+
},
|
|
41
|
+
"homepage": "https://docs.ciao-tools.com",
|
|
42
|
+
"bugs": {
|
|
43
|
+
"url": "https://github.com/ciao-tools/core/issues"
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"experimental-ciao-babel": "workspace:*",
|
|
50
|
+
"glob": "^11.0.0"
|
|
51
|
+
},
|
|
52
|
+
"peerDependencies": {
|
|
53
|
+
"@babel/core": "^7.0.0"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@babel/core": "^7.24.0",
|
|
57
|
+
"@babel/preset-react": "^7.24.0",
|
|
58
|
+
"@babel/preset-typescript": "^7.24.0",
|
|
59
|
+
"@types/babel__core": "^7.20.5"
|
|
60
|
+
}
|
|
61
|
+
}
|