@swiftbrowser/cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +166 -0
  2. package/bin/swiftbrowser.js +11 -0
  3. package/dist/build.d.ts +36 -0
  4. package/dist/build.js +124 -0
  5. package/dist/build.js.map +1 -0
  6. package/dist/cli.d.ts +2 -0
  7. package/dist/cli.js +137 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/commands/build.d.ts +8 -0
  10. package/dist/commands/build.js +33 -0
  11. package/dist/commands/build.js.map +1 -0
  12. package/dist/commands/check.d.ts +4 -0
  13. package/dist/commands/check.js +27 -0
  14. package/dist/commands/check.js.map +1 -0
  15. package/dist/commands/dev.d.ts +19 -0
  16. package/dist/commands/dev.js +83 -0
  17. package/dist/commands/dev.js.map +1 -0
  18. package/dist/commands/doctor.d.ts +12 -0
  19. package/dist/commands/doctor.js +66 -0
  20. package/dist/commands/doctor.js.map +1 -0
  21. package/dist/commands/shared.d.ts +23 -0
  22. package/dist/commands/shared.js +73 -0
  23. package/dist/commands/shared.js.map +1 -0
  24. package/dist/compat.d.ts +27 -0
  25. package/dist/compat.js +111 -0
  26. package/dist/compat.js.map +1 -0
  27. package/dist/config.d.ts +45 -0
  28. package/dist/config.js +70 -0
  29. package/dist/config.js.map +1 -0
  30. package/dist/icu.d.ts +94 -0
  31. package/dist/icu.js +368 -0
  32. package/dist/icu.js.map +1 -0
  33. package/dist/log.d.ts +16 -0
  34. package/dist/log.js +28 -0
  35. package/dist/log.js.map +1 -0
  36. package/dist/project.d.ts +56 -0
  37. package/dist/project.js +264 -0
  38. package/dist/project.js.map +1 -0
  39. package/dist/stage.d.ts +78 -0
  40. package/dist/stage.js +344 -0
  41. package/dist/stage.js.map +1 -0
  42. package/dist/toolchain.d.ts +42 -0
  43. package/dist/toolchain.js +159 -0
  44. package/dist/toolchain.js.map +1 -0
  45. package/package.json +37 -0
package/dist/icu.d.ts ADDED
@@ -0,0 +1,94 @@
1
+ import { type Toolchain } from './toolchain.js';
2
+ export declare const ICU_ARCHIVE = "lib_FoundationICU.a";
3
+ export declare const ICU_MEMBER = "icu_packaged_data.cpp.obj";
4
+ /** The trimmed data package, ready to be assembled into the staged app. */
5
+ export interface ICUData {
6
+ /** The symbol udata.cpp references, `icudt76_dat` for ICU 76. */
7
+ symbol: string;
8
+ /** Absolute path of the trimmed package (little-endian `icudtNNl.dat`). */
9
+ file: string;
10
+ bytes: number;
11
+ items: number;
12
+ originalBytes: number;
13
+ originalItems: number;
14
+ /** The languages kept, normalized; `['*']` when nothing was dropped. */
15
+ languages: string[];
16
+ }
17
+ /** The wasm SDK's `swift_static/wasi` directory, where Foundation's archives are. */
18
+ export declare function wasmStaticLibDir(toolchain: Toolchain, env?: NodeJS.ProcessEnv): string | null;
19
+ /** One member of a static archive. */
20
+ export interface ArchiveMember {
21
+ name: string;
22
+ data: Buffer;
23
+ }
24
+ /** Every member of a (GNU or BSD) `ar` archive, long names resolved. */
25
+ export declare function readArchive(archive: Buffer): ArchiveMember[];
26
+ export declare function archiveMember(archive: Buffer, wanted: string): Buffer | null;
27
+ /** The ICU data: the one data segment of the SDK's packaged-data object, and the symbol naming it. */
28
+ export declare function icuDataFromObject(object: Buffer): {
29
+ symbol: string;
30
+ data: Buffer;
31
+ };
32
+ export interface CmnDItem {
33
+ /** `icudt76l/coll/en.res` */
34
+ name: string;
35
+ data: Buffer;
36
+ }
37
+ export interface CmnDPackage {
38
+ /** The UDataInfo header, copied as is. */
39
+ header: Buffer;
40
+ items: CmnDItem[];
41
+ }
42
+ /**
43
+ * Parses an ICU common-data package: a `UDataInfo` header (its size in the
44
+ * first two bytes, magic da 27), then a table of contents of (nameOffset,
45
+ * dataOffset) pairs relative to the end of the header, the NUL-terminated
46
+ * names, and the items' data in table order.
47
+ */
48
+ export declare function parsePackage(buf: Buffer): CmnDPackage;
49
+ /** Writes a package back: table, names, then each item's data 16-byte aligned. */
50
+ export declare function buildPackage(header: Buffer, items: readonly CmnDItem[]): Buffer;
51
+ /** `en-GB`, `zh_Hant`, `EN` → the language subtag (`en`, `zh`), or `*`. */
52
+ export declare function normalizeLanguage(tag: string): string;
53
+ /**
54
+ * Whether an item stays in the trimmed package. Everything locale-independent
55
+ * stays (break iteration rules, normalization, root collation, time zones,
56
+ * the `pool.res` string pools the kept bundles refer to). Dropped: the
57
+ * resource bundles of other languages (in every directory: locales, coll,
58
+ * curr, lang, region, unit, zone, rbnf, brkitr), transliteration rules, the
59
+ * CJK and south-east-Asian word-break dictionaries, the CJK / phrase / loose /
60
+ * normal line-break rule variants (reached only through the Japanese and
61
+ * Chinese bundles, so they stay with `ja` or `zh`), `unames.icu` (Unicode
62
+ * character names, behind the `\N{…}` regex escape only) and the large
63
+ * legacy multi-byte converters.
64
+ */
65
+ export declare function keepItem(name: string, size: number, languages: ReadonlySet<string>): boolean;
66
+ export interface TrimResult {
67
+ data: Buffer;
68
+ items: number;
69
+ originalItems: number;
70
+ }
71
+ export declare function trimPackage(original: Buffer, languages: readonly string[]): TrimResult;
72
+ /** `['en-GB', 'en', 'fr']` → `['en', 'fr']`; `['*']` or an entry `*` → `['*']`. */
73
+ export declare function normalizeLanguages(languages: readonly string[]): string[];
74
+ export declare function icuCacheDir(): string;
75
+ /**
76
+ * The trimmed ICU package for `languages`, from the cache or freshly made
77
+ * from the wasm SDK's archive (a second or two; cached per SDK archive and
78
+ * language set under `~/.cache/swiftbrowser/icu/`).
79
+ */
80
+ export declare function prepareICUData(toolchain: Toolchain, languages: readonly string[], options?: {
81
+ cache?: string;
82
+ }): ICUData;
83
+ /** The staged C target's directory name (also its SwiftPM target name's root). */
84
+ export declare const ICU_TARGET = "_ICUData";
85
+ /**
86
+ * The assembly source of the staged `_ICUData` target: the trimmed package as
87
+ * the data symbol Foundation's ICU reads, 16-byte aligned like the original.
88
+ * Empty when not building for wasm (a `check` on the host links the host's
89
+ * Foundation), and when no data was prepared.
90
+ */
91
+ export declare function icuAssembly(icu: ICUData | null): string;
92
+ export declare function formatMB(bytes: number): string;
93
+ /** One line for the build log. */
94
+ export declare function describeICUData(icu: ICUData): string;
package/dist/icu.js ADDED
@@ -0,0 +1,368 @@
1
+ // Trimming ICU's locale data for `--foundation full`.
2
+ //
3
+ // The wasm SDK's Foundation links `lib_FoundationICU.a`, whose one data object
4
+ // holds ICU's complete 34 MB data package (`icudtNN_dat`, format "CmnD": a
5
+ // table of contents over some 4,900 items, mostly per-locale resource
6
+ // bundles, collation tables, converters and dictionaries). An app for the
7
+ // browser needs a fraction of it, so the CLI pulls the package out of the
8
+ // SDK's archive, keeps the locale-independent items plus the chosen
9
+ // languages' bundles (about 5.5 MB for English), and makes the trimmed
10
+ // package an object of a C target the staged app depends on. That object
11
+ // defines `icudtNN_dat` before the linker reaches the archive, so the
12
+ // archive's own data member is never pulled in. Nothing in the SDK changes.
13
+ //
14
+ // Everything here is plain parsing: the `ar` archive, the wasm object's data
15
+ // section, and the CmnD table of contents (udata.cpp's layout).
16
+ import { spawnSync } from 'node:child_process';
17
+ import { createHash } from 'node:crypto';
18
+ import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync, writeFileSync } from 'node:fs';
19
+ import { homedir } from 'node:os';
20
+ import path from 'node:path';
21
+ import { CliError } from './log.js';
22
+ import { WASM_SDK, cacheDir, toolchainEnv } from './toolchain.js';
23
+ export const ICU_ARCHIVE = 'lib_FoundationICU.a';
24
+ export const ICU_MEMBER = 'icu_packaged_data.cpp.obj';
25
+ const TRIM_VERSION = 2;
26
+ // ---------------------------------------------------------------------------
27
+ // Locating the SDK's archive
28
+ /** The wasm SDK's `swift_static/wasi` directory, where Foundation's archives are. */
29
+ export function wasmStaticLibDir(toolchain, env = process.env) {
30
+ const shown = spawnSync(toolchain.swift, ['sdk', 'configure', WASM_SDK, 'wasm32-unknown-wasip1', '--show-configuration'], {
31
+ encoding: 'utf8',
32
+ env: toolchainEnv(toolchain, env),
33
+ });
34
+ if (shown.status === 0) {
35
+ const match = /^swiftStaticResourcesPath: (.+)$/m.exec(shown.stdout);
36
+ if (match) {
37
+ const dir = path.join(match[1].trim(), 'wasi');
38
+ if (existsSync(path.join(dir, ICU_ARCHIVE)))
39
+ return dir;
40
+ }
41
+ }
42
+ // The default install location, for an SDK whose configuration is not shown.
43
+ const bundle = path.join(env['SWIFTPM_HOME'] ?? path.join(homedir(), '.swiftpm'), 'swift-sdks', `${WASM_SDK}.artifactbundle`);
44
+ if (existsSync(bundle)) {
45
+ for (const entry of readdirSync(bundle)) {
46
+ const dir = path.join(bundle, entry, 'wasm32-unknown-wasip1', 'swift.xctoolchain', 'usr', 'lib', 'swift_static', 'wasi');
47
+ if (existsSync(path.join(dir, ICU_ARCHIVE)))
48
+ return dir;
49
+ }
50
+ }
51
+ return null;
52
+ }
53
+ /** Every member of a (GNU or BSD) `ar` archive, long names resolved. */
54
+ export function readArchive(archive) {
55
+ if (archive.subarray(0, 8).toString('latin1') !== '!<arch>\n')
56
+ throw new CliError('not an ar archive');
57
+ const members = [];
58
+ let longNames = null;
59
+ let offset = 8;
60
+ while (offset + 60 <= archive.length) {
61
+ const rawName = archive.subarray(offset, offset + 16).toString('latin1');
62
+ const size = Number.parseInt(archive.subarray(offset + 48, offset + 58).toString('latin1').trim(), 10);
63
+ if (!Number.isFinite(size))
64
+ throw new CliError(`corrupt archive member header at ${offset}`);
65
+ let data = archive.subarray(offset + 60, offset + 60 + size);
66
+ let name = rawName.trimEnd();
67
+ if (name === '/' || name === '/SYM64/') {
68
+ // Symbol table.
69
+ name = '';
70
+ }
71
+ else if (name === '//') {
72
+ longNames = data;
73
+ name = '';
74
+ }
75
+ else if (name.startsWith('#1/')) {
76
+ // BSD: the name is the first N bytes of the data.
77
+ const length = Number.parseInt(name.slice(3), 10);
78
+ name = data.subarray(0, length).toString('latin1').replace(/\0+$/, '');
79
+ data = data.subarray(length);
80
+ }
81
+ else if (/^\/\d+$/.test(name)) {
82
+ // GNU: an offset into the long-names table, terminated by "/\n".
83
+ if (!longNames)
84
+ throw new CliError('archive refers to a long-names table it does not have');
85
+ const start = Number.parseInt(name.slice(1), 10);
86
+ let end = start;
87
+ while (end < longNames.length && longNames[end] !== 0x0a)
88
+ end += 1;
89
+ name = longNames.subarray(start, end).toString('latin1').replace(/\/$/, '');
90
+ }
91
+ else {
92
+ name = name.replace(/\/$/, '');
93
+ }
94
+ if (name)
95
+ members.push({ name, data });
96
+ offset += 60 + size + (size % 2);
97
+ }
98
+ return members;
99
+ }
100
+ export function archiveMember(archive, wanted) {
101
+ return readArchive(archive).find((member) => member.name === wanted || member.name.endsWith(`/${wanted}`))?.data ?? null;
102
+ }
103
+ // ---------------------------------------------------------------------------
104
+ // The wasm object holding the data
105
+ function readLeb(buf, pos) {
106
+ let result = 0;
107
+ let shift = 0;
108
+ let byte;
109
+ do {
110
+ byte = buf[pos.at++];
111
+ result += (byte & 0x7f) * 2 ** shift;
112
+ shift += 7;
113
+ } while (byte & 0x80);
114
+ return result;
115
+ }
116
+ /** The ICU data: the one data segment of the SDK's packaged-data object, and the symbol naming it. */
117
+ export function icuDataFromObject(object) {
118
+ if (object.readUInt32LE(0) !== 0x6d736100)
119
+ throw new CliError(`${ICU_MEMBER} is not a wasm object`);
120
+ const symbol = /icudt\d+_dat/.exec(object.toString('latin1'))?.[0];
121
+ if (!symbol)
122
+ throw new CliError(`${ICU_MEMBER} defines no icudtNN_dat symbol`);
123
+ const pos = { at: 8 };
124
+ while (pos.at < object.length) {
125
+ const id = object[pos.at++];
126
+ const size = readLeb(object, pos);
127
+ const end = pos.at + size;
128
+ if (id === 11) {
129
+ const count = readLeb(object, pos);
130
+ for (let i = 0; i < count; i++) {
131
+ const flags = readLeb(object, pos);
132
+ if (flags === 2)
133
+ readLeb(object, pos);
134
+ if (flags !== 1) {
135
+ // Active segment: skip the offset expression (`i32.const n end`).
136
+ while (object[pos.at] !== 0x0b) {
137
+ if (object[pos.at] === 0x41) {
138
+ pos.at += 1;
139
+ readLeb(object, pos);
140
+ }
141
+ else {
142
+ pos.at += 1;
143
+ }
144
+ }
145
+ pos.at += 1;
146
+ }
147
+ const length = readLeb(object, pos);
148
+ const data = object.subarray(pos.at, pos.at + length);
149
+ if (data.subarray(12, 16).toString('latin1') === 'CmnD')
150
+ return { symbol, data };
151
+ pos.at += length;
152
+ }
153
+ }
154
+ pos.at = end;
155
+ }
156
+ throw new CliError(`${ICU_MEMBER} holds no CmnD data segment`);
157
+ }
158
+ /**
159
+ * Parses an ICU common-data package: a `UDataInfo` header (its size in the
160
+ * first two bytes, magic da 27), then a table of contents of (nameOffset,
161
+ * dataOffset) pairs relative to the end of the header, the NUL-terminated
162
+ * names, and the items' data in table order.
163
+ */
164
+ export function parsePackage(buf) {
165
+ const headerSize = buf.readUInt16LE(0);
166
+ if (buf[2] !== 0xda || buf[3] !== 0x27)
167
+ throw new CliError('not an ICU data file');
168
+ const format = buf.subarray(12, 16).toString('latin1');
169
+ if (format !== 'CmnD')
170
+ throw new CliError(`unexpected ICU data format ${JSON.stringify(format)}`);
171
+ const base = headerSize;
172
+ const count = buf.readUInt32LE(base);
173
+ const entries = [];
174
+ for (let i = 0; i < count; i++) {
175
+ const nameOffset = buf.readUInt32LE(base + 4 + i * 8);
176
+ const dataOffset = buf.readUInt32LE(base + 8 + i * 8);
177
+ let end = base + nameOffset;
178
+ while (buf[end] !== 0)
179
+ end += 1;
180
+ entries.push({ name: buf.subarray(base + nameOffset, end).toString('latin1'), dataOffset });
181
+ }
182
+ const items = entries.map((entry, i) => {
183
+ const next = i + 1 < count ? entries[i + 1].dataOffset : buf.length - base;
184
+ return { name: entry.name, data: buf.subarray(base + entry.dataOffset, base + next) };
185
+ });
186
+ return { header: buf.subarray(0, headerSize), items };
187
+ }
188
+ /** Writes a package back: table, names, then each item's data 16-byte aligned. */
189
+ export function buildPackage(header, items) {
190
+ const align = (n) => (n + 15) & ~15;
191
+ const sorted = [...items].sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
192
+ const tableSize = 4 + sorted.length * 8;
193
+ let nameOffset = tableSize;
194
+ const nameOffsets = sorted.map((item) => {
195
+ const at = nameOffset;
196
+ nameOffset += Buffer.byteLength(item.name, 'latin1') + 1;
197
+ return at;
198
+ });
199
+ let dataOffset = align(nameOffset);
200
+ const dataOffsets = sorted.map((item) => {
201
+ const at = dataOffset;
202
+ dataOffset = align(dataOffset + item.data.length);
203
+ return at;
204
+ });
205
+ const out = Buffer.alloc(header.length + dataOffset);
206
+ header.copy(out, 0);
207
+ const base = header.length;
208
+ out.writeUInt32LE(sorted.length, base);
209
+ sorted.forEach((item, i) => {
210
+ out.writeUInt32LE(nameOffsets[i], base + 4 + i * 8);
211
+ out.writeUInt32LE(dataOffsets[i], base + 8 + i * 8);
212
+ out.write(`${item.name}\0`, base + nameOffsets[i], 'latin1');
213
+ item.data.copy(out, base + dataOffsets[i]);
214
+ });
215
+ return out;
216
+ }
217
+ // ---------------------------------------------------------------------------
218
+ // What to keep
219
+ /** `en`, `en_GB`, `sr_Latn_BA`, `es_419`, `en_US_POSIX`: a resource bundle named for a locale. */
220
+ const LOCALE_STEM = /^([a-z]{2,3})(_[A-Z][a-z]{3})?(_[A-Z]{2}|_\d{3})?(_[A-Z0-9]+)*$/;
221
+ /** `en-GB`, `zh_Hant`, `EN` → the language subtag (`en`, `zh`), or `*`. */
222
+ export function normalizeLanguage(tag) {
223
+ const trimmed = tag.trim();
224
+ if (trimmed === '*')
225
+ return '*';
226
+ const match = /^([A-Za-z]{2,3})(?:[-_][A-Za-z0-9]+)*$/.exec(trimmed);
227
+ if (!match)
228
+ throw new CliError(`"${tag}" is not a language tag (like "en", "pt-BR", "zh-Hant"); "*" keeps every locale`);
229
+ return match[1].toLowerCase();
230
+ }
231
+ /**
232
+ * Whether an item stays in the trimmed package. Everything locale-independent
233
+ * stays (break iteration rules, normalization, root collation, time zones,
234
+ * the `pool.res` string pools the kept bundles refer to). Dropped: the
235
+ * resource bundles of other languages (in every directory: locales, coll,
236
+ * curr, lang, region, unit, zone, rbnf, brkitr), transliteration rules, the
237
+ * CJK and south-east-Asian word-break dictionaries, the CJK / phrase / loose /
238
+ * normal line-break rule variants (reached only through the Japanese and
239
+ * Chinese bundles, so they stay with `ja` or `zh`), `unames.icu` (Unicode
240
+ * character names, behind the `\N{…}` regex escape only) and the large
241
+ * legacy multi-byte converters.
242
+ */
243
+ export function keepItem(name, size, languages) {
244
+ if (languages.has('*'))
245
+ return true;
246
+ const parts = name.split('/');
247
+ // `icudt76l/coll/en.res` → dir `coll`, file `en.res`; `icudt76l/root.res` → dir ``.
248
+ const file = parts[parts.length - 1];
249
+ const dir = parts.length > 2 ? parts[1] : '';
250
+ if (dir === 'translit')
251
+ return false;
252
+ if (file.endsWith('.dict'))
253
+ return false;
254
+ if (file === 'unames.icu')
255
+ return false;
256
+ if (dir === 'brkitr' && file.endsWith('.brk') && /_(cj|phrase|loose|normal)\b/.test(file) && !languages.has('ja') && !languages.has('zh'))
257
+ return false;
258
+ if (file.endsWith('.cnv'))
259
+ return size < 16 * 1024;
260
+ if (file.endsWith('.res')) {
261
+ const stem = file.slice(0, -4);
262
+ if (stem === 'root')
263
+ return true;
264
+ const match = LOCALE_STEM.exec(stem);
265
+ if (match)
266
+ return languages.has(match[1]);
267
+ }
268
+ return true;
269
+ }
270
+ export function trimPackage(original, languages) {
271
+ const wanted = new Set(languages.map(normalizeLanguage));
272
+ const pkg = parsePackage(original);
273
+ const kept = pkg.items.filter((item) => keepItem(item.name, item.data.length, wanted));
274
+ return { data: buildPackage(pkg.header, kept), items: kept.length, originalItems: pkg.items.length };
275
+ }
276
+ // ---------------------------------------------------------------------------
277
+ // The cached result and the staged target
278
+ /** `['en-GB', 'en', 'fr']` → `['en', 'fr']`; `['*']` or an entry `*` → `['*']`. */
279
+ export function normalizeLanguages(languages) {
280
+ const normalized = [...new Set(languages.map(normalizeLanguage))].sort();
281
+ return normalized.includes('*') ? ['*'] : normalized;
282
+ }
283
+ export function icuCacheDir() {
284
+ return path.join(cacheDir(), 'icu');
285
+ }
286
+ /**
287
+ * The trimmed ICU package for `languages`, from the cache or freshly made
288
+ * from the wasm SDK's archive (a second or two; cached per SDK archive and
289
+ * language set under `~/.cache/swiftbrowser/icu/`).
290
+ */
291
+ export function prepareICUData(toolchain, languages, options = {}) {
292
+ const libDir = wasmStaticLibDir(toolchain);
293
+ if (!libDir)
294
+ throw new CliError(`cannot find ${ICU_ARCHIVE} in the Swift SDK for WebAssembly (${WASM_SDK}); run \`swiftbrowser doctor\``);
295
+ const archivePath = path.join(libDir, ICU_ARCHIVE);
296
+ const stat = statSync(archivePath);
297
+ const wanted = normalizeLanguages(languages);
298
+ const key = createHash('sha256').update(`${archivePath}|${stat.size}|${stat.mtimeMs}|${wanted.join(',')}|${TRIM_VERSION}`).digest('hex').slice(0, 16);
299
+ const dir = path.join(options.cache ?? icuCacheDir(), key);
300
+ const infoFile = path.join(dir, 'info.json');
301
+ if (existsSync(infoFile)) {
302
+ const info = JSON.parse(readFileSync(infoFile, 'utf8'));
303
+ if (existsSync(info.file) && statSync(info.file).size === info.bytes)
304
+ return info;
305
+ }
306
+ const object = archiveMember(readFileSync(archivePath), ICU_MEMBER);
307
+ if (!object)
308
+ throw new CliError(`${archivePath} has no ${ICU_MEMBER} member; is this the ${WASM_SDK} SDK?`);
309
+ const { symbol, data } = icuDataFromObject(object);
310
+ const trimmed = trimPackage(data, wanted);
311
+ const version = /icudt(\d+)_dat/.exec(symbol)[1];
312
+ mkdirSync(dir, { recursive: true });
313
+ const file = path.join(dir, `icudt${version}l.dat`);
314
+ const partial = `${file}.${process.pid}.tmp`;
315
+ writeFileSync(partial, trimmed.data);
316
+ renameSync(partial, file);
317
+ const info = {
318
+ symbol,
319
+ file,
320
+ bytes: trimmed.data.length,
321
+ items: trimmed.items,
322
+ originalBytes: data.length,
323
+ originalItems: trimmed.originalItems,
324
+ languages: wanted,
325
+ };
326
+ writeFileSync(infoFile, `${JSON.stringify(info, null, 2)}\n`);
327
+ return info;
328
+ }
329
+ /** The staged C target's directory name (also its SwiftPM target name's root). */
330
+ export const ICU_TARGET = '_ICUData';
331
+ /**
332
+ * The assembly source of the staged `_ICUData` target: the trimmed package as
333
+ * the data symbol Foundation's ICU reads, 16-byte aligned like the original.
334
+ * Empty when not building for wasm (a `check` on the host links the host's
335
+ * Foundation), and when no data was prepared.
336
+ */
337
+ export function icuAssembly(icu) {
338
+ const head = [
339
+ '// Generated by @swiftbrowser/cli. The wasm SDK\'s Foundation reads ICU\'s locale',
340
+ '// data from this symbol; defining it here, trimmed to the app\'s languages, keeps',
341
+ '// the SDK\'s 34 MB original out of the module (see @swiftbrowser/cli src/icu.ts).',
342
+ ];
343
+ if (!icu)
344
+ return `${head.join('\n')}\n// No data: this staging was prepared for a host build only.\n`;
345
+ const file = icu.file.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
346
+ return [
347
+ ...head,
348
+ '#ifdef __wasm__',
349
+ `\t.globl\t${icu.symbol}`,
350
+ `\t.section\t.data.${icu.symbol},"",@`,
351
+ '\t.p2align\t4',
352
+ `${icu.symbol}:`,
353
+ `\t.incbin\t"${file}"`,
354
+ `\t.size\t${icu.symbol}, ${icu.bytes}`,
355
+ '#endif',
356
+ '',
357
+ ].join('\n');
358
+ }
359
+ export function formatMB(bytes) {
360
+ return `${(bytes / 1_000_000).toFixed(1)} MB`;
361
+ }
362
+ /** One line for the build log. */
363
+ export function describeICUData(icu) {
364
+ if (icu.languages[0] === '*')
365
+ return `ICU data kept whole (${formatMB(icu.bytes)})`;
366
+ return `ICU data trimmed to ${icu.languages.join(', ')}: ${formatMB(icu.bytes)} of ${formatMB(icu.originalBytes)} (${icu.items} of ${icu.originalItems} items)`;
367
+ }
368
+ //# sourceMappingURL=icu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icu.js","sourceRoot":"","sources":["../src/icu.ts"],"names":[],"mappings":"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"}
package/dist/log.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ export declare const bold: (text: string) => string;
2
+ export declare const dim: (text: string) => string;
3
+ export declare const green: (text: string) => string;
4
+ export declare const red: (text: string) => string;
5
+ export declare const yellow: (text: string) => string;
6
+ export declare const cyan: (text: string) => string;
7
+ export declare const ok: (text: string) => string;
8
+ export declare const bad: (text: string) => string;
9
+ export declare const warn: (text: string) => string;
10
+ export declare function info(message: string): void;
11
+ export declare function error(message: string): void;
12
+ /** A fatal, user-facing problem (printed without a stack trace). */
13
+ export declare class CliError extends Error {
14
+ readonly exitCode: number;
15
+ constructor(message: string, exitCode?: number);
16
+ }
package/dist/log.js ADDED
@@ -0,0 +1,28 @@
1
+ // Minimal console styling for the CLI: colors only when writing to a terminal.
2
+ const tty = process.stdout.isTTY === true && process.env['NO_COLOR'] === undefined;
3
+ const wrap = (open, close = '\x1b[0m') => (text) => (tty ? `${open}${text}${close}` : text);
4
+ export const bold = wrap('\x1b[1m');
5
+ export const dim = wrap('\x1b[2m');
6
+ export const green = wrap('\x1b[32m');
7
+ export const red = wrap('\x1b[31m');
8
+ export const yellow = wrap('\x1b[33m');
9
+ export const cyan = wrap('\x1b[36m');
10
+ export const ok = (text) => `${green('✓')} ${text}`;
11
+ export const bad = (text) => `${red('✗')} ${text}`;
12
+ export const warn = (text) => `${yellow('!')} ${text}`;
13
+ export function info(message) {
14
+ console.log(message);
15
+ }
16
+ export function error(message) {
17
+ console.error(red(message));
18
+ }
19
+ /** A fatal, user-facing problem (printed without a stack trace). */
20
+ export class CliError extends Error {
21
+ exitCode;
22
+ constructor(message, exitCode = 1) {
23
+ super(message);
24
+ this.exitCode = exitCode;
25
+ this.name = 'CliError';
26
+ }
27
+ }
28
+ //# sourceMappingURL=log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAE/E,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,SAAS,CAAC;AACnF,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,KAAK,GAAG,SAAS,EAAE,EAAE,CAAC,CAAC,IAAY,EAAU,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AAEpH,MAAM,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;AACpC,MAAM,CAAC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;AACnC,MAAM,CAAC,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;AACtC,MAAM,CAAC,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;AACpC,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;AACvC,MAAM,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;AAErC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;AACpE,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;AACnE,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;AAEvE,MAAM,UAAU,IAAI,CAAC,OAAe;IAClC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,OAAe;IACnC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;AAC9B,CAAC;AAED,oEAAoE;AACpE,MAAM,OAAO,QAAS,SAAQ,KAAK;IACK;IAAtC,YAAY,OAAe,EAAW,WAAW,CAAC;QAChD,KAAK,CAAC,OAAO,CAAC,CAAC;QADqB,aAAQ,GAAR,QAAQ,CAAI;QAEhD,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF"}
@@ -0,0 +1,56 @@
1
+ import { type FoundationMode, type SwiftLanguageMode } from './config.js';
2
+ export interface ResolvedApp {
3
+ /** Swift module name (`[A-Za-z_][A-Za-z0-9_]*`); also the URL name. */
4
+ name: string;
5
+ displayName: string;
6
+ /** The project directory: `.swiftbrowser/` (staging and build products) lives here. */
7
+ root: string;
8
+ /** Absolute paths of the Swift sources, in build order. */
9
+ sources: string[];
10
+ /** Absolute paths of `*.xcassets` directories. */
11
+ catalogs: string[];
12
+ /** Absolute paths of the resource files and folders `Bundle.main` serves. */
13
+ resources: string[];
14
+ /** A PNG app icon, when one was found. */
15
+ icon?: string;
16
+ swiftLanguageMode: SwiftLanguageMode;
17
+ foundation: FoundationMode;
18
+ /** Languages whose ICU data a full-Foundation build keeps. */
19
+ locales: string[];
20
+ defines: string[];
21
+ /** How the app was found. */
22
+ origin: {
23
+ kind: 'xcodeproj';
24
+ project: string;
25
+ target: string;
26
+ } | {
27
+ kind: 'folder';
28
+ };
29
+ }
30
+ export interface ResolveOptions {
31
+ target?: string;
32
+ configFile?: string;
33
+ foundation?: FoundationMode;
34
+ }
35
+ /** `Guess The Flag` → `GuessTheFlag`; a leading digit gets an underscore. */
36
+ export declare function moduleName(raw: string): string;
37
+ /** Every `.swift` file and `.xcassets` folder under `dir`, by convention. */
38
+ export declare function discoverByConvention(dir: string): {
39
+ sources: string[];
40
+ catalogs: string[];
41
+ };
42
+ /** The largest PNG of the app icon set, for the home-screen manifest. */
43
+ export declare function findAppIcon(catalogs: readonly string[], iconName?: string): string | undefined;
44
+ /** `.xcodeproj` bundles directly in `dir`, else one level down. */
45
+ export declare function xcodeProjectsIn(dir: string): string[];
46
+ /** The Xcode target's copied resources: everything but asset catalogs and compiled resources, in project order. */
47
+ export declare function bundleResources(resources: readonly string[]): string[];
48
+ /** Resolves `input` (an .xcodeproj, a folder with one, or a folder of sources) to an app. */
49
+ export declare function resolveApp(input: string, options?: ResolveOptions): Promise<ResolvedApp>;
50
+ /**
51
+ * The path as it exists on disk when it differs only in case: Xcode projects
52
+ * made on macOS (a case-insensitive disk) may say `BucketList/` for a folder
53
+ * named `Bucketlist/`. Each missing component is matched case-insensitively
54
+ * against its directory; the path comes back unchanged when nothing matches.
55
+ */
56
+ export declare function repairCase(file: string): string;