@lucent-lang/lucent 0.0.4

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 (125) hide show
  1. package/app.plugin.js +92 -0
  2. package/bin/lucent.cjs +16 -0
  3. package/core/index.cjs +11 -0
  4. package/dist/bench-CR3E7e2e.js +304 -0
  5. package/dist/build-CAIrRSYA.js +7 -0
  6. package/dist/build-check-QozuNJm5.js +92 -0
  7. package/dist/check-1SCmYlqA.js +7 -0
  8. package/dist/clean-BVwpbJ5K.js +35 -0
  9. package/dist/cli.js +406 -0
  10. package/dist/codes-CIuwXt1S.js +260 -0
  11. package/dist/compiler.js +4 -0
  12. package/dist/confirm-BYF5eY3q.js +34 -0
  13. package/dist/dashboard-B-NzjjaN.js +91 -0
  14. package/dist/dev-BYWMP7oC.js +221 -0
  15. package/dist/diagnostic-BM9sXmwl.js +30 -0
  16. package/dist/diff-BTDo3Sro.js +44 -0
  17. package/dist/doctor-C0PrfWT6.js +230 -0
  18. package/dist/doctor-DdR4JnVc.js +30 -0
  19. package/dist/explain--vV1oaRl.js +35 -0
  20. package/dist/format-D9fnIMEx.js +53 -0
  21. package/dist/init-gIabu1S_.js +207 -0
  22. package/dist/live-steps-BGcWFM9M.js +79 -0
  23. package/dist/new-module-C2mtb0op.js +66 -0
  24. package/dist/package-manager-BnxwCySi.js +30 -0
  25. package/dist/package.json +3 -0
  26. package/dist/packages-HyskKIsY.js +150 -0
  27. package/dist/pipeline-CH7-2cxu.js +232 -0
  28. package/dist/project-D8tEet0k.js +150 -0
  29. package/dist/sdk-coverage-BoW_3Efd.js +64 -0
  30. package/dist/sdk-prefetch-mo04JDZV.js +89 -0
  31. package/dist/sdk-search-Iv4K3-8a.js +124 -0
  32. package/dist/sdk-show-CkrdlqlP.js +74 -0
  33. package/dist/sdks-Xoyiy2E4.js +28 -0
  34. package/dist/src-BD7f1_aZ.js +11493 -0
  35. package/dist/steps--_h-FFS7.js +24 -0
  36. package/dist/theme-uv5bc0aK.js +134 -0
  37. package/dist/tsconfig-S4uyLNzf.js +59 -0
  38. package/dist/version-bqpIO5sP.js +26 -0
  39. package/gradle/lucent-classpath.gradle +38 -0
  40. package/gradle/lucent-classpath.init.gradle +6 -0
  41. package/gradle/lucent.gradle +24 -0
  42. package/lib/core.cjs +106 -0
  43. package/lib/globals.d.ts +36 -0
  44. package/lib/sdk/android.d.ts +8 -0
  45. package/lib/sdk/core.d.ts +23 -0
  46. package/lib/sdk/ios.d.ts +33 -0
  47. package/lib/sdk/platform.d.ts +8 -0
  48. package/lib/sdk/thread.d.ts +8 -0
  49. package/metro/index.cjs +72 -0
  50. package/metro/index.d.ts +6 -0
  51. package/metro/transformer.cjs +70 -0
  52. package/package.json +61 -0
  53. package/runtime/cpp/lucent/abort.cpp +61 -0
  54. package/runtime/cpp/lucent/abort.h +54 -0
  55. package/runtime/cpp/lucent/array.h +442 -0
  56. package/runtime/cpp/lucent/async.h +236 -0
  57. package/runtime/cpp/lucent/builtins.cpp +163 -0
  58. package/runtime/cpp/lucent/bytes.h +129 -0
  59. package/runtime/cpp/lucent/console.h +17 -0
  60. package/runtime/cpp/lucent/core.h +129 -0
  61. package/runtime/cpp/lucent/date.cpp +441 -0
  62. package/runtime/cpp/lucent/date.h +82 -0
  63. package/runtime/cpp/lucent/equality.h +87 -0
  64. package/runtime/cpp/lucent/function.h +61 -0
  65. package/runtime/cpp/lucent/generator.h +244 -0
  66. package/runtime/cpp/lucent/helpers.h +226 -0
  67. package/runtime/cpp/lucent/jserror.cpp +51 -0
  68. package/runtime/cpp/lucent/jserror.h +66 -0
  69. package/runtime/cpp/lucent/jsi/convert.cpp +202 -0
  70. package/runtime/cpp/lucent/jsi/convert.h +612 -0
  71. package/runtime/cpp/lucent/jsi/host.cpp +322 -0
  72. package/runtime/cpp/lucent/jsi/host.h +166 -0
  73. package/runtime/cpp/lucent/json.cpp +243 -0
  74. package/runtime/cpp/lucent/json.h +164 -0
  75. package/runtime/cpp/lucent/json_parse.h +138 -0
  76. package/runtime/cpp/lucent/jsstring.cpp +874 -0
  77. package/runtime/cpp/lucent/jsstring.h +152 -0
  78. package/runtime/cpp/lucent/lucent.h +24 -0
  79. package/runtime/cpp/lucent/map.h +344 -0
  80. package/runtime/cpp/lucent/native.cpp +76 -0
  81. package/runtime/cpp/lucent/native.h +116 -0
  82. package/runtime/cpp/lucent/number.cpp +545 -0
  83. package/runtime/cpp/lucent/number.h +190 -0
  84. package/runtime/cpp/lucent/ops.h +165 -0
  85. package/runtime/cpp/lucent/platform/android.cpp +437 -0
  86. package/runtime/cpp/lucent/platform/android.h +117 -0
  87. package/runtime/cpp/lucent/platform/ios.h +297 -0
  88. package/runtime/cpp/lucent/platform/ios.mm +31 -0
  89. package/runtime/cpp/lucent/regexp.cpp +440 -0
  90. package/runtime/cpp/lucent/regexp.h +107 -0
  91. package/runtime/cpp/lucent/scheduler.cpp +153 -0
  92. package/runtime/cpp/lucent/scheduler.h +160 -0
  93. package/runtime/cpp/lucent/unicode_data.inc +4051 -0
  94. package/runtime/cpp/rn/LucentModule.cpp +35 -0
  95. package/runtime/cpp/rn/LucentModule.h +37 -0
  96. package/runtime/cpp/third_party/quickjs/LICENSE +22 -0
  97. package/runtime/cpp/third_party/quickjs/README.md +11 -0
  98. package/runtime/cpp/third_party/quickjs/cutils.c +641 -0
  99. package/runtime/cpp/third_party/quickjs/cutils.h +457 -0
  100. package/runtime/cpp/third_party/quickjs/libregexp-opcode.h +73 -0
  101. package/runtime/cpp/third_party/quickjs/libregexp.c +3448 -0
  102. package/runtime/cpp/third_party/quickjs/libregexp.h +65 -0
  103. package/runtime/cpp/third_party/quickjs/libunicode-table.h +5206 -0
  104. package/runtime/cpp/third_party/quickjs/libunicode.c +2124 -0
  105. package/runtime/cpp/third_party/quickjs/libunicode.h +196 -0
  106. package/runtime/js/index.d.ts +7 -0
  107. package/runtime/js/index.js +60 -0
  108. package/runtime/native/LucentNative.podspec +28 -0
  109. package/runtime/native/android/CMakeLists.txt +51 -0
  110. package/runtime/native/android/build.gradle +22 -0
  111. package/runtime/native/android/include/lucentnative.h +16 -0
  112. package/runtime/native/android/src/main/java/dev/lucent/LucentPackage.java +25 -0
  113. package/runtime/native/android/src/main/java/dev/lucent/NativeProxy.java +132 -0
  114. package/runtime/native/ios/LucentRegistration.mm +23 -0
  115. package/runtime/native/package.json +6 -0
  116. package/runtime/native/react-native.config.js +19 -0
  117. package/runtime/test/jsi/harness.cpp +181 -0
  118. package/schemas/build.schema.json +152 -0
  119. package/schemas/check.schema.json +74 -0
  120. package/schemas/doctor.schema.json +40 -0
  121. package/schemas/lucent.schema.json +43 -0
  122. package/schemas/sdk-prefetch.schema.json +37 -0
  123. package/schemas/sdk-search.schema.json +54 -0
  124. package/ts-plugin/index.d.ts +4 -0
  125. package/ts-plugin/index.js +99 -0
package/app.plugin.js ADDED
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ // Expo config plugin. During `expo prebuild` it runs `lucent build` (so the
3
+ // native package exists before `pod install` / Gradle) and makes sure the app's
4
+ // react-native.config.js links it.
5
+ const fs = require("node:fs");
6
+ const path = require("node:path");
7
+ const { spawnSync } = require("node:child_process");
8
+
9
+ let built = false;
10
+
11
+ function buildOnce(projectRoot) {
12
+ if (built) return;
13
+ built = true;
14
+ const cli = path.join(__dirname, "bin/lucent.cjs");
15
+ // No Gradle during prebuild: android/ is half-written, and a Gradle run would cache it so
16
+ // (autolinking with the template's package). The Gradle task this plugin applies resolves
17
+ // the classpath and builds Android when the app is built.
18
+ const r = spawnSync(process.execPath, [cli, "build", "--root", projectRoot], {
19
+ stdio: "inherit",
20
+ env: { ...process.env, LUCENT_NO_GRADLE: "1" },
21
+ });
22
+ if (r.status !== 0)
23
+ throw new Error("lucent build failed; fix the errors above and run prebuild again");
24
+ const rnConfig = path.join(projectRoot, "react-native.config.js");
25
+ const entry = `"lucent": { root: require("path").join(__dirname, ".lucent", "native") }`;
26
+ const text = fs.existsSync(rnConfig) ? fs.readFileSync(rnConfig, "utf8") : undefined;
27
+ if (text === undefined) {
28
+ fs.writeFileSync(rnConfig, `module.exports = {\n dependencies: {\n ${entry},\n },\n};\n`);
29
+ } else if (text.includes('"lucent-native"')) {
30
+ // Earlier versions named the dependency lucent-native.
31
+ fs.writeFileSync(rnConfig, text.replace('"lucent-native"', '"lucent"'));
32
+ } else if (!/["']lucent["']\s*:/.test(text)) {
33
+ throw new Error(`Add ${entry} to the "dependencies" of react-native.config.js`);
34
+ }
35
+ }
36
+
37
+ /** The line that applies Lucent's Gradle task (gradle/lucent.gradle) in android/app/build.gradle. */
38
+ const GRADLE_LINE = `apply from: new File(new File(["node", "--print", "require.resolve('@lucent-lang/lucent/package.json')"].execute(null, rootDir).text.trim()).parentFile, "gradle/lucent.gradle")`;
39
+
40
+ /**
41
+ * android/app/build.gradle with the Gradle task applied after React
42
+ * Native's plugin (or the last `apply plugin`, or at the top), or
43
+ * undefined when it is applied already.
44
+ */
45
+ function applyGradleTask(text) {
46
+ if (text.includes("gradle/lucent.gradle")) return undefined;
47
+ const lines = text.split("\n");
48
+ const react = lines.findIndex((l) => /^apply plugin: ["']com\.facebook\.react["']/.test(l));
49
+ const lastApply = lines.reduce((at, l, i) => (l.startsWith("apply plugin:") ? i : at), -1);
50
+ const after = react >= 0 ? react : lastApply;
51
+ lines.splice(after + 1, 0, GRADLE_LINE);
52
+ return lines.join("\n");
53
+ }
54
+
55
+ /** Info.plist entries Lucent packages need (their lucent.json), as the last build recorded them. */
56
+ function packagesInfoPlist(projectRoot) {
57
+ const manifest = path.join(projectRoot, ".lucent", "native", "manifest.json");
58
+ if (!fs.existsSync(manifest)) return {};
59
+ return JSON.parse(fs.readFileSync(manifest, "utf8")).infoPlist || {};
60
+ }
61
+
62
+ function withLucent(config) {
63
+ const { withAppBuildGradle, withDangerousMod, withInfoPlist } = require("expo/config-plugins");
64
+ // Gradle builds run lucent build first, like `lucent init` sets up in bare apps.
65
+ config = withAppBuildGradle(config, (c) => {
66
+ if (c.modResults.language === "groovy")
67
+ c.modResults.contents = applyGradleTask(c.modResults.contents) ?? c.modResults.contents;
68
+ return c;
69
+ });
70
+ // Keys the app sets itself win.
71
+ config = withInfoPlist(config, (c) => {
72
+ buildOnce(c.modRequest.projectRoot);
73
+ for (const [key, { value }] of Object.entries(packagesInfoPlist(c.modRequest.projectRoot))) {
74
+ if (c.modResults[key] === undefined) c.modResults[key] = value;
75
+ }
76
+ return c;
77
+ });
78
+ for (const platform of ["ios", "android"]) {
79
+ config = withDangerousMod(config, [
80
+ platform,
81
+ async (c) => {
82
+ buildOnce(c.modRequest.projectRoot);
83
+ return c;
84
+ },
85
+ ]);
86
+ }
87
+ return config;
88
+ }
89
+
90
+ module.exports = withLucent;
91
+ module.exports.GRADLE_LINE = GRADLE_LINE;
92
+ module.exports.applyGradleTask = applyGradleTask;
package/bin/lucent.cjs ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ // Runs the bundled CLI, both when installed and in this repository, where
4
+ // `pnpm build` (or the watching `dev` task) keeps dist/ current.
5
+ const fs = require("node:fs");
6
+ const path = require("node:path");
7
+ const { pathToFileURL } = require("node:url");
8
+
9
+ const dist = path.join(__dirname, "../dist/cli.js");
10
+ if (!fs.existsSync(dist)) {
11
+ process.stderr.write(
12
+ "lucent: dist/cli.js is missing; run `pnpm build` in the repository first\n",
13
+ );
14
+ process.exit(1);
15
+ }
16
+ import(pathToFileURL(dist).href);
package/core/index.cjs ADDED
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ // lucent:core's JavaScript implementation, for tests that run Lucent modules
3
+ // as plain TypeScript: point Jest's moduleNameMapper or Vitest's alias for
4
+ // `lucent:core` here. Installed packages ship it as lib/core.cjs (copied by
5
+ // the package build, vite.config.ts); in this repository it is the
6
+ // compiler's source.
7
+ const fs = require("node:fs");
8
+ const path = require("node:path");
9
+
10
+ const inRepository = fs.existsSync(path.join(__dirname, "../src"));
11
+ module.exports = require(inRepository ? "../../compiler/lib/core.cjs" : "../lib/core.cjs");
@@ -0,0 +1,304 @@
1
+ import { d as coreJsPath, g as projectFiles, m as moduleNameOf, n as compile, s as runtimeDir } from "./src-BD7f1_aZ.js";
2
+ import { i as table } from "./format-D9fnIMEx.js";
3
+ import { t as renderDiagnostic } from "./diagnostic-BM9sXmwl.js";
4
+ import fs from "node:fs";
5
+ import path from "node:path";
6
+ import os from "node:os";
7
+ import ts from "typescript";
8
+ import { spawn, spawnSync } from "node:child_process";
9
+ import { createHash } from "node:crypto";
10
+ //#region ../runtime/test/sources.ts
11
+ function runtimeSources(cppDir) {
12
+ const list = (dir, ext) => fs.readdirSync(path.join(cppDir, dir)).filter((f) => f.endsWith(ext)).map((f) => path.join(cppDir, dir, f));
13
+ return {
14
+ cxx: [...list("lucent", ".cpp"), ...list("lucent/jsi", ".cpp")],
15
+ c: list("third_party/quickjs", ".c")
16
+ };
17
+ }
18
+ const cFlags = [
19
+ "-std=c11",
20
+ "-O2",
21
+ "-w"
22
+ ];
23
+ const hostLibs = process.platform === "darwin" ? ["-framework", "CoreFoundation"] : [];
24
+ //#endregion
25
+ //#region src/cli/commands/bench.ts
26
+ const HERMES_FIX = "lucent bench runs your modules in a desktop Hermes: build one (git clone https://github.com/facebook/hermes ~/hermes && cmake -S ~/hermes -B ~/hermes/build -G Ninja -DCMAKE_BUILD_TYPE=Release && ninja -C ~/hermes/build hermesvm jsi), or point HERMES_DIR at a build";
27
+ async function run({ root, out }) {
28
+ const t = out.theme;
29
+ const fail = (message) => {
30
+ if (out.json) out.data({
31
+ ok: false,
32
+ error: message
33
+ });
34
+ else out.error(`${t.error(t.symbols.fail)} ${message}`);
35
+ return 1;
36
+ };
37
+ const benches = findBenches(root);
38
+ if (!benches.length) return fail("no *.bench.ts file: next to a module, export default { name: () => call(), … }");
39
+ const hermes = process.env.HERMES_DIR || path.join(os.homedir(), "hermes");
40
+ if (!fs.existsSync(path.join(hermes, "build/lib")) || !fs.existsSync(path.join(hermes, "API/jsi"))) return fail(`no Hermes build at ${hermes}. ${HERMES_FIX}`);
41
+ const files = projectFiles(root);
42
+ const result = compile(files, { platforms: ["host"] });
43
+ if (!result.ok) {
44
+ for (const d of result.diagnostics) out.error(renderDiagnostic({
45
+ ...d,
46
+ file: d.file && path.relative(root, d.file)
47
+ }, d.file && fs.existsSync(d.file) ? fs.readFileSync(d.file, "utf8") : void 0, t));
48
+ return 1;
49
+ }
50
+ const work = path.join(root, ".lucent/bench");
51
+ const generated = path.join(work, "generated");
52
+ fs.rmSync(generated, {
53
+ recursive: true,
54
+ force: true
55
+ });
56
+ for (const [name, content] of result.files) {
57
+ const file = path.join(generated, name.replace(/^host\//, ""));
58
+ fs.mkdirSync(path.dirname(file), { recursive: true });
59
+ fs.writeFileSync(file, content);
60
+ }
61
+ if (!out.json) out.print(t.dim("building the native host (the first run compiles the runtime)…"));
62
+ const exe = await buildHost(work, generated, hermes);
63
+ const script = path.join(work, "bench.js");
64
+ fs.writeFileSync(script, benchScript(root, files, benches, result.proxies));
65
+ const r = spawnSync(exe, [script], {
66
+ encoding: "utf8",
67
+ timeout: 6e5,
68
+ maxBuffer: 64 << 20
69
+ });
70
+ if (r.status !== 0) return fail(`the benchmark failed:\n${r.stderr || r.stdout}`);
71
+ const cases = r.stdout.trim().split("\n").filter((l) => l.startsWith("{")).map((l) => {
72
+ const c = JSON.parse(l);
73
+ return {
74
+ ...c,
75
+ speedup: c.error ? 0 : c.js / c.native
76
+ };
77
+ });
78
+ if (out.json) {
79
+ out.data({
80
+ ok: cases.every((c) => c.same && !c.error),
81
+ cases
82
+ });
83
+ return cases.every((c) => c.same && !c.error) ? 0 : 1;
84
+ }
85
+ const time = (ms) => ms < 1 ? `${(ms * 1e3).toFixed(1)} µs` : `${ms.toFixed(ms < 10 ? 2 : 1)} ms`;
86
+ const row = (c) => c.error ? [
87
+ c.name,
88
+ t.error(c.error),
89
+ "",
90
+ ""
91
+ ] : [
92
+ c.name,
93
+ time(c.js),
94
+ time(c.native),
95
+ `${c.speedup >= 1 ? t.success(`${c.speedup.toFixed(1)}x`) : t.warn(`${c.speedup.toFixed(1)}x`)}${c.same ? "" : t.error(" results differ")}`
96
+ ];
97
+ const lines = table([[
98
+ "CASE",
99
+ "JS",
100
+ "LUCENT",
101
+ "SPEEDUP"
102
+ ].map((h) => t.dim(h)), ...cases.map(row)], 3);
103
+ out.print(`\n${lines[0]}`);
104
+ cases.forEach((c, i) => {
105
+ if (c.file !== cases[i - 1]?.file) out.print(t.bold(c.file));
106
+ out.print(`${lines[i + 1]}`);
107
+ });
108
+ out.print(t.dim("\nper call, best of 5 rounds; desktop Hermes, so devices differ"));
109
+ return cases.every((c) => c.same && !c.error) ? 0 : 1;
110
+ }
111
+ function findBenches(root) {
112
+ const out = [];
113
+ const walk = (dir) => {
114
+ for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
115
+ if (e.name === "node_modules" || e.name.startsWith(".") || e.name === "ios" || e.name === "android") continue;
116
+ const full = path.join(dir, e.name);
117
+ if (e.isDirectory()) walk(full);
118
+ else if (e.name.endsWith(".bench.ts")) out.push(full);
119
+ }
120
+ };
121
+ walk(root);
122
+ return out.sort();
123
+ }
124
+ async function objects(work, sources) {
125
+ const dir = path.join(work, "obj");
126
+ fs.mkdirSync(dir, { recursive: true });
127
+ const jobs = sources.map((s) => {
128
+ const key = createHash("sha256").update(s.cc).update(s.flags.join(" ")).update(s.file).update(fs.readFileSync(s.file)).digest("hex").slice(0, 16);
129
+ return {
130
+ ...s,
131
+ obj: path.join(dir, `${path.basename(s.file).replace(/\.\w+$/, "")}-${key}.o`)
132
+ };
133
+ });
134
+ const todo = jobs.filter((j) => !fs.existsSync(j.obj));
135
+ let next = 0;
136
+ const worker = async () => {
137
+ while (next < todo.length) {
138
+ const j = todo[next++];
139
+ await new Promise((resolve, reject) => {
140
+ const child = spawn(j.cc, [
141
+ ...j.flags,
142
+ "-c",
143
+ j.file,
144
+ "-o",
145
+ `${j.obj}.tmp`
146
+ ], { stdio: [
147
+ "ignore",
148
+ "ignore",
149
+ "pipe"
150
+ ] });
151
+ let err = "";
152
+ child.stderr.on("data", (d) => err += d.toString());
153
+ child.on("error", reject);
154
+ child.on("close", (code) => code === 0 ? (fs.renameSync(`${j.obj}.tmp`, j.obj), resolve()) : reject(/* @__PURE__ */ new Error(`${j.cc} failed on ${j.file}:\n${err}`)));
155
+ });
156
+ }
157
+ };
158
+ await Promise.all(Array.from({ length: Math.max(1, os.availableParallelism() - 1) }, worker));
159
+ return jobs.map((j) => j.obj);
160
+ }
161
+ async function buildHost(work, generated, hermes) {
162
+ const cpp = path.join(runtimeDir(), "cpp");
163
+ const cxx = process.env.CXX ?? "clang++";
164
+ const flags = [
165
+ "-std=c++20",
166
+ "-ffp-contract=off",
167
+ "-O2",
168
+ "-DNDEBUG",
169
+ "-w",
170
+ `-I${cpp}`,
171
+ `-I${generated}`,
172
+ `-I${hermes}/API`,
173
+ `-I${hermes}/API/jsi`,
174
+ `-I${hermes}/public`
175
+ ];
176
+ const rs = runtimeSources(cpp);
177
+ const objs = await objects(work, [
178
+ ...fs.readdirSync(generated).filter((f) => f.endsWith(".cpp")).map((f) => ({
179
+ file: path.join(generated, f),
180
+ cc: cxx,
181
+ flags
182
+ })),
183
+ ...rs.cxx.map((file) => ({
184
+ file,
185
+ cc: cxx,
186
+ flags
187
+ })),
188
+ ...rs.c.map((file) => ({
189
+ file,
190
+ cc: process.env.CC ?? "clang",
191
+ flags: cFlags
192
+ })),
193
+ {
194
+ file: path.join(runtimeDir(), "test/jsi/harness.cpp"),
195
+ cc: cxx,
196
+ flags
197
+ }
198
+ ]);
199
+ const exe = path.join(work, "bench-host");
200
+ const r = spawnSync(cxx, [
201
+ ...objs,
202
+ `-L${hermes}/build/lib`,
203
+ `-L${hermes}/build/jsi`,
204
+ "-lhermesvm",
205
+ "-ljsi",
206
+ "-lpthread",
207
+ ...hostLibs,
208
+ `-Wl,-rpath,${hermes}/build/lib`,
209
+ `-Wl,-rpath,${hermes}/build/jsi`,
210
+ "-o",
211
+ exe
212
+ ], { encoding: "utf8" });
213
+ if (r.status !== 0) throw new Error(`linking the benchmark host failed:\n${r.stderr}`);
214
+ return exe;
215
+ }
216
+ function benchScript(root, files, benches, proxies) {
217
+ const defs = {};
218
+ const jsDeps = {};
219
+ const nativeDeps = {};
220
+ const transpile = (source) => ts.transpileModule(source, { compilerOptions: {
221
+ module: ts.ModuleKind.CommonJS,
222
+ target: ts.ScriptTarget.ES2019,
223
+ esModuleInterop: false
224
+ } }).outputText;
225
+ const loader = fs.readFileSync(path.join(runtimeDir(), "js/index.js"), "utf8");
226
+ defs.core = fs.readFileSync(coreJsPath(), "utf8");
227
+ defs.loader = loader;
228
+ defs["react-native"] = "module.exports = { TurboModuleRegistry: { get: function () { return undefined; } } };";
229
+ const resolve = (from, spec) => {
230
+ if (spec === "lucent:core") return "core";
231
+ if (!spec.startsWith(".")) return void 0;
232
+ const base = path.resolve(path.dirname(from), spec);
233
+ return [
234
+ `${base}.ts`,
235
+ base,
236
+ `${base}.tsx`
237
+ ].find((f) => files.includes(f) || benches.includes(f));
238
+ };
239
+ const specs = (source) => [...source.matchAll(/(?:from|import)\s+["']([^"']+)["']/g)].map((m) => m[1]);
240
+ for (const file of [...files, ...benches]) {
241
+ const source = fs.readFileSync(file, "utf8");
242
+ defs[file] = transpile(source);
243
+ jsDeps[file] = {};
244
+ nativeDeps[file] = {};
245
+ for (const spec of specs(source)) {
246
+ const target = resolve(file, spec);
247
+ if (!target) continue;
248
+ jsDeps[file][spec] = target;
249
+ nativeDeps[file][spec] = files.includes(target) ? `proxy:${moduleNameOf(target)}` : target;
250
+ }
251
+ }
252
+ for (const [name, proxy] of proxies) {
253
+ defs[`proxy:${name}`] = proxy;
254
+ nativeDeps[`proxy:${name}`] = {
255
+ [`${"../".repeat(name.split("/").length - 1) || "./"}_lucent/runtime.js`]: "loader",
256
+ "react-native": "react-native"
257
+ };
258
+ }
259
+ nativeDeps.loader = {};
260
+ return `var defs = {
261
+ ${Object.entries(defs).map(([id, code]) => `${JSON.stringify(id)}: function (module, exports, require) {\n${code}\n}`).join(",\n")}
262
+ };
263
+ var deps = { js: ${JSON.stringify(jsDeps)}, native: ${JSON.stringify(nativeDeps)} };
264
+ var loaded = { js: {}, native: {} };
265
+ function load(world, id) {
266
+ var cache = loaded[world];
267
+ if (cache[id]) return cache[id].exports;
268
+ var module = { exports: {} };
269
+ cache[id] = module;
270
+ defs[id](module, module.exports, function (spec) {
271
+ var target = (deps[world][id] || {})[spec];
272
+ if (target === undefined) throw new Error("cannot resolve " + spec + " from " + id);
273
+ return load(world, target);
274
+ });
275
+ return module.exports;
276
+ }
277
+ // Milliseconds per call: the best of 5 rounds, each repeating the call for
278
+ // at least 30 ms, so fast cases are measured beyond the clock's resolution.
279
+ function best(f) {
280
+ var min = Infinity;
281
+ for (var r = 0; r < 5; r++) {
282
+ var start = Date.now(), calls = 0, elapsed;
283
+ do { f(); calls++; elapsed = Date.now() - start; } while (elapsed < 30);
284
+ min = Math.min(min, elapsed / calls);
285
+ }
286
+ return min;
287
+ }
288
+ var benches = ${JSON.stringify(benches.map((b) => [b, path.relative(root, b)]))};
289
+ for (var i = 0; i < benches.length; i++) {
290
+ var id = benches[i][0], file = benches[i][1];
291
+ var js = load("js", id).default, native = load("native", id).default;
292
+ for (var name in js) {
293
+ try {
294
+ var same = JSON.stringify(js[name]()) === JSON.stringify(native[name]());
295
+ print(JSON.stringify({ file: file, name: name, js: best(js[name]), native: best(native[name]), same: same }));
296
+ } catch (e) {
297
+ print(JSON.stringify({ file: file, name: name, js: 0, native: 0, same: false, error: String(e && e.message || e) }));
298
+ }
299
+ }
300
+ }
301
+ `;
302
+ }
303
+ //#endregion
304
+ export { run };
@@ -0,0 +1,7 @@
1
+ import { t as buildOrCheck } from "./build-check-QozuNJm5.js";
2
+ //#region src/cli/commands/build.ts
3
+ function run(invocation) {
4
+ return buildOrCheck("build", invocation);
5
+ }
6
+ //#endregion
7
+ export { run };
@@ -0,0 +1,92 @@
1
+ import { n as version } from "./version-bqpIO5sP.js";
2
+ import { i as table, n as duration } from "./format-D9fnIMEx.js";
3
+ import { t as renderDiagnostic } from "./diagnostic-BM9sXmwl.js";
4
+ import { n as nextText, r as plural, t as buildProject } from "./pipeline-CH7-2cxu.js";
5
+ import { t as plainSteps } from "./steps--_h-FFS7.js";
6
+ import fs from "node:fs";
7
+ import path from "node:path";
8
+ //#region src/cli/commands/build-check.ts
9
+ async function buildOrCheck(command, { root, flags, out }) {
10
+ const theme = out.theme;
11
+ const notices = [];
12
+ const notify = (n) => {
13
+ notices.push(n);
14
+ out.print(`${n.level === "ok" ? theme.success(theme.symbols.ok) : theme.warn(theme.symbols.warn)} ${n.text}`);
15
+ };
16
+ if (command === "build") out.print(`${theme.brand(theme.symbols.brand)} ${theme.bold("lucent")} ${theme.dim(version())}\n`);
17
+ const steps = command === "check" || out.json ? plainSteps(() => {}, theme) : out.terminal.interactive ? (await import("./live-steps-BGcWFM9M.js")).liveSteps(theme) : plainSteps((l) => out.print(l), theme);
18
+ let result;
19
+ try {
20
+ result = await buildProject(root, {
21
+ mode: command,
22
+ force: !!flags.force,
23
+ platforms: typeof flags.platforms === "string" && flags.platforms ? flags.platforms.split(",") : void 0,
24
+ out: typeof flags.out === "string" ? flags.out : void 0,
25
+ prefetch: true
26
+ }, steps, notify);
27
+ } finally {
28
+ await steps.close();
29
+ }
30
+ if (out.json) {
31
+ if (result.fatal) out.data({
32
+ ok: false,
33
+ error: result.fatal
34
+ });
35
+ else if (command === "check") out.data({
36
+ ok: result.ok,
37
+ modules: result.modules.map((m) => m.name),
38
+ diagnostics: result.diagnostics,
39
+ errors: result.diagnostics.length,
40
+ ms: result.ms
41
+ });
42
+ else out.data({
43
+ ok: result.ok,
44
+ upToDate: result.upToDate,
45
+ out: path.resolve(root, typeof flags.out === "string" ? flags.out : ".lucent/native"),
46
+ modules: result.modules,
47
+ steps: steps.results,
48
+ diagnostics: result.diagnostics,
49
+ notices,
50
+ next: result.next,
51
+ ms: result.ms
52
+ });
53
+ return result.ok ? 0 : 1;
54
+ }
55
+ if (result.fatal) {
56
+ out.error(`${theme.error(theme.symbols.fail)} ${result.fatal}`);
57
+ return 1;
58
+ }
59
+ if (!result.ok) {
60
+ problems(result.diagnostics, result.modules.length, result.ms, command === "build");
61
+ return 1;
62
+ }
63
+ if (command === "check") {
64
+ out.print(`${theme.success(theme.symbols.ok)} ${plural(result.modules.length, "module")}, no problems ${theme.dim(result.upToDate ? `${duration(result.ms)} (unchanged since the last check)` : duration(result.ms))}`);
65
+ return 0;
66
+ }
67
+ if (result.upToDate) return 0;
68
+ out.print("");
69
+ for (const line of table(result.modules.map((m, i) => [
70
+ i ? "" : theme.dim("modules"),
71
+ m.name,
72
+ m.platforms.join(" ")
73
+ ]))) out.print(line);
74
+ out.print(`${theme.dim("next")} ${nextText(result.next)}`);
75
+ return 0;
76
+ function problems(diagnostics, modules, ms, build) {
77
+ const sources = /* @__PURE__ */ new Map();
78
+ const source = (file) => {
79
+ if (!sources.has(file)) {
80
+ const abs = path.resolve(root, file);
81
+ sources.set(file, fs.existsSync(abs) ? fs.readFileSync(abs, "utf8") : void 0);
82
+ }
83
+ return sources.get(file);
84
+ };
85
+ out.error("");
86
+ for (const d of diagnostics) out.error(`${renderDiagnostic(d, d.file ? source(d.file) : void 0, theme)}\n`);
87
+ const summary = `${plural(diagnostics.length, "error")} ${theme.dim("·")} ${plural(modules, "module")} ${theme.dim("·")} ${duration(ms)}`;
88
+ out.error(` ${theme.error(summary)}${build ? theme.dim(" nothing was written") : ""}`);
89
+ }
90
+ }
91
+ //#endregion
92
+ export { buildOrCheck as t };
@@ -0,0 +1,7 @@
1
+ import { t as buildOrCheck } from "./build-check-QozuNJm5.js";
2
+ //#region src/cli/commands/check.ts
3
+ function run(invocation) {
4
+ return buildOrCheck("check", invocation);
5
+ }
6
+ //#endregion
7
+ export { run };
@@ -0,0 +1,35 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import os from "node:os";
4
+ //#region src/cli/commands/clean.ts
5
+ function size(dir) {
6
+ if (!fs.existsSync(dir)) return 0;
7
+ const stat = fs.statSync(dir);
8
+ if (!stat.isDirectory()) return stat.size;
9
+ return fs.readdirSync(dir).reduce((n, e) => n + size(path.join(dir, e)), 0);
10
+ }
11
+ const mb = (bytes) => `${(bytes / 1e6).toFixed(1)} MB`;
12
+ function run({ root, flags, out }) {
13
+ const t = out.theme;
14
+ const generated = path.join(root, ".lucent");
15
+ if (fs.existsSync(generated)) {
16
+ const freed = size(generated);
17
+ fs.rmSync(generated, {
18
+ recursive: true,
19
+ force: true
20
+ });
21
+ out.print(`${t.success(t.symbols.ok)} removed .lucent ${t.dim(mb(freed))}`);
22
+ } else out.print(`${t.dim(t.symbols.off)} nothing to remove in the project`);
23
+ if (flags.cache) {
24
+ const cache = path.join(process.env.LUCENT_CACHE_DIR || path.join(process.env.XDG_CACHE_HOME || path.join(os.homedir(), ".cache"), "lucent"), "sdk");
25
+ const freed = size(cache);
26
+ fs.rmSync(cache, {
27
+ recursive: true,
28
+ force: true
29
+ });
30
+ out.print(`${t.success(t.symbols.ok)} removed the SDK cache ${t.dim(`${mb(freed)}, ${cache.replace(os.homedir(), "~")}; SDK modules are extracted again on first use`)}`);
31
+ }
32
+ return 0;
33
+ }
34
+ //#endregion
35
+ export { run };