@lucent-lang/lucent 0.0.4 → 0.1.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.
Files changed (152) hide show
  1. package/README.md +97 -0
  2. package/app.plugin.js +46 -10
  3. package/dist/{bench-CR3E7e2e.js → bench-eEez4jhQ.js} +10 -6
  4. package/dist/{build-CAIrRSYA.js → build-CpUjeHFz.js} +1 -1
  5. package/dist/{build-check-QozuNJm5.js → build-check-BA1ZEp9s.js} +28 -13
  6. package/dist/{check-1SCmYlqA.js → check-BZx3FgI6.js} +1 -1
  7. package/dist/cli.js +62 -13
  8. package/dist/{codes-CIuwXt1S.js → codes-D-6LxUqD.js} +163 -7
  9. package/dist/compiler.js +4 -4
  10. package/dist/{dashboard-B-NzjjaN.js → dashboard-CC-HXhcd.js} +2 -2
  11. package/dist/{dev-BYWMP7oC.js → dev-DI5yL8zx.js} +62 -23
  12. package/dist/{diagnostic-BM9sXmwl.js → diagnostic-BvwLZQS1.js} +3 -1
  13. package/dist/{doctor-C0PrfWT6.js → doctor-CTAX3euc.js} +1 -1
  14. package/dist/{doctor-DdR4JnVc.js → doctor-CrgOAV5L.js} +1 -1
  15. package/dist/{explain--vV1oaRl.js → explain-Byit07F-.js} +1 -1
  16. package/dist/{packages-HyskKIsY.js → packages-CSmKeaAh.js} +2 -33
  17. package/dist/pipeline-BM_VM2X_.js +700 -0
  18. package/dist/project-BKNoTEEp.js +342 -0
  19. package/dist/sdk-coverage-iiv3JqMp.js +113 -0
  20. package/dist/sdk-diff-ByJ1Gw-F.js +109 -0
  21. package/dist/sdk-lock-BQn7IyRs.js +38 -0
  22. package/dist/{sdk-prefetch-mo04JDZV.js → sdk-prefetch-Bv2pNega.js} +2 -2
  23. package/dist/{sdk-search-Iv4K3-8a.js → sdk-search-CPGJm_Ne.js} +2 -2
  24. package/dist/{sdk-show-CkrdlqlP.js → sdk-show-BUkLqRnA.js} +5 -4
  25. package/dist/sdk-usage-0ZFMAYg1.js +95 -0
  26. package/dist/src-ChnmWLwn.js +40851 -0
  27. package/dist/trace-Bi4hkmPx.js +139 -0
  28. package/lib/core.cjs +368 -1
  29. package/lib/sdk/android.d.ts +54 -1
  30. package/lib/sdk/compose.d.ts +94 -0
  31. package/lib/sdk/compose.schemas.json.gz +0 -0
  32. package/lib/sdk/core.d.ts +201 -0
  33. package/lib/sdk/ios.d.ts +75 -2
  34. package/lib/sdk/ui.d.ts +129 -0
  35. package/metro/transformer.cjs +11 -2
  36. package/package.json +4 -3
  37. package/runtime/cpp/lucent/abort.cpp +59 -11
  38. package/runtime/cpp/lucent/abort.h +22 -6
  39. package/runtime/cpp/lucent/array.h +12 -2
  40. package/runtime/cpp/lucent/async.h +101 -21
  41. package/runtime/cpp/lucent/bigint.cpp +898 -0
  42. package/runtime/cpp/lucent/bigint.h +302 -0
  43. package/runtime/cpp/lucent/buffer.cpp +228 -0
  44. package/runtime/cpp/lucent/buffer.h +328 -0
  45. package/runtime/cpp/lucent/builtins.cpp +4 -1
  46. package/runtime/cpp/lucent/bytes.h +21 -2
  47. package/runtime/cpp/lucent/callback.cpp +29 -0
  48. package/runtime/cpp/lucent/callback.h +230 -0
  49. package/runtime/cpp/lucent/compute.cpp +370 -0
  50. package/runtime/cpp/lucent/compute.h +455 -0
  51. package/runtime/cpp/lucent/conversions.h +111 -0
  52. package/runtime/cpp/lucent/core.h +16 -5
  53. package/runtime/cpp/lucent/equality.h +107 -28
  54. package/runtime/cpp/lucent/execution.cpp +416 -0
  55. package/runtime/cpp/lucent/execution.h +270 -0
  56. package/runtime/cpp/lucent/extension.cpp +97 -0
  57. package/runtime/cpp/lucent/extension.h +210 -0
  58. package/runtime/cpp/lucent/helpers.h +12 -5
  59. package/runtime/cpp/lucent/items.h +52 -0
  60. package/runtime/cpp/lucent/jserror.cpp +9 -0
  61. package/runtime/cpp/lucent/jserror.h +11 -0
  62. package/runtime/cpp/lucent/jsi/convert.cpp +138 -0
  63. package/runtime/cpp/lucent/jsi/convert.h +128 -59
  64. package/runtime/cpp/lucent/jsi/host.cpp +213 -35
  65. package/runtime/cpp/lucent/jsi/host.h +116 -16
  66. package/runtime/cpp/lucent/json.h +19 -1
  67. package/runtime/cpp/lucent/lifecycle.cpp +260 -0
  68. package/runtime/cpp/lucent/lifecycle.h +124 -0
  69. package/runtime/cpp/lucent/lucent.h +7 -0
  70. package/runtime/cpp/lucent/map.h +41 -7
  71. package/runtime/cpp/lucent/native.cpp +35 -47
  72. package/runtime/cpp/lucent/native.h +116 -26
  73. package/runtime/cpp/lucent/number.cpp +38 -38
  74. package/runtime/cpp/lucent/number.h +33 -0
  75. package/runtime/cpp/lucent/operation.h +65 -0
  76. package/runtime/cpp/lucent/ops.h +14 -6
  77. package/runtime/cpp/lucent/platform/android.cpp +223 -10
  78. package/runtime/cpp/lucent/platform/android.h +227 -4
  79. package/runtime/cpp/lucent/platform/android_activity.cpp +258 -0
  80. package/runtime/cpp/lucent/platform/android_requests.h +140 -0
  81. package/runtime/cpp/lucent/platform/compose.h +256 -0
  82. package/runtime/cpp/lucent/platform/ios.h +325 -25
  83. package/runtime/cpp/lucent/platform/ios.mm +1 -14
  84. package/runtime/cpp/lucent/platform/ios_ui.h +192 -0
  85. package/runtime/cpp/lucent/platform/ios_ui.mm +454 -0
  86. package/runtime/cpp/lucent/platform/swiftui.h +190 -0
  87. package/runtime/cpp/lucent/presentation.cpp +11 -0
  88. package/runtime/cpp/lucent/presentation.h +109 -0
  89. package/runtime/cpp/lucent/reactive.cpp +406 -0
  90. package/runtime/cpp/lucent/reactive.h +566 -0
  91. package/runtime/cpp/lucent/report.cpp +40 -0
  92. package/runtime/cpp/lucent/report.h +16 -0
  93. package/runtime/cpp/lucent/resource.cpp +83 -0
  94. package/runtime/cpp/lucent/resource.h +75 -0
  95. package/runtime/cpp/lucent/scheduler.cpp +38 -124
  96. package/runtime/cpp/lucent/scheduler.h +102 -83
  97. package/runtime/cpp/lucent/scope.cpp +308 -0
  98. package/runtime/cpp/lucent/scope.h +452 -0
  99. package/runtime/cpp/lucent/sizing.h +263 -0
  100. package/runtime/cpp/lucent/slots.h +231 -0
  101. package/runtime/cpp/lucent/trace.cpp +539 -0
  102. package/runtime/cpp/lucent/trace.h +251 -0
  103. package/runtime/cpp/lucent/transport.cpp +9 -0
  104. package/runtime/cpp/lucent/transport.h +341 -0
  105. package/runtime/cpp/lucent/view.cpp +123 -0
  106. package/runtime/cpp/lucent/view.h +157 -0
  107. package/runtime/cpp/rn/LucentComponentView.h +121 -0
  108. package/runtime/cpp/rn/LucentComponentView.mm +479 -0
  109. package/runtime/cpp/rn/LucentModule.cpp +37 -7
  110. package/runtime/cpp/rn/LucentModule.h +3 -0
  111. package/runtime/cpp/rn/LucentViewChildren.h +80 -0
  112. package/runtime/cpp/rn/LucentViewChildren.mm +211 -0
  113. package/runtime/cpp/rn/LucentViewRegistry.h +62 -0
  114. package/runtime/cpp/rn/LucentViewRequests.cpp +91 -0
  115. package/runtime/cpp/rn/LucentViewRequests.h +104 -0
  116. package/runtime/cpp/rn/LucentViewSizing.h +345 -0
  117. package/runtime/cpp/rn/LucentViewSlots.h +242 -0
  118. package/runtime/cpp/rn/LucentViewValues.h +125 -0
  119. package/runtime/cpp/rn/LucentViews.h +440 -0
  120. package/runtime/cpp/rn/LucentViewsAndroid.cpp +439 -0
  121. package/runtime/cpp/rn/LucentViewsAndroid.h +138 -0
  122. package/runtime/cpp/third_party/dragonbox/LICENSE-Boost +23 -0
  123. package/runtime/cpp/third_party/dragonbox/README.md +16 -0
  124. package/runtime/cpp/third_party/dragonbox/dragonbox.h +4440 -0
  125. package/runtime/js/index.d.ts +11 -1
  126. package/runtime/js/index.js +84 -8
  127. package/runtime/js/views.d.ts +38 -0
  128. package/runtime/js/views.js +226 -0
  129. package/runtime/native/android/CMakeLists.txt +4 -1
  130. package/runtime/native/android/src/compose/java/dev/lucent/compose/CompositionRules.kt +44 -0
  131. package/runtime/native/android/src/compose/java/dev/lucent/compose/LucentComposition.kt +161 -0
  132. package/runtime/native/android/src/main/java/dev/lucent/LucentActivities.java +292 -0
  133. package/runtime/native/android/src/main/java/dev/lucent/LucentChildren.java +174 -0
  134. package/runtime/native/android/src/main/java/dev/lucent/LucentHostView.java +232 -0
  135. package/runtime/native/android/src/main/java/dev/lucent/LucentInitializer.java +46 -0
  136. package/runtime/native/android/src/main/java/dev/lucent/LucentPackage.java +4 -3
  137. package/runtime/native/android/src/main/java/dev/lucent/LucentRequestActivity.java +92 -0
  138. package/runtime/native/android/src/main/java/dev/lucent/LucentSlotView.java +102 -0
  139. package/runtime/native/android/src/main/java/dev/lucent/LucentViewManager.java +149 -0
  140. package/runtime/native/android/src/main/java/dev/lucent/LucentViewManagers.java +16 -0
  141. package/runtime/native/android/src/main/java/dev/lucent/LucentViews.java +44 -0
  142. package/runtime/test/jsi/harness.cpp +9 -0
  143. package/schemas/build.schema.json +96 -1
  144. package/schemas/check.schema.json +56 -1
  145. package/schemas/lucent.schema.json +495 -9
  146. package/schemas/sdk-diff.schema.json +70 -0
  147. package/schemas/sdk-lock.schema.json +67 -0
  148. package/ts-plugin/index.js +85 -4
  149. package/dist/pipeline-CH7-2cxu.js +0 -232
  150. package/dist/project-D8tEet0k.js +0 -150
  151. package/dist/sdk-coverage-BoW_3Efd.js +0 -64
  152. package/dist/src-BD7f1_aZ.js +0 -11493
@@ -0,0 +1,342 @@
1
+ import { t as packageFile } from "./version-bqpIO5sP.js";
2
+ import { J as forgetLoadedSdks, W as podsSearchPaths, c as sdkModules, f as runtimeDir, g as libraryBuildGradle, v as resolveNative, x as fileHashes } from "./src-ChnmWLwn.js";
3
+ import { n as lucentPackages } from "./packages-CSmKeaAh.js";
4
+ import { t as withLucentPaths } from "./tsconfig-S4uyLNzf.js";
5
+ import fs from "node:fs";
6
+ import path from "node:path";
7
+ import os from "node:os";
8
+ import { createHash } from "node:crypto";
9
+ import { spawn, spawnSync } from "node:child_process";
10
+ //#region ../bindgen/src/vendored.ts
11
+ function frameworkSearchPath(framework) {
12
+ if (!framework.endsWith(".xcframework")) return path.dirname(framework);
13
+ const slice = xcframeworkLibraries(framework).find((l) => l.platform === "ios" && l.variant === "simulator" && l.identifier && l.path);
14
+ if (!slice) return void 0;
15
+ const dir = path.join(framework, slice.identifier);
16
+ return fs.existsSync(path.join(dir, slice.path)) ? dir : void 0;
17
+ }
18
+ function xcframeworkLibraries(framework) {
19
+ const plist = path.join(framework, "Info.plist");
20
+ if (!fs.existsSync(plist)) return [];
21
+ const text = fs.readFileSync(plist, "utf8");
22
+ const start = /<key>AvailableLibraries<\/key>\s*<array>/.exec(text);
23
+ if (!start) return [];
24
+ const tags = /<(\/?)array>/g;
25
+ tags.lastIndex = start.index + start[0].length;
26
+ let end = text.length;
27
+ for (let depth = 1, m = tags.exec(text); m; m = tags.exec(text)) {
28
+ depth += m[1] ? -1 : 1;
29
+ if (depth === 0) {
30
+ end = m.index;
31
+ break;
32
+ }
33
+ }
34
+ return [...text.slice(start.index + start[0].length, end).matchAll(/<dict>([\s\S]*?)<\/dict>/g)].map(([, entry]) => {
35
+ const value = (key) => new RegExp(`<key>${key}</key>\\s*<string>([^<]*)</string>`).exec(entry)?.[1];
36
+ return {
37
+ identifier: value("LibraryIdentifier"),
38
+ path: value("LibraryPath"),
39
+ platform: value("SupportedPlatform"),
40
+ variant: value("SupportedPlatformVariant")
41
+ };
42
+ });
43
+ }
44
+ //#endregion
45
+ //#region src/cli/project.ts
46
+ function mapLucentPaths(root) {
47
+ const file = path.join(root, "tsconfig.json");
48
+ if (!fs.existsSync(file)) return void 0;
49
+ let text;
50
+ try {
51
+ text = withLucentPaths(fs.readFileSync(file, "utf8"));
52
+ } catch (e) {
53
+ return {
54
+ level: "warn",
55
+ text: `${e.message}; add "paths": { "lucent:*": ["./.lucent/native/types/*"] } to its compilerOptions yourself`
56
+ };
57
+ }
58
+ if (text === void 0) return void 0;
59
+ fs.writeFileSync(file, text);
60
+ return {
61
+ level: "ok",
62
+ text: "mapped lucent:* in tsconfig.json"
63
+ };
64
+ }
65
+ function projectSdk(root, native) {
66
+ const binaries = native?.binaries ?? packageBinaries(root);
67
+ const pods = podsSearchPaths(path.join(root, "ios"));
68
+ const frameworkPaths = [...new Set(binaries.ios.map(frameworkSearchPath).filter((dir) => dir !== void 0))];
69
+ const ios = pods || frameworkPaths.length ? pods ?? {} : void 0;
70
+ return {
71
+ android: {
72
+ classpath: path.join(root, ".lucent/android-classpath.json"),
73
+ ...binaries.android.length ? { libraries: binaries.android } : {}
74
+ },
75
+ ...ios ? { ios: {
76
+ ...ios,
77
+ frameworkPaths: [...ios.frameworkPaths ?? [], ...frameworkPaths]
78
+ } } : {}
79
+ };
80
+ }
81
+ function packageBinaries(root) {
82
+ const hashes = projectHashes(root);
83
+ try {
84
+ const { binaries } = resolveNative(lucentPackages(root), { hashes });
85
+ hashes.save();
86
+ return binaries;
87
+ } catch {
88
+ return {
89
+ ios: [],
90
+ android: []
91
+ };
92
+ }
93
+ }
94
+ const projectHashes = (root) => fileHashes(path.join(root, ".lucent/file-hashes.json"));
95
+ function resolveAndroidDependencies(root, files, sdk, native, force) {
96
+ const gradlew = gradlewOf(root);
97
+ const android = path.dirname(gradlew);
98
+ if (!sdkImports(files).android.length || !fs.existsSync(gradlew)) return { status: "none" };
99
+ const stateFile = path.join(root, ".lucent/android-classpath.state.json");
100
+ const inputs = gradleInputsHash(root, native);
101
+ const record = (ok) => {
102
+ fs.mkdirSync(path.dirname(stateFile), { recursive: true });
103
+ fs.writeFileSync(stateFile, JSON.stringify({
104
+ inputs,
105
+ ok
106
+ }) + "\n");
107
+ };
108
+ if (process.env.LUCENT_GRADLE_CLASSPATH) {
109
+ if (fs.existsSync(sdk.android.classpath)) record(true);
110
+ return { status: "cached" };
111
+ }
112
+ if (process.env.LUCENT_NO_GRADLE) return fs.existsSync(sdk.android.classpath) ? { status: "cached" } : { status: "deferred" };
113
+ const known = () => {
114
+ const state = fs.existsSync(stateFile) ? JSON.parse(fs.readFileSync(stateFile, "utf8")) : {};
115
+ if (force || state.inputs !== inputs) return void 0;
116
+ if (state.ok === false) return {
117
+ status: "failed",
118
+ detail: "Gradle could not resolve them for these build files before; lucent build --force retries"
119
+ };
120
+ return fs.existsSync(sdk.android.classpath) ? { status: "cached" } : void 0;
121
+ };
122
+ const before = known();
123
+ if (before) return before;
124
+ const lock = path.join(root, ".lucent/gradle.lock");
125
+ if (!acquire(lock)) {
126
+ waitFor(lock);
127
+ const after = known();
128
+ if (after) return after;
129
+ if (!acquire(lock)) throw new Error(`${lock}: another lucent build holds it`);
130
+ }
131
+ try {
132
+ const script = packageFile("gradle/lucent-classpath.init.gradle");
133
+ const r = spawnSync(gradlew, [
134
+ "-q",
135
+ "--init-script",
136
+ script,
137
+ ":app:lucentClasspath"
138
+ ], {
139
+ cwd: android,
140
+ encoding: "utf8",
141
+ env: {
142
+ ...process.env,
143
+ LUCENT_GRADLE_CLASSPATH: "1"
144
+ }
145
+ });
146
+ record(r.status === 0);
147
+ forgetLoadedSdks();
148
+ if (r.status === 0) return { status: "resolved" };
149
+ return {
150
+ status: "failed",
151
+ detail: `Gradle could not resolve them (retried when the build files or the lockfile change, or with lucent build --force):\n${(r.stderr || r.stdout).trim().split("\n").slice(-8).join("\n")}`
152
+ };
153
+ } finally {
154
+ fs.rmSync(lock, { force: true });
155
+ }
156
+ }
157
+ function acquire(lock) {
158
+ fs.mkdirSync(path.dirname(lock), { recursive: true });
159
+ for (;;) try {
160
+ fs.writeFileSync(lock, `${os.hostname()}\n${process.pid}`, { flag: "wx" });
161
+ return true;
162
+ } catch {
163
+ if (holderAlive(lock)) return false;
164
+ fs.rmSync(lock, { force: true });
165
+ }
166
+ }
167
+ function holderAlive(lock) {
168
+ let text;
169
+ try {
170
+ text = fs.readFileSync(lock, "utf8");
171
+ } catch {
172
+ return false;
173
+ }
174
+ const [host, pid] = text.split("\n");
175
+ if (host !== os.hostname()) return true;
176
+ try {
177
+ process.kill(Number(pid), 0);
178
+ return true;
179
+ } catch {
180
+ return false;
181
+ }
182
+ }
183
+ function waitFor(lock, timeoutMs = 6e5) {
184
+ const sleeper = new Int32Array(new SharedArrayBuffer(4));
185
+ for (const start = Date.now(); fs.existsSync(lock) && holderAlive(lock);) {
186
+ if (Date.now() - start > timeoutMs) return;
187
+ Atomics.wait(sleeper, 0, 0, 50);
188
+ }
189
+ }
190
+ function writeLinkedPackage(root, out, native) {
191
+ const templates = path.join(runtimeDir(), "native");
192
+ const created = !fs.existsSync(path.join(out, "react-native.config.js"));
193
+ for (const file of listFiles(templates)) {
194
+ const to = path.join(out, path.relative(templates, file));
195
+ if (fs.existsSync(to)) continue;
196
+ fs.mkdirSync(path.dirname(to), { recursive: true });
197
+ fs.copyFileSync(file, to);
198
+ }
199
+ writeGradleDependencies(out, native);
200
+ if (created) staleAutolinking(root);
201
+ return created;
202
+ }
203
+ function staleAutolinking(root) {
204
+ const dir = path.join(root, "android/build/generated/autolinking");
205
+ if (!fs.existsSync(dir)) return;
206
+ for (const f of fs.readdirSync(dir)) if (f.endsWith(".sha")) fs.rmSync(path.join(dir, f));
207
+ }
208
+ function listFiles(dir) {
209
+ return fs.readdirSync(dir, { withFileTypes: true }).flatMap((e) => e.isDirectory() ? listFiles(path.join(dir, e.name)) : [path.join(dir, e.name)]);
210
+ }
211
+ function writeGradleDependencies(out, native) {
212
+ const file = path.join(out, "android/build.gradle");
213
+ const kotlin = (dir) => {
214
+ const at = path.join(out, "android/src/main/java/dev/lucent", dir);
215
+ return fs.existsSync(at) ? fs.readdirSync(at).filter((f) => f.endsWith(".kt")).map((f) => fs.readFileSync(path.join(at, f), "utf8")) : [];
216
+ };
217
+ const text = libraryBuildGradle(fs.readFileSync(path.join(runtimeDir(), "native/android/build.gradle"), "utf8"), native, kotlin("shims").length > 0, kotlin("compose"));
218
+ if (fs.existsSync(file) && fs.readFileSync(file, "utf8") === text) return;
219
+ fs.mkdirSync(path.dirname(file), { recursive: true });
220
+ fs.writeFileSync(file, text);
221
+ }
222
+ const APP_PLISTS = [{
223
+ entries: (n) => n.ios.infoPlist,
224
+ files: (dir) => ["Info.plist"].filter((f) => fs.existsSync(path.join(dir, f))),
225
+ none: "the app has no Info.plist"
226
+ }, {
227
+ entries: (n) => n.ios.entitlements,
228
+ files: (dir) => fs.readdirSync(dir).filter((f) => f.endsWith(".entitlements")),
229
+ none: "the app's target has no .entitlements file"
230
+ }];
231
+ function missingAppEntries(root, native) {
232
+ const ios = path.join(root, "ios");
233
+ const targets = fs.existsSync(ios) ? fs.readdirSync(ios, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => path.join(ios, e.name)) : [];
234
+ const out = [];
235
+ const warn = (text) => out.push({
236
+ level: "warn",
237
+ text: `${text} (the Expo config plugin adds it)`
238
+ });
239
+ const who = (from) => `${from.join(" and ")} ${from.length === 1 ? "needs" : "need"}`;
240
+ for (const { entries, files, none } of APP_PLISTS) {
241
+ const keys = Object.entries(entries(native));
242
+ const found = targets.flatMap((dir) => files(dir).map((f) => path.join(dir, f)));
243
+ if (!keys.length || !targets.length) continue;
244
+ if (!found.length) for (const [key, { from }] of keys) warn(`${who(from)} ${key}, but ${none}`);
245
+ for (const file of found) {
246
+ const app = plistEntries(fs.readFileSync(file, "utf8"));
247
+ const where = path.relative(root, file);
248
+ for (const [key, { value, from }] of keys) {
249
+ const has = app.get(key);
250
+ if (has === void 0) warn(`${who(from)} ${key} in ${where}`);
251
+ else if (Array.isArray(value)) for (const v of value.filter((v) => !(Array.isArray(has) && has.includes(v)))) warn(`${who(from)} ${JSON.stringify(v)} in ${key} in ${where}`);
252
+ }
253
+ }
254
+ }
255
+ return out;
256
+ }
257
+ function plistEntries(text) {
258
+ const out = /* @__PURE__ */ new Map();
259
+ for (const m of text.matchAll(/<key>([^<]*)<\/key>\s*(?:<string>([^<]*)<\/string>|<(true|false)\/>|<array>([\s\S]*?)<\/array>|<array\/>)?/g)) {
260
+ const [, key, string, boolean, array] = m;
261
+ out.set(key, string !== void 0 ? string : boolean !== void 0 ? boolean === "true" : array !== void 0 || m[0].endsWith("<array/>") ? [...(array ?? "").matchAll(/<string>([^<]*)<\/string>/g)].map((s) => s[1]) : null);
262
+ }
263
+ return out;
264
+ }
265
+ function gradleInputsHash(root, native) {
266
+ const android = path.join(root, "android");
267
+ const gradle = [
268
+ "settings.gradle",
269
+ "settings.gradle.kts",
270
+ "build.gradle",
271
+ "build.gradle.kts",
272
+ "app/build.gradle",
273
+ "app/build.gradle.kts",
274
+ "gradle.properties",
275
+ "gradle/libs.versions.toml"
276
+ ].map((f) => path.join(android, f));
277
+ const h = createHash("sha256");
278
+ for (const f of [...gradle, ...lockfiles(root)]) h.update(`${f}\0${fs.existsSync(f) ? fs.readFileSync(f) : ""}\0`);
279
+ h.update(JSON.stringify(native.android.dependencies));
280
+ return h.digest("hex").slice(0, 16);
281
+ }
282
+ const gradlewOf = (root) => path.join(root, "android", process.platform === "win32" ? "gradlew.bat" : "gradlew");
283
+ function pendingAndroidModules(root, files, sdk) {
284
+ const imports = sdkImports(files).android;
285
+ const resolved = sdk.android?.classpath && fs.existsSync(sdk.android.classpath);
286
+ if (!imports.length || resolved || fs.existsSync(gradlewOf(root))) return [];
287
+ const available = sdkModules("android", sdk);
288
+ if (!Array.isArray(available)) return [];
289
+ const declared = new Set(available);
290
+ return imports.filter((m) => !declared.has(m));
291
+ }
292
+ function lockfiles(root) {
293
+ const names = [
294
+ "package-lock.json",
295
+ "yarn.lock",
296
+ "pnpm-lock.yaml",
297
+ "bun.lock",
298
+ "bun.lockb"
299
+ ];
300
+ for (let dir = path.resolve(root);; dir = path.dirname(dir)) {
301
+ const found = names.map((n) => path.join(dir, n)).filter((f) => fs.existsSync(f));
302
+ if (found.length || path.dirname(dir) === dir) return found;
303
+ }
304
+ }
305
+ function sdkImports(files) {
306
+ const out = {
307
+ ios: /* @__PURE__ */ new Set(),
308
+ android: /* @__PURE__ */ new Set()
309
+ };
310
+ for (const f of files) for (const m of fs.readFileSync(f, "utf8").matchAll(/["']lucent:(ios|android)\/([\w.]+)["']/g)) out[m[1]].add(m[2]);
311
+ return {
312
+ ios: [...out.ios].sort(),
313
+ android: [...out.android].sort()
314
+ };
315
+ }
316
+ function prefetchJobs(imports, platforms, slots) {
317
+ const jobs = platforms.flatMap((p) => imports[p].map((m) => [p, m]));
318
+ const count = Math.min(jobs.length, slots);
319
+ return Array.from({ length: count }, (_, i) => {
320
+ const mine = jobs.filter((_, j) => j % count === i);
321
+ return platforms.flatMap((p) => {
322
+ const modules = mine.filter(([q]) => q === p).map(([, m]) => m);
323
+ return modules.length ? [`--${p}`, modules.join(",")] : [];
324
+ });
325
+ });
326
+ }
327
+ function backgroundPrefetch(root, files, platforms) {
328
+ const slots = Math.max(1, os.availableParallelism() - 1);
329
+ for (const args of prefetchJobs(sdkImports(files), platforms, slots)) spawn(process.execPath, [
330
+ process.argv[1],
331
+ "sdk",
332
+ "prefetch",
333
+ ...args,
334
+ "--root",
335
+ root
336
+ ], {
337
+ detached: true,
338
+ stdio: "ignore"
339
+ }).unref();
340
+ }
341
+ //#endregion
342
+ export { projectHashes as a, sdkImports as c, pendingAndroidModules as i, staleAutolinking as l, mapLucentPaths as n, projectSdk as o, missingAppEntries as r, resolveAndroidDependencies as s, backgroundPrefetch as t, writeLinkedPackage as u };
@@ -0,0 +1,113 @@
1
+ import { N as projectFiles, R as coverage, U as symbolKey, c as sdkModules, et as sdkSourceModule, h as toolkitsFrom, s as sdkModule } from "./src-ChnmWLwn.js";
2
+ import { c as sdkImports, o as projectSdk } from "./project-BKNoTEEp.js";
3
+ import { i as table } from "./format-D9fnIMEx.js";
4
+ import { n as USAGE_FILE, o as readUsage } from "./sdk-usage-0ZFMAYg1.js";
5
+ import fs from "node:fs";
6
+ import path from "node:path";
7
+ //#region src/cli/commands/sdk-coverage.ts
8
+ function run({ root, flags, out }) {
9
+ const t = out.theme;
10
+ const sdk = projectSdk(root);
11
+ const list = (flag) => (typeof flags[flag] === "string" ? flags[flag] : "").split(",").filter(Boolean);
12
+ const wanted = {
13
+ ios: list("ios"),
14
+ android: list("android")
15
+ };
16
+ if (!wanted.ios.length && !wanted.android.length) Object.assign(wanted, sdkImports(projectFiles(root)));
17
+ let evidence;
18
+ try {
19
+ evidence = readEvidence(root, typeof flags.exercised === "string" ? flags.exercised : "", (problem) => out.error(`${t.warn(t.symbols.warn)} ${problem}: generated is unknown until the next check or build`));
20
+ } catch (e) {
21
+ out.error(`${t.error(t.symbols.fail)} ${e.message}`);
22
+ return 1;
23
+ }
24
+ const reports = [];
25
+ for (const platform of ["ios", "android"]) {
26
+ const listed = () => {
27
+ const all = sdkModules(platform, sdk);
28
+ return "missing" in all ? [] : all;
29
+ };
30
+ const modules = wanted[platform].flatMap((m) => m.endsWith(".*") ? listed().filter((x) => x.startsWith(m.slice(0, -1))) : [m]);
31
+ for (const m of modules) {
32
+ const r = sdkModule(platform, m, sdk);
33
+ if ("missing" in r) {
34
+ out.error(`${t.error(t.symbols.fail)} ${r.missing}`);
35
+ return 1;
36
+ }
37
+ reports.push(coverage(r.schema, void 0, evidence));
38
+ for (const toolkit of toolkitsFrom(platform, m)) {
39
+ const source = sdkSourceModule(platform, m, sdk);
40
+ if ("missing" in source) {
41
+ out.error(`${t.error(t.symbols.fail)} ${toolkit}: ${source.missing}`);
42
+ return 1;
43
+ }
44
+ reports.push({
45
+ ...coverage(source.schema, void 0, evidence),
46
+ module: toolkit
47
+ });
48
+ }
49
+ }
50
+ }
51
+ if (flags.json) out.data(flags.members ? reports : reports.map((c) => ({
52
+ ...c,
53
+ members: void 0
54
+ })));
55
+ else {
56
+ const pct = (n, t) => `${t ? (100 * n / t).toFixed(1) : "0.0"}%`;
57
+ const known = (n) => n === null ? "-" : String(n);
58
+ const rows = reports.map((c) => [
59
+ c.module,
60
+ String(c.stages.discovered),
61
+ String(c.stages.representable),
62
+ `${c.unrepresentable} (${pct(c.unrepresentable, c.total)})`,
63
+ known(c.stages.generated),
64
+ known(c.stages.exercised)
65
+ ]);
66
+ for (const line of table([[
67
+ "module",
68
+ "discovered",
69
+ "representable",
70
+ "unrepresentable",
71
+ "generated",
72
+ "exercised"
73
+ ].map((h) => t.dim(h)), ...rows])) out.print(line);
74
+ if (flags.members) for (const c of reports) {
75
+ out.print("");
76
+ out.print(t.bold(c.module));
77
+ for (const line of table(c.members.map((m) => [
78
+ ` ${t.dim(m.stage)}`,
79
+ m.display,
80
+ m.reason ?? t.dim(m.key ?? "")
81
+ ]))) out.print(line.trimEnd());
82
+ }
83
+ }
84
+ const baselineFile = typeof flags.check === "string" ? flags.check : "";
85
+ if (!baselineFile) return 0;
86
+ const baseline = new Map(JSON.parse(fs.readFileSync(baselineFile, "utf8")).map((c) => [c.module, c]));
87
+ const share = (c) => c.total ? 100 * c.unrepresentable / c.total : 0;
88
+ let dropped = false;
89
+ for (const c of reports) {
90
+ const b = baseline.get(c.module);
91
+ if (b && share(c) > share(b) + .05) {
92
+ process.stderr.write(`${t.symbols.fail} ${c.module}: ${share(c).toFixed(2)}% unrepresentable, ${share(b).toFixed(2)}% in the baseline\n`);
93
+ dropped = true;
94
+ }
95
+ }
96
+ return dropped ? 1 : 0;
97
+ }
98
+ function readEvidence(root, exercisedFile, warn) {
99
+ const out = {};
100
+ try {
101
+ const usage = readUsage(path.join(root, USAGE_FILE));
102
+ if (usage) out.generated = new Set(usage.symbols.map(symbolKey));
103
+ } catch (e) {
104
+ warn(e.message);
105
+ }
106
+ if (!exercisedFile) return out;
107
+ const value = JSON.parse(fs.readFileSync(path.resolve(root, exercisedFile), "utf8"));
108
+ if (!Array.isArray(value) || !value.every((k) => typeof k === "string")) throw new Error(`${exercisedFile}: expected a JSON array of symbol keys (lucent sdk coverage --members --json lists them)`);
109
+ out.exercised = new Set(value);
110
+ return out;
111
+ }
112
+ //#endregion
113
+ export { run };
@@ -0,0 +1,109 @@
1
+ import { B as diffModule, H as displayName, K as cachedSchema, U as symbolKey, V as diffSymbols, s as sdkModule, z as compareArtifacts } from "./src-ChnmWLwn.js";
2
+ import { o as projectSdk } from "./project-BKNoTEEp.js";
3
+ import { i as table } from "./format-D9fnIMEx.js";
4
+ import { o as readUsage, r as artifactText, s as sdkUnavailable, t as LOCK_FILE, u as usedModules } from "./sdk-usage-0ZFMAYg1.js";
5
+ import path from "node:path";
6
+ //#region src/cli/commands/sdk-diff.ts
7
+ const entry = (c) => {
8
+ const s = c.after ?? c.before;
9
+ return {
10
+ change: c.change,
11
+ platform: s.platform,
12
+ module: s.module,
13
+ key: symbolKey(c.before ?? s),
14
+ display: displayName(c.before ?? s),
15
+ signature: s.signature,
16
+ details: c.details
17
+ };
18
+ };
19
+ function run({ root, flags, out }) {
20
+ const t = out.theme;
21
+ let lock;
22
+ try {
23
+ lock = readUsage(path.join(root, LOCK_FILE));
24
+ } catch (e) {
25
+ out.error(`${t.error(t.symbols.fail)} ${e.message}`);
26
+ return 1;
27
+ }
28
+ if (!lock) {
29
+ out.error(`${t.error(t.symbols.fail)} no ${LOCK_FILE}: lucent sdk lock records the SDKs to compare with`);
30
+ return 1;
31
+ }
32
+ const sdk = projectSdk(root);
33
+ const unavailable = lock.targets.flatMap((p) => {
34
+ const reason = sdkUnavailable(p, sdk);
35
+ return reason ? [{
36
+ platform: p,
37
+ reason
38
+ }] : [];
39
+ });
40
+ const available = (p) => !unavailable.some((u) => u.platform === p);
41
+ const schemaOf = (p, m) => {
42
+ const r = sdkModule(p, m, sdk);
43
+ return "schema" in r ? r.schema : r;
44
+ };
45
+ const used = diffSymbols(lock.symbols.filter((s) => available(s.platform)), schemaOf);
46
+ const lockedModules = Object.keys(lock.modules).filter((k) => available(k.split("/")[0]));
47
+ const artifacts = compareArtifacts(lock.modules, usedModules(lockedModules, sdk));
48
+ const others = [];
49
+ const uncached = [];
50
+ if (flags.all) {
51
+ const usedKeys = new Set(lock.symbols.map(symbolKey));
52
+ for (const key of lockedModules) {
53
+ const [p, m] = key.split("/");
54
+ const ref = lock.modules[key].schema;
55
+ const before = ref ? cachedSchema(p, m, ref, sdk) : void 0;
56
+ const after = schemaOf(p, m);
57
+ if (!before) uncached.push(key);
58
+ if (!before || "missing" in after) continue;
59
+ others.push(...diffModule(before, after).filter((c) => c.change !== "unchanged" && !usedKeys.has(symbolKey(c.before ?? c.after))));
60
+ }
61
+ }
62
+ const removed = used.filter((c) => c.change === "removed").length;
63
+ const changed = used.filter((c) => c.change === "changed").length;
64
+ const ok = !unavailable.length && !removed && !changed;
65
+ if (out.json) {
66
+ out.data({
67
+ ok,
68
+ unavailable,
69
+ artifacts,
70
+ used: used.map(entry),
71
+ ...flags.all ? {
72
+ others: others.map(entry),
73
+ uncached
74
+ } : {}
75
+ });
76
+ return ok ? 0 : 1;
77
+ }
78
+ for (const u of unavailable) out.error(`${t.error(t.symbols.fail)} ${u.platform}: ${u.reason}`);
79
+ print(out, artifacts, [...used, ...others]);
80
+ for (const key of uncached) out.print(t.dim(`lucent:${key}: the locked schema is not in this machine's SDK cache: only its used symbols are compared`));
81
+ const total = used.length;
82
+ out.print(removed + changed ? `${removed + changed} of ${total} used symbols changed: ${removed} removed, ${changed} changed ${t.dim(`(lucent sdk lock records the installed SDKs once the code is updated)`)}` : `${t.success(t.symbols.ok)} none of the ${total} used symbols changed`);
83
+ return ok ? 0 : 1;
84
+ }
85
+ function print(out, artifacts, changes) {
86
+ const t = out.theme;
87
+ const byModule = /* @__PURE__ */ new Map();
88
+ const of = (key) => byModule.get(key) ?? byModule.set(key, { changes: [] }).get(key);
89
+ for (const a of artifacts) of(a.module).artifacts = a;
90
+ for (const c of changes) {
91
+ if (c.change === "unchanged") continue;
92
+ const s = c.before ?? c.after;
93
+ of(`${s.platform}/${s.module}`).changes.push(c);
94
+ }
95
+ for (const [key, m] of [...byModule].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)) {
96
+ const [platform] = key.split("/");
97
+ out.print(`${t.brand(platform)} ${t.bold(`lucent:${key}`)}`);
98
+ if (m.artifacts) out.print(` ${t.dim("artifacts")} ${artifactText(m.artifacts)}`);
99
+ const rows = m.changes.map((c) => [
100
+ ` ${c.change === "added" ? t.dim(c.change) : c.change === "changed" ? t.warn(c.change) : t.error(c.change)}`,
101
+ displayName(c.before ?? c.after),
102
+ c.details.join("; ") || (c.after ?? c.before).signature
103
+ ]);
104
+ for (const line of table(rows)) out.print(line.trimEnd());
105
+ out.print("");
106
+ }
107
+ }
108
+ //#endregion
109
+ export { run };
@@ -0,0 +1,38 @@
1
+ import { r as plural, t as buildProject } from "./pipeline-BM_VM2X_.js";
2
+ import { d as writeUsage, t as LOCK_FILE } from "./sdk-usage-0ZFMAYg1.js";
3
+ import { t as plainSteps } from "./steps--_h-FFS7.js";
4
+ import path from "node:path";
5
+ //#region src/cli/commands/sdk-lock.ts
6
+ async function run({ root, flags, out }) {
7
+ const t = out.theme;
8
+ const platforms = typeof flags.platforms === "string" && flags.platforms ? flags.platforms.split(",") : void 0;
9
+ const result = await buildProject(root, {
10
+ mode: "check",
11
+ force: true,
12
+ platforms
13
+ }, plainSteps(() => {}, t), (n) => out.error(`${n.level === "ok" ? t.symbols.ok : t.warn(t.symbols.warn)} ${n.text}`));
14
+ const others = result.usage?.targets.join(",");
15
+ const failure = result.fatal ?? (result.ok ? void 0 : `${plural(result.diagnostics.length, "error")} in the project: lucent check shows them; the lock records a project that checks`) ?? (result.skipped.length ? [...result.skipped.map((s) => `${s.platform}: ${s.reason}`), `the lock needs every platform the project has code for: install the SDK, or lock ${others} alone with --platforms ${others}`].join("\n") : void 0);
16
+ if (failure || !result.usage) {
17
+ if (out.json) out.data({
18
+ ok: false,
19
+ error: failure ?? "the check recorded no SDK usage"
20
+ });
21
+ else out.error(`${t.error(t.symbols.fail)} ${failure ?? "the check recorded no SDK usage"}`);
22
+ return 1;
23
+ }
24
+ const usage = result.usage;
25
+ writeUsage(path.join(root, LOCK_FILE), usage);
26
+ const summary = {
27
+ ok: true,
28
+ file: LOCK_FILE,
29
+ targets: usage.targets,
30
+ modules: Object.keys(usage.modules).length,
31
+ symbols: usage.symbols.length
32
+ };
33
+ if (out.json) out.data(summary);
34
+ else out.print(`${t.success(t.symbols.ok)} ${LOCK_FILE} ${plural(summary.symbols, "symbol")} of ${plural(summary.modules, "module")}${usage.targets.length ? `, for ${usage.targets.join(" and ")}` : ""}`);
35
+ return 0;
36
+ }
37
+ //#endregion
38
+ export { run };
@@ -1,5 +1,5 @@
1
- import { C as extractionCount, D as sdkModule, O as sdkModules, g as projectFiles } from "./src-BD7f1_aZ.js";
2
- import { i as projectSdk, o as sdkImports } from "./project-D8tEet0k.js";
1
+ import { N as projectFiles, c as sdkModules, q as extractionCount, s as sdkModule } from "./src-ChnmWLwn.js";
2
+ import { c as sdkImports, o as projectSdk } from "./project-BKNoTEEp.js";
3
3
  import { t as plainSteps } from "./steps--_h-FFS7.js";
4
4
  //#region src/cli/commands/sdk-prefetch.ts
5
5
  async function run({ root, flags, out }) {
@@ -1,6 +1,6 @@
1
- import { D as sdkModule, E as sdkAvailable, S as cachedModules, g as projectFiles, k as sdkNames } from "./src-BD7f1_aZ.js";
1
+ import { G as cachedModules, N as projectFiles, Q as sdkNames, X as sdkAvailable, s as sdkModule } from "./src-ChnmWLwn.js";
2
+ import { c as sdkImports, o as projectSdk } from "./project-BKNoTEEp.js";
2
3
  import { i as table } from "./format-D9fnIMEx.js";
3
- import { i as projectSdk, o as sdkImports } from "./project-D8tEet0k.js";
4
4
  //#region src/cli/commands/sdk-search.ts
5
5
  function run({ root, positionals, out }) {
6
6
  const t = out.theme;
@@ -1,5 +1,5 @@
1
- import { D as sdkModule, E as sdkAvailable, O as sdkModules, y as sdkDts } from "./src-BD7f1_aZ.js";
2
- import { i as projectSdk } from "./project-D8tEet0k.js";
1
+ import { X as sdkAvailable, c as sdkModules, o as sdkDeclarations, s as sdkModule } from "./src-ChnmWLwn.js";
2
+ import { o as projectSdk } from "./project-BKNoTEEp.js";
3
3
  //#region src/cli/commands/sdk-show.ts
4
4
  function run({ root, positionals, out }) {
5
5
  const t = out.theme;
@@ -19,7 +19,7 @@ function run({ root, positionals, out }) {
19
19
  const r = sdkModule(platform, module, sdk);
20
20
  if ("missing" in r) continue;
21
21
  const [type, member] = parts.slice(n);
22
- const block = declaration(sdkDts(r.schema), type);
22
+ const block = declaration(sdkDeclarations(r.schema), type);
23
23
  if (!block) {
24
24
  out.error(`${t.error(t.symbols.fail)} no ${type} in lucent:${platform}/${module}: lucent sdk search ${type} finds similar names`);
25
25
  return 1;
@@ -29,13 +29,14 @@ function run({ root, positionals, out }) {
29
29
  out.error(`${t.error(t.symbols.fail)} ${type} has no member ${member}`);
30
30
  return 1;
31
31
  }
32
+ const from = r.schema.form === "source" ? "lucent:compose" : `lucent:${platform}/${module}`;
32
33
  if (out.json) out.data({
33
34
  platform,
34
35
  module,
35
36
  symbol,
36
37
  declaration: shown
37
38
  });
38
- else out.print(`${t.dim(`// lucent:${platform}/${module}`)}\n${highlight(shown, t)}`);
39
+ else out.print(`${t.dim(`// ${from}`)}\n${highlight(shown, t)}`);
39
40
  return 0;
40
41
  }
41
42
  }