@arcote.tech/arc-cli 0.3.0 → 0.4.1
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/dist/index.js +18069 -7197
- package/package.json +2 -2
- package/src/builder/module-builder.ts +348 -0
- package/src/commands/platform-build.ts +7 -0
- package/src/commands/platform-dev.ts +116 -0
- package/src/commands/platform-start.ts +56 -0
- package/src/i18n/catalog.ts +204 -0
- package/src/i18n/compile.ts +37 -0
- package/src/i18n/index.ts +77 -0
- package/src/i18n/plugin.ts +55 -0
- package/src/index.ts +24 -1
- package/src/platform/server.ts +353 -0
- package/src/platform/shared.ts +280 -0
- package/src/utils/build.ts +93 -126
- package/src/utils/config.ts +18 -31
package/src/utils/build.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { spawn } from "child_process";
|
|
2
|
-
import { readFileSync } from "fs";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "fs";
|
|
3
3
|
import { dirname, join } from "path";
|
|
4
4
|
import type { ArcConfig, ContextInfo } from "./config";
|
|
5
5
|
import { generateClientTypes } from "./config";
|
|
@@ -23,9 +23,6 @@ export interface BuildTask {
|
|
|
23
23
|
watch: boolean;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
/**
|
|
27
|
-
* Read package.json and extract peer dependencies
|
|
28
|
-
*/
|
|
29
26
|
function getPeerDependencies(configDir: string): string[] {
|
|
30
27
|
try {
|
|
31
28
|
const packageJsonPath = join(configDir, "package.json");
|
|
@@ -36,9 +33,6 @@ function getPeerDependencies(configDir: string): string[] {
|
|
|
36
33
|
}
|
|
37
34
|
}
|
|
38
35
|
|
|
39
|
-
/**
|
|
40
|
-
* Get external dependencies for a specific client
|
|
41
|
-
*/
|
|
42
36
|
function getExternals(
|
|
43
37
|
config: ArcConfig,
|
|
44
38
|
configDir: string,
|
|
@@ -46,27 +40,20 @@ function getExternals(
|
|
|
46
40
|
): string[] {
|
|
47
41
|
const peerDeps = getPeerDependencies(configDir);
|
|
48
42
|
const externals = new Set<string>(peerDeps);
|
|
49
|
-
|
|
50
43
|
if (config.externals?.common) {
|
|
51
44
|
config.externals.common.forEach((ext) => externals.add(ext));
|
|
52
45
|
}
|
|
53
|
-
|
|
54
46
|
const clientExternals =
|
|
55
47
|
config.externals?.[client as keyof typeof config.externals];
|
|
56
48
|
if (Array.isArray(clientExternals)) {
|
|
57
49
|
clientExternals.forEach((ext) => externals.add(ext));
|
|
58
50
|
}
|
|
59
|
-
|
|
60
51
|
return Array.from(externals);
|
|
61
52
|
}
|
|
62
53
|
|
|
63
|
-
/**
|
|
64
|
-
* Build a single context for a specific client
|
|
65
|
-
*/
|
|
66
54
|
export async function buildContext(task: BuildTask): Promise<BuildResult> {
|
|
67
55
|
const startTime = Date.now();
|
|
68
56
|
const { configPath, config, context, client, watch } = task;
|
|
69
|
-
|
|
70
57
|
const result: BuildResult = {
|
|
71
58
|
success: false,
|
|
72
59
|
context: context.name,
|
|
@@ -77,11 +64,8 @@ export async function buildContext(task: BuildTask): Promise<BuildResult> {
|
|
|
77
64
|
};
|
|
78
65
|
|
|
79
66
|
try {
|
|
80
|
-
// Build the JavaScript bundle
|
|
81
67
|
await buildContextBundle(configPath, config, context, client, watch);
|
|
82
68
|
result.jsBuilt = true;
|
|
83
|
-
|
|
84
|
-
// Build declarations
|
|
85
69
|
if (!watch) {
|
|
86
70
|
const declResult = await buildContextDeclarations(
|
|
87
71
|
configPath,
|
|
@@ -92,7 +76,6 @@ export async function buildContext(task: BuildTask): Promise<BuildResult> {
|
|
|
92
76
|
result.declarationsBuilt = declResult.success;
|
|
93
77
|
result.declarationErrors = declResult.errors;
|
|
94
78
|
}
|
|
95
|
-
|
|
96
79
|
result.success = result.jsBuilt;
|
|
97
80
|
result.duration = Date.now() - startTime;
|
|
98
81
|
return result;
|
|
@@ -103,9 +86,6 @@ export async function buildContext(task: BuildTask): Promise<BuildResult> {
|
|
|
103
86
|
}
|
|
104
87
|
}
|
|
105
88
|
|
|
106
|
-
/**
|
|
107
|
-
* Build JavaScript bundle for a context
|
|
108
|
-
*/
|
|
109
89
|
export async function buildContextBundle(
|
|
110
90
|
configPath: string,
|
|
111
91
|
config: ArcConfig,
|
|
@@ -114,66 +94,98 @@ export async function buildContextBundle(
|
|
|
114
94
|
watch: boolean = false,
|
|
115
95
|
): Promise<void> {
|
|
116
96
|
const configDir = dirname(configPath);
|
|
117
|
-
|
|
118
97
|
const defineValues: Record<string, string> = {};
|
|
119
|
-
|
|
120
98
|
for (const c of config.clients) {
|
|
121
99
|
const normalizedC = c.toUpperCase().replace(/[^A-Z0-9]/g, "_");
|
|
122
100
|
defineValues[normalizedC] = c === client ? "true" : "false";
|
|
123
101
|
defineValues[`NOT_ON_${normalizedC}`] = c === client ? "false" : "true";
|
|
124
102
|
defineValues[`ONLY_${normalizedC}`] = c === client ? "true" : "false";
|
|
125
103
|
}
|
|
126
|
-
|
|
127
104
|
const defineArgs = Object.entries(defineValues)
|
|
128
105
|
.map(([key, value]) => `--define="${key}=${value}"`)
|
|
129
106
|
.join(" ");
|
|
130
|
-
|
|
131
107
|
const externals = getExternals(config, configDir, client);
|
|
132
108
|
const externalArgs = externals.map((dep) => `--external=${dep}`).join(" ");
|
|
133
|
-
|
|
134
109
|
const buildTarget = client === "browser" ? "browser" : "bun";
|
|
135
|
-
|
|
110
|
+
// JS output: dist/{client}/{context}/ (matches TypeScript declaration output)
|
|
136
111
|
const outDirPath = join(
|
|
137
112
|
configDir,
|
|
138
113
|
config.outDir,
|
|
139
|
-
context.name,
|
|
140
114
|
client.toLowerCase(),
|
|
115
|
+
context.name,
|
|
141
116
|
);
|
|
142
|
-
|
|
143
117
|
const command = `bun build ${context.fullPath} --target=${buildTarget} --outdir=${outDirPath} ${defineArgs} ${externalArgs}${watch ? " --watch" : ""}`;
|
|
144
118
|
|
|
145
119
|
return new Promise((resolve, reject) => {
|
|
146
120
|
const proc = spawn(command, { shell: true, cwd: configDir });
|
|
147
|
-
|
|
148
121
|
let output = "";
|
|
149
122
|
let errorOutput = "";
|
|
150
|
-
|
|
151
|
-
proc.stdout.on("data", (data) => {
|
|
123
|
+
proc.stdout.on("data", (data: Buffer) => {
|
|
152
124
|
output += data.toString();
|
|
153
125
|
});
|
|
154
|
-
|
|
155
|
-
proc.stderr.on("data", (data) => {
|
|
126
|
+
proc.stderr.on("data", (data: Buffer) => {
|
|
156
127
|
errorOutput += data.toString();
|
|
157
128
|
});
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
if (code !== 0 && !watch) {
|
|
129
|
+
proc.on("close", (code: number) => {
|
|
130
|
+
if (code !== 0 && !watch)
|
|
161
131
|
reject(new Error(`Build failed: ${errorOutput || output}`));
|
|
162
|
-
|
|
163
|
-
resolve();
|
|
164
|
-
}
|
|
132
|
+
else if (!watch) resolve();
|
|
165
133
|
});
|
|
166
134
|
});
|
|
167
135
|
}
|
|
168
136
|
|
|
169
|
-
interface DeclarationResult {
|
|
137
|
+
export interface DeclarationResult {
|
|
170
138
|
success: boolean;
|
|
171
139
|
errors: string[];
|
|
172
140
|
}
|
|
173
141
|
|
|
142
|
+
// ---------------------------------------------------------------------------
|
|
143
|
+
// Core declaration builder — reusable by both old arc.config flow and platform
|
|
144
|
+
// ---------------------------------------------------------------------------
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Build type declarations using tsgo (with tsc fallback).
|
|
148
|
+
*
|
|
149
|
+
* @param files Entry .ts/.tsx files to generate declarations for
|
|
150
|
+
* @param outDir Output directory for .d.ts files
|
|
151
|
+
* @param rootDir Root directory for TypeScript (controls output structure)
|
|
152
|
+
* @param globalsContent Optional ambient declarations (ONLY_SERVER etc.) —
|
|
153
|
+
* written to a temp .d.ts and included in compilation.
|
|
154
|
+
*/
|
|
155
|
+
export async function buildTypeDeclarations(
|
|
156
|
+
files: string[],
|
|
157
|
+
outDir: string,
|
|
158
|
+
rootDir: string,
|
|
159
|
+
globalsContent?: string,
|
|
160
|
+
): Promise<DeclarationResult> {
|
|
161
|
+
const allFiles = [...files];
|
|
162
|
+
|
|
163
|
+
// Write temp globals .d.ts OUTSIDE source dir to avoid triggering file watchers
|
|
164
|
+
let globalsPath: string | null = null;
|
|
165
|
+
if (globalsContent) {
|
|
166
|
+
const tmpDir = join(outDir, "_build-types");
|
|
167
|
+
mkdirSync(tmpDir, { recursive: true });
|
|
168
|
+
globalsPath = join(tmpDir, "globals.d.ts");
|
|
169
|
+
writeFileSync(globalsPath, globalsContent);
|
|
170
|
+
allFiles.push(globalsPath);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
let result = await runTsgo(allFiles, outDir, rootDir);
|
|
174
|
+
if (result === null) {
|
|
175
|
+
result = await runTsc(allFiles, outDir, rootDir);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Clean up temp globals
|
|
179
|
+
if (globalsPath && existsSync(globalsPath)) {
|
|
180
|
+
unlinkSync(globalsPath);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return result;
|
|
184
|
+
}
|
|
185
|
+
|
|
174
186
|
/**
|
|
175
|
-
* Build declarations
|
|
176
|
-
*
|
|
187
|
+
* Build declarations (old arc.config flow).
|
|
188
|
+
* Output: dist/{client}/{context}/ (matches JS output and TypeScript's natural output)
|
|
177
189
|
*/
|
|
178
190
|
export async function buildContextDeclarations(
|
|
179
191
|
configPath: string,
|
|
@@ -182,61 +194,47 @@ export async function buildContextDeclarations(
|
|
|
182
194
|
client: string,
|
|
183
195
|
): Promise<DeclarationResult> {
|
|
184
196
|
const configDir = dirname(configPath);
|
|
185
|
-
|
|
186
|
-
// Generate client types
|
|
187
197
|
generateClientTypes(config, configDir, client);
|
|
188
198
|
|
|
189
|
-
const outDir = join(
|
|
190
|
-
configDir,
|
|
191
|
-
config.outDir,
|
|
192
|
-
context.name,
|
|
193
|
-
client.toLowerCase(),
|
|
194
|
-
);
|
|
199
|
+
const outDir = join(configDir, config.outDir, client.toLowerCase());
|
|
195
200
|
|
|
196
|
-
//
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
+
// Include arc.d.ts for global constants
|
|
202
|
+
const arcTypesPath = join(configDir, "arc.d.ts");
|
|
203
|
+
const files = existsSync(arcTypesPath)
|
|
204
|
+
? [context.fullPath, arcTypesPath]
|
|
205
|
+
: [context.fullPath];
|
|
201
206
|
|
|
202
|
-
|
|
203
|
-
|
|
207
|
+
let result = await runTsgo(files, outDir, configDir);
|
|
208
|
+
if (result === null) {
|
|
209
|
+
result = await runTsc(files, outDir, configDir);
|
|
210
|
+
}
|
|
211
|
+
return result;
|
|
204
212
|
}
|
|
205
213
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
214
|
+
// ---------------------------------------------------------------------------
|
|
215
|
+
// tsgo / tsc runners
|
|
216
|
+
// ---------------------------------------------------------------------------
|
|
217
|
+
|
|
210
218
|
async function runTsgo(
|
|
211
|
-
|
|
219
|
+
files: string[],
|
|
212
220
|
outDir: string,
|
|
213
221
|
cwd: string,
|
|
214
222
|
): Promise<DeclarationResult | null> {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
// --ignoreConfig to skip tsconfig.json when files are specified on command line
|
|
218
|
-
const command = `npx tsgo --declaration --emitDeclarationOnly --outDir "${outDir}" --skipLibCheck --moduleResolution bundler --module esnext --target esnext --ignoreConfig "${entryFile}"`;
|
|
223
|
+
const fileArgs = files.map((f) => `"${f}"`).join(" ");
|
|
224
|
+
const command = `npx tsgo ${fileArgs} --declaration --emitDeclarationOnly --outDir "${outDir}" --rootDir "${cwd}" --skipLibCheck --moduleResolution bundler --module esnext --target esnext --jsx react-jsx --ignoreConfig`;
|
|
219
225
|
|
|
226
|
+
return new Promise((resolve) => {
|
|
220
227
|
const proc = spawn(command, { shell: true, cwd });
|
|
221
|
-
|
|
222
228
|
let output = "";
|
|
223
229
|
let errorOutput = "";
|
|
224
|
-
|
|
225
|
-
proc.stdout.on("data", (data) => {
|
|
230
|
+
proc.stdout.on("data", (data: Buffer) => {
|
|
226
231
|
output += data.toString();
|
|
227
232
|
});
|
|
228
|
-
|
|
229
|
-
proc.stderr.on("data", (data) => {
|
|
233
|
+
proc.stderr.on("data", (data: Buffer) => {
|
|
230
234
|
errorOutput += data.toString();
|
|
231
235
|
});
|
|
232
|
-
|
|
233
|
-
proc.on("
|
|
234
|
-
// tsgo not available
|
|
235
|
-
resolve(null);
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
proc.on("close", (code) => {
|
|
239
|
-
// Check if tsgo was not found
|
|
236
|
+
proc.on("error", () => resolve(null));
|
|
237
|
+
proc.on("close", (code: number) => {
|
|
240
238
|
if (
|
|
241
239
|
errorOutput.includes("not found") ||
|
|
242
240
|
errorOutput.includes("ENOENT") ||
|
|
@@ -245,64 +243,40 @@ async function runTsgo(
|
|
|
245
243
|
resolve(null);
|
|
246
244
|
return;
|
|
247
245
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
const errors = parseTypeScriptErrors(allOutput, cwd);
|
|
251
|
-
|
|
252
|
-
resolve({
|
|
253
|
-
success: code === 0 && errors.length === 0,
|
|
254
|
-
errors,
|
|
255
|
-
});
|
|
246
|
+
const errors = parseTypeScriptErrors(output + errorOutput, cwd);
|
|
247
|
+
resolve({ success: code === 0 && errors.length === 0, errors });
|
|
256
248
|
});
|
|
257
249
|
});
|
|
258
250
|
}
|
|
259
251
|
|
|
260
|
-
/**
|
|
261
|
-
* Run tsc CLI for declaration generation (fallback)
|
|
262
|
-
*/
|
|
263
252
|
async function runTsc(
|
|
264
|
-
|
|
253
|
+
files: string[],
|
|
265
254
|
outDir: string,
|
|
266
255
|
cwd: string,
|
|
267
256
|
): Promise<DeclarationResult> {
|
|
268
|
-
|
|
269
|
-
|
|
257
|
+
const fileArgs = files.map((f) => `"${f}"`).join(" ");
|
|
258
|
+
const command = `npx tsc ${fileArgs} --declaration --emitDeclarationOnly --outDir "${outDir}" --rootDir "${cwd}" --skipLibCheck --moduleResolution bundler --module esnext --target esnext --jsx react-jsx`;
|
|
270
259
|
|
|
260
|
+
return new Promise((resolve) => {
|
|
271
261
|
const proc = spawn(command, { shell: true, cwd });
|
|
272
|
-
|
|
273
262
|
let output = "";
|
|
274
263
|
let errorOutput = "";
|
|
275
|
-
|
|
276
|
-
proc.stdout.on("data", (data) => {
|
|
264
|
+
proc.stdout.on("data", (data: Buffer) => {
|
|
277
265
|
output += data.toString();
|
|
278
266
|
});
|
|
279
|
-
|
|
280
|
-
proc.stderr.on("data", (data) => {
|
|
267
|
+
proc.stderr.on("data", (data: Buffer) => {
|
|
281
268
|
errorOutput += data.toString();
|
|
282
269
|
});
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
const errors = parseTypeScriptErrors(allOutput, cwd);
|
|
287
|
-
|
|
288
|
-
resolve({
|
|
289
|
-
success: code === 0 && errors.length === 0,
|
|
290
|
-
errors,
|
|
291
|
-
});
|
|
270
|
+
proc.on("close", (code: number) => {
|
|
271
|
+
const errors = parseTypeScriptErrors(output + errorOutput, cwd);
|
|
272
|
+
resolve({ success: code === 0 && errors.length === 0, errors });
|
|
292
273
|
});
|
|
293
274
|
});
|
|
294
275
|
}
|
|
295
276
|
|
|
296
|
-
/**
|
|
297
|
-
* Parse TypeScript CLI error output into structured errors
|
|
298
|
-
*/
|
|
299
277
|
function parseTypeScriptErrors(output: string, cwd: string): string[] {
|
|
300
278
|
const errors: string[] = [];
|
|
301
|
-
const
|
|
302
|
-
|
|
303
|
-
for (const line of lines) {
|
|
304
|
-
// Match TypeScript error format: file(line,col): error TS1234: message
|
|
305
|
-
// or: file:line:col - error TS1234: message
|
|
279
|
+
for (const line of output.split("\n")) {
|
|
306
280
|
const match = line.match(
|
|
307
281
|
/^(.+?)(?:\((\d+),(\d+)\)|:(\d+):(\d+))\s*[-:]\s*error\s+TS\d+:\s*(.+)$/,
|
|
308
282
|
);
|
|
@@ -310,33 +284,28 @@ function parseTypeScriptErrors(output: string, cwd: string): string[] {
|
|
|
310
284
|
const file = match[1].replace(cwd + "/", "");
|
|
311
285
|
const lineNum = match[2] || match[4];
|
|
312
286
|
const col = match[3] || match[5];
|
|
313
|
-
|
|
314
|
-
errors.push(`${file}:${lineNum}:${col} - ${message}`);
|
|
287
|
+
errors.push(`${file}:${lineNum}:${col} - ${match[6]}`);
|
|
315
288
|
} else if (line.includes("error TS")) {
|
|
316
|
-
// Catch any other error format
|
|
317
289
|
errors.push(line.trim());
|
|
318
290
|
}
|
|
319
291
|
}
|
|
320
|
-
|
|
321
292
|
return errors;
|
|
322
293
|
}
|
|
323
294
|
|
|
324
|
-
// Legacy
|
|
295
|
+
// Legacy
|
|
325
296
|
export async function buildClient(
|
|
326
297
|
configPath: string,
|
|
327
298
|
config: ArcConfig,
|
|
328
299
|
client: string,
|
|
329
|
-
watch
|
|
300
|
+
watch = false,
|
|
330
301
|
): Promise<void> {
|
|
331
302
|
const configDir = dirname(configPath);
|
|
332
|
-
|
|
333
303
|
if (config.file) {
|
|
334
304
|
const context: ContextInfo = {
|
|
335
305
|
name: "main",
|
|
336
306
|
entryFile: config.file,
|
|
337
307
|
fullPath: join(configDir, config.file),
|
|
338
308
|
};
|
|
339
|
-
|
|
340
309
|
await buildContextBundle(configPath, config, context, client, watch);
|
|
341
310
|
}
|
|
342
311
|
}
|
|
@@ -347,14 +316,12 @@ export async function buildDeclarations(
|
|
|
347
316
|
client: string,
|
|
348
317
|
): Promise<void> {
|
|
349
318
|
const configDir = dirname(configPath);
|
|
350
|
-
|
|
351
319
|
if (config.file) {
|
|
352
320
|
const context: ContextInfo = {
|
|
353
321
|
name: "main",
|
|
354
322
|
entryFile: config.file,
|
|
355
323
|
fullPath: join(configDir, config.file),
|
|
356
324
|
};
|
|
357
|
-
|
|
358
325
|
await buildContextDeclarations(configPath, config, context, client);
|
|
359
326
|
}
|
|
360
327
|
}
|
package/src/utils/config.ts
CHANGED
|
@@ -113,40 +113,29 @@ export function getContextsFromConfig(
|
|
|
113
113
|
|
|
114
114
|
/**
|
|
115
115
|
* Generate base types file for TypeScript intellisense
|
|
116
|
-
* This creates a file with all constants defined as boolean type
|
|
116
|
+
* This creates a .d.ts file with all constants defined as boolean type
|
|
117
117
|
*/
|
|
118
118
|
export function generateBaseTypes(config: ArcConfig, configDir: string): void {
|
|
119
119
|
const { clients } = config;
|
|
120
120
|
|
|
121
|
-
//
|
|
122
|
-
|
|
123
|
-
if (!existsSync(arcDir)) {
|
|
124
|
-
mkdirSync(arcDir, { recursive: true });
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Generate types.ts file with boolean declarations for IDE support
|
|
128
|
-
let typesDefs = `declare global {\n`;
|
|
121
|
+
// Generate ambient declarations (no export {} so they're truly global)
|
|
122
|
+
let typesDefs = "";
|
|
129
123
|
|
|
130
124
|
clients.forEach((client) => {
|
|
131
125
|
const normalizedClient = normalizeClientName(client);
|
|
132
126
|
|
|
133
|
-
typesDefs += `
|
|
134
|
-
typesDefs += `
|
|
135
|
-
typesDefs += `
|
|
127
|
+
typesDefs += `declare const ${normalizedClient}: boolean;\n`;
|
|
128
|
+
typesDefs += `declare const NOT_ON_${normalizedClient}: boolean;\n`;
|
|
129
|
+
typesDefs += `declare const ONLY_${normalizedClient}: boolean;\n`;
|
|
136
130
|
});
|
|
137
131
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
writeFileSync(join(arcDir, "types.ts"), typesDefs);
|
|
141
|
-
|
|
142
|
-
// Also generate arc.types.ts in root for backward compatibility
|
|
143
|
-
// Only generate at root level - contexts should reference the root file
|
|
144
|
-
writeFileSync(join(configDir, "arc.types.ts"), typesDefs);
|
|
132
|
+
// Write as .d.ts file in the config directory for proper TypeScript pickup
|
|
133
|
+
writeFileSync(join(configDir, "arc.d.ts"), typesDefs);
|
|
145
134
|
}
|
|
146
135
|
|
|
147
136
|
/**
|
|
148
137
|
* Generate client-specific types file for a build
|
|
149
|
-
* This creates a file with concrete true/false values based on the current client
|
|
138
|
+
* This creates a .d.ts file with concrete true/false values based on the current client
|
|
150
139
|
*/
|
|
151
140
|
export function generateClientTypes(
|
|
152
141
|
config: ArcConfig,
|
|
@@ -154,33 +143,31 @@ export function generateClientTypes(
|
|
|
154
143
|
client: string,
|
|
155
144
|
): string {
|
|
156
145
|
const { clients } = config;
|
|
157
|
-
const arcDir = join(configDir, ".arc");
|
|
158
146
|
|
|
159
|
-
// Create client-
|
|
147
|
+
// Create .arc/client-types directory
|
|
148
|
+
const arcDir = join(configDir, ".arc");
|
|
160
149
|
const clientTypesDir = join(arcDir, "client-types");
|
|
161
150
|
if (!existsSync(clientTypesDir)) {
|
|
162
151
|
mkdirSync(clientTypesDir, { recursive: true });
|
|
163
152
|
}
|
|
164
153
|
|
|
165
|
-
// Generate client-specific
|
|
166
|
-
let typesDefs =
|
|
154
|
+
// Generate client-specific ambient declarations
|
|
155
|
+
let typesDefs = "";
|
|
167
156
|
|
|
168
157
|
clients.forEach((c) => {
|
|
169
158
|
const normalizedC = normalizeClientName(c);
|
|
170
159
|
const isCurrentClient = normalizeClientName(client) === normalizedC;
|
|
171
160
|
|
|
172
161
|
// Set concrete values based on the current client
|
|
173
|
-
typesDefs += `
|
|
174
|
-
typesDefs += `
|
|
175
|
-
typesDefs += `
|
|
162
|
+
typesDefs += `declare const ${normalizedC}: ${isCurrentClient ? "true" : "false"};\n`;
|
|
163
|
+
typesDefs += `declare const NOT_ON_${normalizedC}: ${isCurrentClient ? "false" : "true"};\n`;
|
|
164
|
+
typesDefs += `declare const ONLY_${normalizedC}: ${isCurrentClient ? "true" : "false"};\n`;
|
|
176
165
|
});
|
|
177
166
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
// Write to a client-specific file
|
|
167
|
+
// Write as .d.ts file
|
|
181
168
|
const typesPath = join(
|
|
182
169
|
clientTypesDir,
|
|
183
|
-
`${normalizeClientName(client).toLowerCase()}.ts`,
|
|
170
|
+
`${normalizeClientName(client).toLowerCase()}.d.ts`,
|
|
184
171
|
);
|
|
185
172
|
writeFileSync(typesPath, typesDefs);
|
|
186
173
|
|