@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.
- package/README.md +97 -0
- package/app.plugin.js +46 -10
- package/dist/{bench-CR3E7e2e.js → bench-eEez4jhQ.js} +10 -6
- package/dist/{build-CAIrRSYA.js → build-CpUjeHFz.js} +1 -1
- package/dist/{build-check-QozuNJm5.js → build-check-BA1ZEp9s.js} +28 -13
- package/dist/{check-1SCmYlqA.js → check-BZx3FgI6.js} +1 -1
- package/dist/cli.js +62 -13
- package/dist/{codes-CIuwXt1S.js → codes-D-6LxUqD.js} +163 -7
- package/dist/compiler.js +4 -4
- package/dist/{dashboard-B-NzjjaN.js → dashboard-CC-HXhcd.js} +2 -2
- package/dist/{dev-BYWMP7oC.js → dev-DI5yL8zx.js} +62 -23
- package/dist/{diagnostic-BM9sXmwl.js → diagnostic-BvwLZQS1.js} +3 -1
- package/dist/{doctor-C0PrfWT6.js → doctor-CTAX3euc.js} +1 -1
- package/dist/{doctor-DdR4JnVc.js → doctor-CrgOAV5L.js} +1 -1
- package/dist/{explain--vV1oaRl.js → explain-Byit07F-.js} +1 -1
- package/dist/{packages-HyskKIsY.js → packages-CSmKeaAh.js} +2 -33
- package/dist/pipeline-BM_VM2X_.js +700 -0
- package/dist/project-BKNoTEEp.js +342 -0
- package/dist/sdk-coverage-iiv3JqMp.js +113 -0
- package/dist/sdk-diff-ByJ1Gw-F.js +109 -0
- package/dist/sdk-lock-BQn7IyRs.js +38 -0
- package/dist/{sdk-prefetch-mo04JDZV.js → sdk-prefetch-Bv2pNega.js} +2 -2
- package/dist/{sdk-search-Iv4K3-8a.js → sdk-search-CPGJm_Ne.js} +2 -2
- package/dist/{sdk-show-CkrdlqlP.js → sdk-show-BUkLqRnA.js} +5 -4
- package/dist/sdk-usage-0ZFMAYg1.js +95 -0
- package/dist/src-ChnmWLwn.js +40851 -0
- package/dist/trace-Bi4hkmPx.js +139 -0
- package/lib/core.cjs +368 -1
- package/lib/sdk/android.d.ts +54 -1
- package/lib/sdk/compose.d.ts +94 -0
- package/lib/sdk/compose.schemas.json.gz +0 -0
- package/lib/sdk/core.d.ts +201 -0
- package/lib/sdk/ios.d.ts +75 -2
- package/lib/sdk/ui.d.ts +129 -0
- package/metro/transformer.cjs +11 -2
- package/package.json +4 -3
- package/runtime/cpp/lucent/abort.cpp +59 -11
- package/runtime/cpp/lucent/abort.h +22 -6
- package/runtime/cpp/lucent/array.h +12 -2
- package/runtime/cpp/lucent/async.h +101 -21
- package/runtime/cpp/lucent/bigint.cpp +898 -0
- package/runtime/cpp/lucent/bigint.h +302 -0
- package/runtime/cpp/lucent/buffer.cpp +228 -0
- package/runtime/cpp/lucent/buffer.h +328 -0
- package/runtime/cpp/lucent/builtins.cpp +4 -1
- package/runtime/cpp/lucent/bytes.h +21 -2
- package/runtime/cpp/lucent/callback.cpp +29 -0
- package/runtime/cpp/lucent/callback.h +230 -0
- package/runtime/cpp/lucent/compute.cpp +370 -0
- package/runtime/cpp/lucent/compute.h +455 -0
- package/runtime/cpp/lucent/conversions.h +111 -0
- package/runtime/cpp/lucent/core.h +16 -5
- package/runtime/cpp/lucent/equality.h +107 -28
- package/runtime/cpp/lucent/execution.cpp +416 -0
- package/runtime/cpp/lucent/execution.h +270 -0
- package/runtime/cpp/lucent/extension.cpp +97 -0
- package/runtime/cpp/lucent/extension.h +210 -0
- package/runtime/cpp/lucent/helpers.h +12 -5
- package/runtime/cpp/lucent/items.h +52 -0
- package/runtime/cpp/lucent/jserror.cpp +9 -0
- package/runtime/cpp/lucent/jserror.h +11 -0
- package/runtime/cpp/lucent/jsi/convert.cpp +138 -0
- package/runtime/cpp/lucent/jsi/convert.h +128 -59
- package/runtime/cpp/lucent/jsi/host.cpp +213 -35
- package/runtime/cpp/lucent/jsi/host.h +116 -16
- package/runtime/cpp/lucent/json.h +19 -1
- package/runtime/cpp/lucent/lifecycle.cpp +260 -0
- package/runtime/cpp/lucent/lifecycle.h +124 -0
- package/runtime/cpp/lucent/lucent.h +7 -0
- package/runtime/cpp/lucent/map.h +41 -7
- package/runtime/cpp/lucent/native.cpp +35 -47
- package/runtime/cpp/lucent/native.h +116 -26
- package/runtime/cpp/lucent/number.cpp +38 -38
- package/runtime/cpp/lucent/number.h +33 -0
- package/runtime/cpp/lucent/operation.h +65 -0
- package/runtime/cpp/lucent/ops.h +14 -6
- package/runtime/cpp/lucent/platform/android.cpp +223 -10
- package/runtime/cpp/lucent/platform/android.h +227 -4
- package/runtime/cpp/lucent/platform/android_activity.cpp +258 -0
- package/runtime/cpp/lucent/platform/android_requests.h +140 -0
- package/runtime/cpp/lucent/platform/compose.h +256 -0
- package/runtime/cpp/lucent/platform/ios.h +325 -25
- package/runtime/cpp/lucent/platform/ios.mm +1 -14
- package/runtime/cpp/lucent/platform/ios_ui.h +192 -0
- package/runtime/cpp/lucent/platform/ios_ui.mm +454 -0
- package/runtime/cpp/lucent/platform/swiftui.h +190 -0
- package/runtime/cpp/lucent/presentation.cpp +11 -0
- package/runtime/cpp/lucent/presentation.h +109 -0
- package/runtime/cpp/lucent/reactive.cpp +406 -0
- package/runtime/cpp/lucent/reactive.h +566 -0
- package/runtime/cpp/lucent/report.cpp +40 -0
- package/runtime/cpp/lucent/report.h +16 -0
- package/runtime/cpp/lucent/resource.cpp +83 -0
- package/runtime/cpp/lucent/resource.h +75 -0
- package/runtime/cpp/lucent/scheduler.cpp +38 -124
- package/runtime/cpp/lucent/scheduler.h +102 -83
- package/runtime/cpp/lucent/scope.cpp +308 -0
- package/runtime/cpp/lucent/scope.h +452 -0
- package/runtime/cpp/lucent/sizing.h +263 -0
- package/runtime/cpp/lucent/slots.h +231 -0
- package/runtime/cpp/lucent/trace.cpp +539 -0
- package/runtime/cpp/lucent/trace.h +251 -0
- package/runtime/cpp/lucent/transport.cpp +9 -0
- package/runtime/cpp/lucent/transport.h +341 -0
- package/runtime/cpp/lucent/view.cpp +123 -0
- package/runtime/cpp/lucent/view.h +157 -0
- package/runtime/cpp/rn/LucentComponentView.h +121 -0
- package/runtime/cpp/rn/LucentComponentView.mm +479 -0
- package/runtime/cpp/rn/LucentModule.cpp +37 -7
- package/runtime/cpp/rn/LucentModule.h +3 -0
- package/runtime/cpp/rn/LucentViewChildren.h +80 -0
- package/runtime/cpp/rn/LucentViewChildren.mm +211 -0
- package/runtime/cpp/rn/LucentViewRegistry.h +62 -0
- package/runtime/cpp/rn/LucentViewRequests.cpp +91 -0
- package/runtime/cpp/rn/LucentViewRequests.h +104 -0
- package/runtime/cpp/rn/LucentViewSizing.h +345 -0
- package/runtime/cpp/rn/LucentViewSlots.h +242 -0
- package/runtime/cpp/rn/LucentViewValues.h +125 -0
- package/runtime/cpp/rn/LucentViews.h +440 -0
- package/runtime/cpp/rn/LucentViewsAndroid.cpp +439 -0
- package/runtime/cpp/rn/LucentViewsAndroid.h +138 -0
- package/runtime/cpp/third_party/dragonbox/LICENSE-Boost +23 -0
- package/runtime/cpp/third_party/dragonbox/README.md +16 -0
- package/runtime/cpp/third_party/dragonbox/dragonbox.h +4440 -0
- package/runtime/js/index.d.ts +11 -1
- package/runtime/js/index.js +84 -8
- package/runtime/js/views.d.ts +38 -0
- package/runtime/js/views.js +226 -0
- package/runtime/native/android/CMakeLists.txt +4 -1
- package/runtime/native/android/src/compose/java/dev/lucent/compose/CompositionRules.kt +44 -0
- package/runtime/native/android/src/compose/java/dev/lucent/compose/LucentComposition.kt +161 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentActivities.java +292 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentChildren.java +174 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentHostView.java +232 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentInitializer.java +46 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentPackage.java +4 -3
- package/runtime/native/android/src/main/java/dev/lucent/LucentRequestActivity.java +92 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentSlotView.java +102 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentViewManager.java +149 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentViewManagers.java +16 -0
- package/runtime/native/android/src/main/java/dev/lucent/LucentViews.java +44 -0
- package/runtime/test/jsi/harness.cpp +9 -0
- package/schemas/build.schema.json +96 -1
- package/schemas/check.schema.json +56 -1
- package/schemas/lucent.schema.json +495 -9
- package/schemas/sdk-diff.schema.json +70 -0
- package/schemas/sdk-lock.schema.json +67 -0
- package/ts-plugin/index.js +85 -4
- package/dist/pipeline-CH7-2cxu.js +0 -232
- package/dist/project-D8tEet0k.js +0 -150
- package/dist/sdk-coverage-BoW_3Efd.js +0 -64
- package/dist/src-BD7f1_aZ.js +0 -11493
|
@@ -0,0 +1,700 @@
|
|
|
1
|
+
import { C as bindExtensions, F as moduleNamespace, M as platformOf, N as projectFiles, P as usesPlatforms, S as inNativePackage, Z as sdkModuleArtifacts, d as isUpToDate, j as moduleNameOf, l as deferredLibraryGradle, n as compile, p as writeNativePackage, q as extractionCount, s as sdkModule, u as inputsKey, v as resolveNative } from "./src-ChnmWLwn.js";
|
|
2
|
+
import { n as lucentPackages } from "./packages-CSmKeaAh.js";
|
|
3
|
+
import { a as projectHashes, c as sdkImports, i as pendingAndroidModules, l as staleAutolinking, n as mapLucentPaths, o as projectSdk, r as missingAppEntries, s as resolveAndroidDependencies, t as backgroundPrefetch, u as writeLinkedPackage } from "./project-BKNoTEEp.js";
|
|
4
|
+
import { a as lockProblems, c as sdkUsage, d as writeUsage, i as frozenFailure, l as usageReadable, n as USAGE_FILE, o as readUsage, s as sdkUnavailable, t as LOCK_FILE, u as usedModules } from "./sdk-usage-0ZFMAYg1.js";
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { createHash } from "node:crypto";
|
|
8
|
+
const ACTION_KINDS = [
|
|
9
|
+
"reinstall",
|
|
10
|
+
"relink",
|
|
11
|
+
"compile-native",
|
|
12
|
+
"repackage",
|
|
13
|
+
"reload-js"
|
|
14
|
+
];
|
|
15
|
+
function contentHash(data) {
|
|
16
|
+
return createHash("sha256").update(data).digest("hex").slice(0, 16);
|
|
17
|
+
}
|
|
18
|
+
function fileArtifact(root, file) {
|
|
19
|
+
return {
|
|
20
|
+
key: path.relative(root, path.resolve(file)).split(path.sep).join("/"),
|
|
21
|
+
hash: fs.existsSync(file) ? contentHash(fs.readFileSync(file)) : "missing"
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function byKey(a, b) {
|
|
25
|
+
return a.key < b.key ? -1 : a.key > b.key ? 1 : 0;
|
|
26
|
+
}
|
|
27
|
+
var BuildGraph = class {
|
|
28
|
+
nodes = /* @__PURE__ */ new Map();
|
|
29
|
+
timings = {};
|
|
30
|
+
startedAt = {};
|
|
31
|
+
started = Date.now();
|
|
32
|
+
mode;
|
|
33
|
+
constructor(mode) {
|
|
34
|
+
this.mode = mode;
|
|
35
|
+
}
|
|
36
|
+
record(id, kind, status, fields = {}) {
|
|
37
|
+
if (this.nodes.has(id)) throw new Error(`build graph: node ${id} recorded twice`);
|
|
38
|
+
const inputs = [...fields.inputs ?? []].sort(byKey);
|
|
39
|
+
const outputs = [...fields.outputs ?? []].sort(byKey);
|
|
40
|
+
const node = {
|
|
41
|
+
id,
|
|
42
|
+
kind,
|
|
43
|
+
status,
|
|
44
|
+
inputs,
|
|
45
|
+
outputs,
|
|
46
|
+
hash: contentHash(JSON.stringify({
|
|
47
|
+
kind,
|
|
48
|
+
inputs,
|
|
49
|
+
outputs
|
|
50
|
+
})),
|
|
51
|
+
...fields.detail !== void 0 ? { detail: fields.detail } : {},
|
|
52
|
+
...fields.log !== void 0 ? { log: fields.log } : {}
|
|
53
|
+
};
|
|
54
|
+
this.nodes.set(id, node);
|
|
55
|
+
if (fields.ms !== void 0) {
|
|
56
|
+
this.timings[id] = fields.ms;
|
|
57
|
+
this.startedAt[id] = Math.max(0, Date.now() - fields.ms - this.started);
|
|
58
|
+
}
|
|
59
|
+
return node;
|
|
60
|
+
}
|
|
61
|
+
get(id) {
|
|
62
|
+
return this.nodes.get(id);
|
|
63
|
+
}
|
|
64
|
+
toRecord(requiredAction, pendingActions = []) {
|
|
65
|
+
const nodes = [...this.nodes.values()];
|
|
66
|
+
return {
|
|
67
|
+
schemaVersion: 1,
|
|
68
|
+
mode: this.mode,
|
|
69
|
+
nodes,
|
|
70
|
+
requiredAction,
|
|
71
|
+
pendingActions,
|
|
72
|
+
timings: { ...this.timings },
|
|
73
|
+
startedAt: { ...this.startedAt }
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
function writeBuildRecord(file, record) {
|
|
78
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
79
|
+
const tmp = `${file}.${process.pid}.tmp`;
|
|
80
|
+
fs.writeFileSync(tmp, `${JSON.stringify(record, null, 2)}\n`);
|
|
81
|
+
fs.renameSync(tmp, file);
|
|
82
|
+
}
|
|
83
|
+
function requiredAction(next, targets, changedUnits) {
|
|
84
|
+
if (next.podInstall) return {
|
|
85
|
+
kind: "relink",
|
|
86
|
+
targets,
|
|
87
|
+
dependencyChanges: ["native files added or removed"]
|
|
88
|
+
};
|
|
89
|
+
if (next.rebuild) return {
|
|
90
|
+
kind: "compile-native",
|
|
91
|
+
targets,
|
|
92
|
+
changedUnits: [...changedUnits].sort()
|
|
93
|
+
};
|
|
94
|
+
if (next.reload) return { kind: "reload-js" };
|
|
95
|
+
return { kind: "none" };
|
|
96
|
+
}
|
|
97
|
+
//#endregion
|
|
98
|
+
//#region src/cli/changes.ts
|
|
99
|
+
const IGNORED = {
|
|
100
|
+
kind: void 0,
|
|
101
|
+
targets: []
|
|
102
|
+
};
|
|
103
|
+
const OUTPUT_ROLES = [
|
|
104
|
+
[/^manifest\.json$/, () => IGNORED],
|
|
105
|
+
[/^types\//, () => IGNORED],
|
|
106
|
+
[/^js\/_lucent\/identity\.js$/, () => IGNORED],
|
|
107
|
+
[/^js\//, () => ({
|
|
108
|
+
kind: "reload-js",
|
|
109
|
+
targets: "all"
|
|
110
|
+
})],
|
|
111
|
+
[/^cpp\/generated\/(ios|android|host)\//, (m) => ({
|
|
112
|
+
kind: "compile-native",
|
|
113
|
+
targets: [m[1]]
|
|
114
|
+
})],
|
|
115
|
+
[/^cpp\//, () => ({
|
|
116
|
+
kind: "compile-native",
|
|
117
|
+
targets: "all"
|
|
118
|
+
})],
|
|
119
|
+
[/^ios\//, () => ({
|
|
120
|
+
kind: "compile-native",
|
|
121
|
+
targets: ["ios"]
|
|
122
|
+
})],
|
|
123
|
+
[/^android\/src\/main\/java\//, () => ({
|
|
124
|
+
kind: "compile-native",
|
|
125
|
+
targets: ["android"]
|
|
126
|
+
})],
|
|
127
|
+
[/^android\/src\/main\/AndroidManifest\.xml$/, () => ({
|
|
128
|
+
kind: "reinstall",
|
|
129
|
+
targets: ["android"]
|
|
130
|
+
})],
|
|
131
|
+
[/^LucentNative\.podspec$/, () => ({
|
|
132
|
+
kind: "relink",
|
|
133
|
+
targets: ["ios"]
|
|
134
|
+
})],
|
|
135
|
+
[/^android\//, () => ({
|
|
136
|
+
kind: "relink",
|
|
137
|
+
targets: ["android"]
|
|
138
|
+
})]
|
|
139
|
+
];
|
|
140
|
+
const FIELD_ACTIONS = {
|
|
141
|
+
ios: {
|
|
142
|
+
nativeSources: "compile-native",
|
|
143
|
+
resources: "repackage",
|
|
144
|
+
resourceBundles: "repackage",
|
|
145
|
+
vendoredFrameworks: "relink"
|
|
146
|
+
},
|
|
147
|
+
android: {
|
|
148
|
+
nativeSources: "compile-native",
|
|
149
|
+
resources: "repackage",
|
|
150
|
+
assets: "repackage",
|
|
151
|
+
libraries: "relink",
|
|
152
|
+
nativeLibraries: "relink"
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
const APP_CONFIGURATION = ["infoPlist", "entitlements"];
|
|
156
|
+
function packageRoles(file, manifests) {
|
|
157
|
+
const roles = [];
|
|
158
|
+
for (const manifest of manifests) for (const platform of ["ios", "android"]) for (const [field, kind] of Object.entries(FIELD_ACTIONS[platform])) {
|
|
159
|
+
const listed = manifest[platform][field];
|
|
160
|
+
if ((Array.isArray(listed) ? listed : Object.values(listed).flat()).some((p) => file === inNativePackage(p) || file.startsWith(`${inNativePackage(p)}/`))) roles.push({
|
|
161
|
+
kind,
|
|
162
|
+
targets: [platform]
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
return roles;
|
|
166
|
+
}
|
|
167
|
+
function rolesOf(file, change) {
|
|
168
|
+
if (file.startsWith("packages/")) {
|
|
169
|
+
const roles = packageRoles(file, [change.manifest, ...change.previous ? [change.previous] : []]);
|
|
170
|
+
return roles.length ? roles : [{
|
|
171
|
+
kind: "relink",
|
|
172
|
+
targets: "all"
|
|
173
|
+
}];
|
|
174
|
+
}
|
|
175
|
+
for (const [pattern, role] of OUTPUT_ROLES) {
|
|
176
|
+
const m = pattern.exec(file);
|
|
177
|
+
if (m) return [role(m)];
|
|
178
|
+
}
|
|
179
|
+
return [{
|
|
180
|
+
kind: "relink",
|
|
181
|
+
targets: "all"
|
|
182
|
+
}];
|
|
183
|
+
}
|
|
184
|
+
const canonical = (v) => JSON.stringify(v, (_, x) => x && typeof x === "object" && !Array.isArray(x) ? Object.fromEntries(Object.entries(x).sort(([a], [b]) => a < b ? -1 : 1)) : x);
|
|
185
|
+
function classifyChanges(change) {
|
|
186
|
+
const actions = /* @__PURE__ */ new Map();
|
|
187
|
+
const need = (kind, targets, file) => {
|
|
188
|
+
const on = (targets === "all" ? change.targets : targets).filter((t) => change.targets.includes(t));
|
|
189
|
+
if (!on.length) return;
|
|
190
|
+
const action = actions.get(kind) ?? {
|
|
191
|
+
targets: /* @__PURE__ */ new Set(),
|
|
192
|
+
files: /* @__PURE__ */ new Set()
|
|
193
|
+
};
|
|
194
|
+
for (const t of on) action.targets.add(t);
|
|
195
|
+
action.files.add(file);
|
|
196
|
+
actions.set(kind, action);
|
|
197
|
+
};
|
|
198
|
+
for (const file of [...change.written, ...change.removed]) {
|
|
199
|
+
if (file === "resolved.json") {
|
|
200
|
+
for (const key of APP_CONFIGURATION) if (canonical(change.manifest.ios[key]) !== canonical(change.previous?.ios[key] ?? {})) need("reinstall", ["ios"], `resolved.json#ios.${key}`);
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
for (const role of rolesOf(file, change)) if (role.kind) need(role.kind, role.targets, file);
|
|
204
|
+
}
|
|
205
|
+
for (const file of [...change.added, ...change.removed]) for (const role of rolesOf(file, change)) if (role.kind && role.kind !== "reload-js") need("relink", role.targets === "all" ? ["ios"] : role.targets.filter((t) => t === "ios"), file);
|
|
206
|
+
return ACTION_KINDS.filter((kind) => actions.has(kind)).map((kind) => {
|
|
207
|
+
const { targets, files } = actions.get(kind);
|
|
208
|
+
return {
|
|
209
|
+
kind,
|
|
210
|
+
targets: change.targets.filter((t) => targets.has(t)),
|
|
211
|
+
files: [...files].sort()
|
|
212
|
+
};
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
const ACTION_TEXT = {
|
|
216
|
+
reinstall: "reinstall the app",
|
|
217
|
+
relink: "relink native dependencies",
|
|
218
|
+
"compile-native": "recompile native code",
|
|
219
|
+
repackage: "repackage resources",
|
|
220
|
+
"reload-js": "reload JavaScript"
|
|
221
|
+
};
|
|
222
|
+
function filesText(files, shown = 2) {
|
|
223
|
+
const more = files.length - shown;
|
|
224
|
+
return `${files.slice(0, shown).join(", ")}${more > 0 ? ` +${more} more` : ""}`;
|
|
225
|
+
}
|
|
226
|
+
//#endregion
|
|
227
|
+
//#region src/cli/pipeline.ts
|
|
228
|
+
const NONE = {
|
|
229
|
+
rebuild: false,
|
|
230
|
+
podInstall: false,
|
|
231
|
+
reload: false
|
|
232
|
+
};
|
|
233
|
+
async function buildProject(root, options, steps, notify) {
|
|
234
|
+
const t0 = Date.now();
|
|
235
|
+
const build = options.mode === "build";
|
|
236
|
+
let files = [];
|
|
237
|
+
let native;
|
|
238
|
+
let nativeInputs = [];
|
|
239
|
+
const graph = new BuildGraph(options.mode);
|
|
240
|
+
let targets = [];
|
|
241
|
+
let changedUnits = [];
|
|
242
|
+
const skipped = [];
|
|
243
|
+
const outcome = (o) => {
|
|
244
|
+
const next = o.next ?? NONE;
|
|
245
|
+
const actions = o.actions ?? [];
|
|
246
|
+
const record = graph.toRecord(requiredAction(next, targets, changedUnits), actions);
|
|
247
|
+
writeBuildRecord(path.join(root, ".lucent/build-record.json"), record);
|
|
248
|
+
return {
|
|
249
|
+
ok: false,
|
|
250
|
+
upToDate: false,
|
|
251
|
+
files,
|
|
252
|
+
modules: moduleSummary(files, void 0),
|
|
253
|
+
diagnostics: [],
|
|
254
|
+
warnings: [],
|
|
255
|
+
next,
|
|
256
|
+
actions,
|
|
257
|
+
nativeInputs,
|
|
258
|
+
record,
|
|
259
|
+
skipped,
|
|
260
|
+
ms: Date.now() - t0,
|
|
261
|
+
...o
|
|
262
|
+
};
|
|
263
|
+
};
|
|
264
|
+
const tResolve = Date.now();
|
|
265
|
+
try {
|
|
266
|
+
files = projectFiles(root);
|
|
267
|
+
const hashes = projectHashes(root);
|
|
268
|
+
native = resolveNative(lucentPackages(root), { hashes });
|
|
269
|
+
hashes.save();
|
|
270
|
+
nativeInputs = native.read;
|
|
271
|
+
} catch (e) {
|
|
272
|
+
graph.record("resolve", "resolve", "failed", {
|
|
273
|
+
detail: e.message,
|
|
274
|
+
ms: Date.now() - tResolve
|
|
275
|
+
});
|
|
276
|
+
return outcome({ fatal: e.message });
|
|
277
|
+
}
|
|
278
|
+
const superseded = (step) => {
|
|
279
|
+
graph.record(step, step === "generate" ? "generate" : "check", "skipped", { detail: "superseded by a newer change" });
|
|
280
|
+
return outcome({ superseded: true });
|
|
281
|
+
};
|
|
282
|
+
graph.record("resolve", "resolve", "ok", {
|
|
283
|
+
inputs: [{
|
|
284
|
+
key: "native-dependencies",
|
|
285
|
+
hash: contentHash(JSON.stringify(native.manifest))
|
|
286
|
+
}, ...packageInputs(native)],
|
|
287
|
+
ms: Date.now() - tResolve
|
|
288
|
+
});
|
|
289
|
+
if (options.signal?.aborted) return superseded("check");
|
|
290
|
+
let extensions = [];
|
|
291
|
+
if (native.extensions.length) {
|
|
292
|
+
const t = Date.now();
|
|
293
|
+
const inputs = native.extensions.map((e) => ({
|
|
294
|
+
key: `ext/${e.name}`,
|
|
295
|
+
hash: e.hash
|
|
296
|
+
}));
|
|
297
|
+
try {
|
|
298
|
+
extensions = bindExtensions(native.extensions);
|
|
299
|
+
} catch (e) {
|
|
300
|
+
graph.record("extract:extensions", "extract", "failed", {
|
|
301
|
+
inputs,
|
|
302
|
+
detail: e.message,
|
|
303
|
+
ms: Date.now() - t
|
|
304
|
+
});
|
|
305
|
+
return outcome({ fatal: e.message });
|
|
306
|
+
}
|
|
307
|
+
graph.record("extract:extensions", "extract", "ok", {
|
|
308
|
+
inputs,
|
|
309
|
+
ms: Date.now() - t
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
const sdk = projectSdk(root, native);
|
|
313
|
+
const outDir = path.resolve(root, options.out ?? ".lucent/native");
|
|
314
|
+
let lock;
|
|
315
|
+
const lockProblem = (detail) => {
|
|
316
|
+
graph.record("resolve:lock", "resolve", "failed", { detail });
|
|
317
|
+
return outcome({ fatal: detail });
|
|
318
|
+
};
|
|
319
|
+
if (options.frozen) {
|
|
320
|
+
try {
|
|
321
|
+
lock = readUsage(path.join(root, LOCK_FILE));
|
|
322
|
+
} catch (e) {
|
|
323
|
+
return lockProblem(e.message);
|
|
324
|
+
}
|
|
325
|
+
if (!lock) return lockProblem(`--frozen needs ${LOCK_FILE}: run lucent sdk lock and commit it`);
|
|
326
|
+
for (const p of lock.targets) {
|
|
327
|
+
if (options.platforms && !options.platforms.includes(p)) continue;
|
|
328
|
+
const why = sdkUnavailable(p, sdk);
|
|
329
|
+
if (why) return lockProblem(`the SDK lock requires ${p}, whose SDK is unavailable: ${why}`);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
const libraryGradle = path.join(outDir, "android/build.gradle");
|
|
333
|
+
const configured = fs.existsSync(libraryGradle) ? fs.readFileSync(libraryGradle, "utf8") : void 0;
|
|
334
|
+
let platforms = options.platforms;
|
|
335
|
+
let deferAndroid = false;
|
|
336
|
+
let deferReason = "its dependencies are resolved by the Gradle build";
|
|
337
|
+
if (build && (!platforms || platforms.includes("android"))) {
|
|
338
|
+
if (writeLinkedPackage(root, outDir, native) && process.env.LUCENT_GRADLE_CLASSPATH) {
|
|
339
|
+
const detail = `this Gradle build read the app's autolinking config before ${path.relative(root, outDir)} existed, so the app would not link Lucent: build again`;
|
|
340
|
+
graph.record("resolve:android", "resolve", "failed", { detail });
|
|
341
|
+
return outcome({ fatal: detail });
|
|
342
|
+
}
|
|
343
|
+
steps.start("android-dependencies", "Android dependencies");
|
|
344
|
+
await steps.flush();
|
|
345
|
+
const t = Date.now();
|
|
346
|
+
const deps = resolveAndroidDependencies(root, files, sdk, native.manifest, !!options.force);
|
|
347
|
+
const label = "Android dependencies";
|
|
348
|
+
graph.record("resolve:android", "resolve", deps.status === "resolved" ? "ok" : deps.status === "deferred" ? "skipped" : deps.status === "failed" ? "failed" : "cached", {
|
|
349
|
+
...deps.status === "failed" ? { detail: deps.detail } : {},
|
|
350
|
+
ms: Date.now() - t
|
|
351
|
+
});
|
|
352
|
+
if (deps.status === "resolved") steps.finish({
|
|
353
|
+
name: "android-dependencies",
|
|
354
|
+
label,
|
|
355
|
+
status: "ok",
|
|
356
|
+
detail: "resolved with Gradle",
|
|
357
|
+
ms: Date.now() - t
|
|
358
|
+
});
|
|
359
|
+
else if (deps.status === "cached") steps.finish({
|
|
360
|
+
name: "android-dependencies",
|
|
361
|
+
label,
|
|
362
|
+
status: "cached"
|
|
363
|
+
});
|
|
364
|
+
else if (deps.status === "failed") steps.finish({
|
|
365
|
+
name: "android-dependencies",
|
|
366
|
+
label,
|
|
367
|
+
status: "failed",
|
|
368
|
+
detail: deps.detail
|
|
369
|
+
});
|
|
370
|
+
else if (deps.status === "deferred") {
|
|
371
|
+
deferAndroid = true;
|
|
372
|
+
steps.finish({
|
|
373
|
+
name: "android-dependencies",
|
|
374
|
+
label,
|
|
375
|
+
status: "skipped",
|
|
376
|
+
detail: "resolved by the Gradle build"
|
|
377
|
+
});
|
|
378
|
+
notify({
|
|
379
|
+
level: "warn",
|
|
380
|
+
text: "the app's Android dependencies are not resolved yet: skipped Android here; the Gradle build compiles it (its lucentBuild task)"
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
if (!deferAndroid && !platforms?.includes("android")) {
|
|
385
|
+
const pending = pendingAndroidModules(root, files, sdk).map((m) => `lucent:android/${m}`);
|
|
386
|
+
if (pending.length) {
|
|
387
|
+
deferAndroid = true;
|
|
388
|
+
deferReason = "the app has no Android project yet";
|
|
389
|
+
notify({
|
|
390
|
+
level: "warn",
|
|
391
|
+
text: `${pending.join(", ")} ${pending.length === 1 ? "is" : "are"} untyped: the app has no Android project to resolve ${pending.length === 1 ? "it" : "them"} yet. Checked after expo prebuild, or once android/ exists${platforms ? "" : "; skipped Android here"}`
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
if (!platforms && files.some((f) => platformOf(f) || usesPlatforms(f))) {
|
|
396
|
+
for (const p of ["ios", "android"]) {
|
|
397
|
+
const why = sdkUnavailable(p, sdk);
|
|
398
|
+
if (why) {
|
|
399
|
+
skipped.push({
|
|
400
|
+
platform: p,
|
|
401
|
+
reason: why
|
|
402
|
+
});
|
|
403
|
+
notify({
|
|
404
|
+
level: "warn",
|
|
405
|
+
text: `${why}; skipped ${p === "ios" ? "iOS" : "Android"} (build it with --platforms ${p} once the SDK is installed)`
|
|
406
|
+
});
|
|
407
|
+
} else if (p === "android" && deferAndroid) skipped.push({
|
|
408
|
+
platform: p,
|
|
409
|
+
reason: deferReason
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
const installed = ["ios", "android"].filter((p) => !skipped.some((s) => s.platform === p));
|
|
413
|
+
if (!installed.length) {
|
|
414
|
+
const detail = deferAndroid ? `no platform to build here: ${skipped.map((s) => `${s.platform}: ${s.reason}`).join("; ")}` : "no platform SDK is installed";
|
|
415
|
+
graph.record("resolve:platforms", "resolve", "failed", { detail });
|
|
416
|
+
return outcome({ fatal: detail });
|
|
417
|
+
}
|
|
418
|
+
platforms = installed;
|
|
419
|
+
if (build && options.prefetch) backgroundPrefetch(root, files, installed);
|
|
420
|
+
}
|
|
421
|
+
for (const { platform, reason } of skipped) if (lock?.targets.includes(platform)) return lockProblem(`the SDK lock requires ${platform}, which this build skips: ${reason}`);
|
|
422
|
+
if (build && outDir === path.join(root, ".lucent/native")) {
|
|
423
|
+
const mapped = mapLucentPaths(root);
|
|
424
|
+
if (mapped) notify(mapped);
|
|
425
|
+
}
|
|
426
|
+
const modules = moduleSummary(files, platforms);
|
|
427
|
+
const moduleCount = modules.length;
|
|
428
|
+
targets = [...platforms ?? ["ios", "android"]];
|
|
429
|
+
const built = (platforms ?? []).filter((p) => p !== "host");
|
|
430
|
+
const checkInputs = [...files.map((f) => fileArtifact(root, f)), {
|
|
431
|
+
key: "targets",
|
|
432
|
+
hash: contentHash(targets.join(","))
|
|
433
|
+
}];
|
|
434
|
+
const key = inputsKey(files, outDir) + (platforms ? `:${platforms.join(",")}` : "") + `:${createHash("sha256").update(JSON.stringify(native.manifest)).digest("hex").slice(0, 12)}`;
|
|
435
|
+
const checked = path.join(root, ".lucent/check.json");
|
|
436
|
+
const cacheable = !options.force && !lock && usageReadable(path.join(root, ".lucent/sdk-usage.json"));
|
|
437
|
+
if (!build && cacheable) {
|
|
438
|
+
if ((fs.existsSync(checked) ? JSON.parse(fs.readFileSync(checked, "utf8")) : {}).inputs === key) {
|
|
439
|
+
graph.record("check", "check", "cached", { inputs: checkInputs });
|
|
440
|
+
return outcome({
|
|
441
|
+
ok: true,
|
|
442
|
+
upToDate: true,
|
|
443
|
+
modules
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
if (build && cacheable && isUpToDate(outDir, key)) {
|
|
448
|
+
graph.record("check", "check", "cached", { inputs: checkInputs });
|
|
449
|
+
graph.record("generate", "generate", "cached", { outputs: packageArtifacts(root, outDir) });
|
|
450
|
+
steps.finish({
|
|
451
|
+
name: "up-to-date",
|
|
452
|
+
label: "Up to date",
|
|
453
|
+
status: "ok",
|
|
454
|
+
detail: `${plural(moduleCount, "module")}, nothing to build`,
|
|
455
|
+
ms: Date.now() - t0
|
|
456
|
+
});
|
|
457
|
+
return outcome({
|
|
458
|
+
ok: true,
|
|
459
|
+
upToDate: true,
|
|
460
|
+
modules
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
const imports = sdkImports(files);
|
|
464
|
+
const wanted = ["ios", "android"].flatMap((p) => (platforms ?? []).includes(p) ? imports[p].map((m) => [p, m]) : []);
|
|
465
|
+
if (wanted.length) {
|
|
466
|
+
const names = wanted.map(([, m]) => m);
|
|
467
|
+
const listed = names.length > 3 ? `${names.slice(0, 3).join(" · ")} +${names.length - 3} more` : names.join(" · ");
|
|
468
|
+
steps.start("sdk", `SDK bindings ${listed}`);
|
|
469
|
+
await steps.flush();
|
|
470
|
+
const t = Date.now();
|
|
471
|
+
const before = extractionCount();
|
|
472
|
+
for (const [p, m] of wanted) sdkModule(p, m, sdk);
|
|
473
|
+
const extracted = extractionCount() - before;
|
|
474
|
+
const read = wanted.map(([p, m]) => ({
|
|
475
|
+
key: `${p}/${m}`,
|
|
476
|
+
artifacts: sdkModuleArtifacts(p, m, sdk)
|
|
477
|
+
}));
|
|
478
|
+
const artifacts = new Map(read.flatMap((r) => r.artifacts).map((a) => [a.id, a]));
|
|
479
|
+
const identity = (a) => `${a.id}#${a.contentHash}`;
|
|
480
|
+
graph.record("extract", "extract", extracted ? "ok" : "cached", {
|
|
481
|
+
inputs: [...read.map((r) => ({
|
|
482
|
+
key: r.key,
|
|
483
|
+
hash: contentHash(r.artifacts.map(identity).join("\n"))
|
|
484
|
+
})), ...[...artifacts.values()].map((a) => ({
|
|
485
|
+
key: a.id,
|
|
486
|
+
hash: a.contentHash
|
|
487
|
+
}))],
|
|
488
|
+
detail: listed,
|
|
489
|
+
ms: Date.now() - t
|
|
490
|
+
});
|
|
491
|
+
steps.finish({
|
|
492
|
+
name: "sdk",
|
|
493
|
+
label: "SDK bindings",
|
|
494
|
+
status: extracted ? "ok" : "cached",
|
|
495
|
+
detail: listed,
|
|
496
|
+
ms: extracted ? Date.now() - t : void 0
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
if (lock) {
|
|
500
|
+
const locked = Object.keys(lock.modules).filter((k) => built.includes(k.split("/")[0]));
|
|
501
|
+
const problems = lockProblems(lock, usedModules([...wanted.map(([p, m]) => `${p}/${m}`), ...locked], sdk));
|
|
502
|
+
if (problems.length) {
|
|
503
|
+
graph.record("extract:lock", "extract", "failed", { detail: problems.join("\n") });
|
|
504
|
+
return outcome({ fatal: frozenFailure(problems) });
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
steps.start("check", `Checking ${plural(moduleCount, "module")}`);
|
|
508
|
+
await steps.flush();
|
|
509
|
+
const tCheck = Date.now();
|
|
510
|
+
const deferred = deferAndroid && !platforms?.includes("android") ? ["android"] : [];
|
|
511
|
+
const result = compile(files, {
|
|
512
|
+
platforms,
|
|
513
|
+
sdk,
|
|
514
|
+
extensions,
|
|
515
|
+
deferred
|
|
516
|
+
});
|
|
517
|
+
const relative = (d) => ({
|
|
518
|
+
...d,
|
|
519
|
+
file: d.file && path.relative(root, d.file)
|
|
520
|
+
});
|
|
521
|
+
const diagnostics = result.diagnostics.map(relative);
|
|
522
|
+
const warnings = (result.warnings ?? []).map(relative);
|
|
523
|
+
if (!result.ok) {
|
|
524
|
+
graph.record("check", "check", "failed", {
|
|
525
|
+
inputs: checkInputs,
|
|
526
|
+
detail: plural(diagnostics.length, "error"),
|
|
527
|
+
ms: Date.now() - tCheck
|
|
528
|
+
});
|
|
529
|
+
steps.finish({
|
|
530
|
+
name: "check",
|
|
531
|
+
label: `Checked ${plural(moduleCount, "module")}`,
|
|
532
|
+
status: "failed",
|
|
533
|
+
detail: plural(diagnostics.length, "error"),
|
|
534
|
+
ms: Date.now() - tCheck
|
|
535
|
+
});
|
|
536
|
+
return outcome({
|
|
537
|
+
modules,
|
|
538
|
+
diagnostics,
|
|
539
|
+
warnings
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
const names = [...result.proxies.keys()];
|
|
543
|
+
const usage = sdkUsage(result.sdkUses ?? [], built, wanted.map(([p, m]) => `${p}/${m}`), sdk);
|
|
544
|
+
writeUsage(path.join(root, USAGE_FILE), usage);
|
|
545
|
+
const unlocked = lock ? lockProblems(lock, usage.modules, usage.symbols) : [];
|
|
546
|
+
if (unlocked.length) {
|
|
547
|
+
graph.record("check", "check", "failed", {
|
|
548
|
+
inputs: checkInputs,
|
|
549
|
+
detail: unlocked.join("\n"),
|
|
550
|
+
ms: Date.now() - tCheck
|
|
551
|
+
});
|
|
552
|
+
steps.finish({
|
|
553
|
+
name: "check",
|
|
554
|
+
label: `Checked ${plural(moduleCount, "module")}`,
|
|
555
|
+
status: "failed",
|
|
556
|
+
detail: `not the SDK symbols ${LOCK_FILE} records`,
|
|
557
|
+
ms: Date.now() - tCheck
|
|
558
|
+
});
|
|
559
|
+
return outcome({
|
|
560
|
+
modules,
|
|
561
|
+
warnings,
|
|
562
|
+
usage,
|
|
563
|
+
fatal: frozenFailure(unlocked)
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
graph.record("check", "check", "ok", {
|
|
567
|
+
inputs: checkInputs,
|
|
568
|
+
ms: Date.now() - tCheck
|
|
569
|
+
});
|
|
570
|
+
steps.finish({
|
|
571
|
+
name: "check",
|
|
572
|
+
label: `Checked ${plural(names.length, "module")}`,
|
|
573
|
+
status: "ok",
|
|
574
|
+
ms: Date.now() - tCheck
|
|
575
|
+
});
|
|
576
|
+
if (!build) {
|
|
577
|
+
fs.mkdirSync(path.dirname(checked), { recursive: true });
|
|
578
|
+
fs.writeFileSync(checked, `${JSON.stringify({ inputs: key })}\n`);
|
|
579
|
+
return outcome({
|
|
580
|
+
ok: true,
|
|
581
|
+
modules,
|
|
582
|
+
warnings,
|
|
583
|
+
usage
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
if (options.signal?.aborted) return superseded("generate");
|
|
587
|
+
const resolvedFile = path.join(outDir, "resolved.json");
|
|
588
|
+
const previous = fs.existsSync(resolvedFile) ? JSON.parse(fs.readFileSync(resolvedFile, "utf8")) : void 0;
|
|
589
|
+
const tWrite = Date.now();
|
|
590
|
+
const w = writeNativePackage(result, outDir, {
|
|
591
|
+
inputsKey: key,
|
|
592
|
+
native,
|
|
593
|
+
androidDeferred: deferred.includes("android")
|
|
594
|
+
});
|
|
595
|
+
const inPackage = (f) => path.relative(outDir, f).split(path.sep).join("/");
|
|
596
|
+
const written = new Set(w.written.map(inPackage));
|
|
597
|
+
if (written.has("react-native.config.js")) staleAutolinking(root);
|
|
598
|
+
if (process.env.LUCENT_GRADLE_CLASSPATH && configured !== void 0 && fs.readFileSync(libraryGradle, "utf8") !== configured && configured !== deferredLibraryGradle(native)) {
|
|
599
|
+
const detail = `this Gradle build configured the Lucent Android library before its build.gradle changed (${path.relative(root, libraryGradle)}: Kotlin shims, packages' Android needs), so it would build it as it was: build again`;
|
|
600
|
+
graph.record("generate", "generate", "failed", {
|
|
601
|
+
detail,
|
|
602
|
+
ms: Date.now() - tWrite
|
|
603
|
+
});
|
|
604
|
+
return outcome({ fatal: detail });
|
|
605
|
+
}
|
|
606
|
+
graph.record("generate", "generate", "ok", {
|
|
607
|
+
outputs: packageArtifacts(root, outDir),
|
|
608
|
+
detail: `${written.size} written, ${w.removed.length} removed`,
|
|
609
|
+
ms: Date.now() - tWrite
|
|
610
|
+
});
|
|
611
|
+
changedUnits = [...written].filter((f) => f.startsWith("cpp/"));
|
|
612
|
+
const changed = names.filter((n) => [...written].some((f) => f.startsWith("cpp/generated/") && path.basename(f).startsWith(`${moduleNamespace(n)}.`))).length;
|
|
613
|
+
steps.finish({
|
|
614
|
+
name: "generate",
|
|
615
|
+
label: "Generated C++",
|
|
616
|
+
status: "ok",
|
|
617
|
+
detail: changed === names.length ? `${changed} changed` : `${changed} changed, ${names.length - changed} cached`,
|
|
618
|
+
ms: Date.now() - tWrite
|
|
619
|
+
});
|
|
620
|
+
steps.finish({
|
|
621
|
+
name: "package",
|
|
622
|
+
label: "Native package",
|
|
623
|
+
status: "ok",
|
|
624
|
+
detail: path.relative(root, outDir) || "."
|
|
625
|
+
});
|
|
626
|
+
for (const n of missingAppEntries(root, native.manifest)) notify(n);
|
|
627
|
+
const nativeChanged = w.removed.length > 0 || [...written].some((f) => !f.startsWith("js/") && f !== "manifest.json");
|
|
628
|
+
return outcome({
|
|
629
|
+
ok: true,
|
|
630
|
+
modules,
|
|
631
|
+
warnings,
|
|
632
|
+
usage,
|
|
633
|
+
actions: classifyChanges({
|
|
634
|
+
written: [...written],
|
|
635
|
+
added: w.added.map(inPackage),
|
|
636
|
+
removed: w.removed.map(inPackage),
|
|
637
|
+
manifest: native.manifest,
|
|
638
|
+
previous,
|
|
639
|
+
targets
|
|
640
|
+
}),
|
|
641
|
+
next: {
|
|
642
|
+
rebuild: nativeChanged,
|
|
643
|
+
podInstall: w.structureChanged,
|
|
644
|
+
reload: !nativeChanged && [...written].some((f) => f.startsWith("js/"))
|
|
645
|
+
}
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
function packageInputs(native) {
|
|
649
|
+
const { ios, android } = native.manifest;
|
|
650
|
+
const listed = [
|
|
651
|
+
...ios.nativeSources,
|
|
652
|
+
...ios.resources,
|
|
653
|
+
...Object.values(ios.resourceBundles).flat(),
|
|
654
|
+
...ios.vendoredFrameworks,
|
|
655
|
+
...android.nativeSources,
|
|
656
|
+
...android.resources,
|
|
657
|
+
...android.assets,
|
|
658
|
+
...android.libraries,
|
|
659
|
+
...android.nativeLibraries
|
|
660
|
+
];
|
|
661
|
+
return [...new Map(listed.map((p) => [inNativePackage(p), p.hash])).entries()].map(([key, hash]) => ({
|
|
662
|
+
key,
|
|
663
|
+
hash
|
|
664
|
+
}));
|
|
665
|
+
}
|
|
666
|
+
function packageArtifacts(root, outDir) {
|
|
667
|
+
const out = [];
|
|
668
|
+
const walk = (dir) => {
|
|
669
|
+
for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
670
|
+
const full = path.join(dir, e.name);
|
|
671
|
+
if (e.isDirectory()) walk(full);
|
|
672
|
+
else if (full !== path.join(outDir, "manifest.json")) out.push(fileArtifact(root, full));
|
|
673
|
+
}
|
|
674
|
+
};
|
|
675
|
+
if (fs.existsSync(outDir)) walk(outDir);
|
|
676
|
+
return out;
|
|
677
|
+
}
|
|
678
|
+
function moduleSummary(files, platforms) {
|
|
679
|
+
const built = (platforms ?? ["ios", "android"]).filter((p) => p !== "host");
|
|
680
|
+
const byModule = /* @__PURE__ */ new Map();
|
|
681
|
+
for (const f of files) {
|
|
682
|
+
const set = byModule.get(moduleNameOf(f)) ?? /* @__PURE__ */ new Set();
|
|
683
|
+
const p = platformOf(f);
|
|
684
|
+
if (p) set.add(p);
|
|
685
|
+
else if (usesPlatforms(f)) for (const b of built) set.add(b);
|
|
686
|
+
byModule.set(moduleNameOf(f), set);
|
|
687
|
+
}
|
|
688
|
+
return [...byModule].map(([name, set]) => ({
|
|
689
|
+
name,
|
|
690
|
+
platforms: set.size ? ["ios", "android"].filter((p) => set.has(p)) : ["shared"]
|
|
691
|
+
}));
|
|
692
|
+
}
|
|
693
|
+
function plural(n, word) {
|
|
694
|
+
return `${n} ${word}${n === 1 ? "" : "s"}`;
|
|
695
|
+
}
|
|
696
|
+
function nextText(next) {
|
|
697
|
+
return next.rebuild ? `rebuild the app${next.podInstall ? " (iOS: pod install first)" : ""}` : next.reload ? "reload the app" : "nothing to do: the native package did not change";
|
|
698
|
+
}
|
|
699
|
+
//#endregion
|
|
700
|
+
export { filesText as a, ACTION_TEXT as i, nextText as n, plural as r, buildProject as t };
|