@deveco-test/deveco-code 0.0.0-TD → 0.0.0-test-harness.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 (6) hide show
  1. package/CHANGELOG.md +394 -178
  2. package/LICENSE +21 -21
  3. package/README.md +333 -328
  4. package/bin/deveco +206 -206
  5. package/package.json +6 -5
  6. package/postinstall.mjs +325 -217
package/postinstall.mjs CHANGED
@@ -1,217 +1,325 @@
1
- #!/usr/bin/env node
2
-
3
- import childProcess from "child_process"
4
- import fs from "fs"
5
- import os from "os"
6
- import path from "path"
7
- import { createRequire } from "module"
8
- import { fileURLToPath } from "url"
9
-
10
- const __dirname = path.dirname(fileURLToPath(import.meta.url))
11
- const require = createRequire(import.meta.url)
12
- const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, "package.json"), "utf8"))
13
-
14
- const platformMap = {
15
- darwin: "darwin",
16
- linux: "linux",
17
- win32: "windows",
18
- }
19
- const archMap = {
20
- x64: "x64",
21
- arm64: "arm64",
22
- arm: "arm",
23
- }
24
-
25
- const platform = platformMap[os.platform()] ?? os.platform()
26
- const arch = archMap[os.arch()] ?? os.arch()
27
- const scope = packageJson.name && packageJson.name.includes("/") ? packageJson.name.split("/")[0] : "@deveco"
28
- const base = `${scope}/deveco-code-${platform}-${arch}`
29
- const sourceBinary = platform === "windows" ? "deveco.exe" : "deveco"
30
- const targetBinary = path.join(__dirname, "bin", "deveco.exe")
31
-
32
- function supportsAvx2() {
33
- if (arch !== "x64") return false
34
-
35
- if (platform === "linux") {
36
- try {
37
- return /(^|\s)avx2(\s|$)/i.test(fs.readFileSync("/proc/cpuinfo", "utf8"))
38
- } catch {
39
- return false
40
- }
41
- }
42
-
43
- if (platform === "darwin") {
44
- try {
45
- const result = childProcess.spawnSync("sysctl", ["-n", "hw.optional.avx2_0"], {
46
- encoding: "utf8",
47
- timeout: 1500,
48
- })
49
- if (result.status !== 0) return false
50
- return (result.stdout || "").trim() === "1"
51
- } catch {
52
- return false
53
- }
54
- }
55
-
56
- if (platform === "windows") {
57
- const command =
58
- '(Add-Type -MemberDefinition "[DllImport(""kernel32.dll"")] public static extern bool IsProcessorFeaturePresent(int ProcessorFeature);" -Name Kernel32 -Namespace Win32 -PassThru)::IsProcessorFeaturePresent(40)'
59
-
60
- for (const executable of ["powershell.exe", "pwsh.exe", "pwsh", "powershell"]) {
61
- try {
62
- const result = childProcess.spawnSync(executable, ["-NoProfile", "-NonInteractive", "-Command", command], {
63
- encoding: "utf8",
64
- timeout: 3000,
65
- windowsHide: true,
66
- })
67
- if (result.status !== 0) continue
68
- const output = (result.stdout || "").trim().toLowerCase()
69
- if (output === "true" || output === "1") return true
70
- if (output === "false" || output === "0") return false
71
- } catch {
72
- continue
73
- }
74
- }
75
- }
76
-
77
- return false
78
- }
79
-
80
- function isMusl() {
81
- if (platform !== "linux") return false
82
-
83
- try {
84
- if (fs.existsSync("/etc/alpine-release")) return true
85
- } catch {
86
- // Ignore filesystem probes that are blocked by the host.
87
- }
88
-
89
- try {
90
- const result = childProcess.spawnSync("ldd", ["--version"], { encoding: "utf8" })
91
- return `${result.stdout || ""}${result.stderr || ""}`.toLowerCase().includes("musl")
92
- } catch {
93
- return false
94
- }
95
- }
96
-
97
- function packageNames() {
98
- const baseline = arch === "x64" && !supportsAvx2()
99
-
100
- if (platform === "linux") {
101
- if (isMusl()) {
102
- if (arch === "x64")
103
- return baseline
104
- ? [`${base}-baseline-musl`, `${base}-musl`, `${base}-baseline`, base]
105
- : [`${base}-musl`, `${base}-baseline-musl`, base, `${base}-baseline`]
106
- return [`${base}-musl`, base]
107
- }
108
-
109
- if (arch === "x64")
110
- return baseline
111
- ? [`${base}-baseline`, base, `${base}-baseline-musl`, `${base}-musl`]
112
- : [base, `${base}-baseline`, `${base}-musl`, `${base}-baseline-musl`]
113
- return [base, `${base}-musl`]
114
- }
115
-
116
- if (arch === "x64") return baseline ? [`${base}-baseline`, base] : [base, `${base}-baseline`]
117
- return [base]
118
- }
119
-
120
- function resolvePackageDir(name) {
121
- const packageJsonPath = require.resolve(`${name}/package.json`)
122
- return path.dirname(packageJsonPath)
123
- }
124
-
125
- function resolveBinary(name) {
126
- const binaryPath = path.join(resolvePackageDir(name), "bin", sourceBinary)
127
- if (!fs.existsSync(binaryPath)) throw new Error(`Binary not found at ${binaryPath}`)
128
- return binaryPath
129
- }
130
-
131
- function copyDir(src, dst) {
132
- if (!fs.existsSync(dst)) fs.mkdirSync(dst, { recursive: true })
133
- for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
134
- const srcPath = path.join(src, entry.name)
135
- const dstPath = path.join(dst, entry.name)
136
- if (entry.isDirectory()) {
137
- copyDir(srcPath, dstPath)
138
- } else {
139
- fs.copyFileSync(srcPath, dstPath)
140
- }
141
- }
142
- }
143
-
144
- function copyVendor(packageDir) {
145
- const vendorSrc = path.join(packageDir, "vendor")
146
- const vendorDst = path.join(__dirname, "vendor")
147
- if (fs.existsSync(vendorSrc)) {
148
- copyDir(vendorSrc, vendorDst)
149
- }
150
- }
151
-
152
- function installPackage(name) {
153
- const version = packageJson.optionalDependencies?.[name]
154
- if (!version) return
155
-
156
- const temp = fs.mkdtempSync(path.join(os.tmpdir(), "opencode-install-"))
157
- try {
158
- const result = childProcess.spawnSync(
159
- "npm",
160
- ["install", "--ignore-scripts", "--no-save", "--loglevel=error", "--prefix", temp, `${name}@${version}`],
161
- { stdio: "inherit", windowsHide: true },
162
- )
163
- if (result.status !== 0) return
164
- const packageDir = path.join(temp, "node_modules", name)
165
- copyBinary(path.join(packageDir, "bin", sourceBinary), targetBinary)
166
- copyVendor(packageDir)
167
- return true
168
- } finally {
169
- fs.rmSync(temp, { recursive: true, force: true })
170
- }
171
- }
172
-
173
- function copyBinary(source, target) {
174
- if (!fs.existsSync(source)) throw new Error(`Binary not found at ${source}`)
175
- fs.mkdirSync(path.dirname(target), { recursive: true })
176
- if (fs.existsSync(target)) fs.unlinkSync(target)
177
- try {
178
- fs.linkSync(source, target)
179
- } catch {
180
- fs.copyFileSync(source, target)
181
- }
182
- fs.chmodSync(target, 0o755)
183
- }
184
-
185
- function verifyBinary() {
186
- const result = childProcess.spawnSync(targetBinary, ["--version"], {
187
- encoding: "utf8",
188
- stdio: "ignore",
189
- windowsHide: true,
190
- })
191
- return result.status === 0
192
- }
193
-
194
- function main() {
195
- for (const name of packageNames()) {
196
- try {
197
- copyBinary(resolveBinary(name), targetBinary)
198
- copyVendor(resolvePackageDir(name))
199
- if (verifyBinary()) return
200
- } catch {
201
- if (installPackage(name) && verifyBinary()) return
202
- }
203
- }
204
-
205
- throw new Error(
206
- `It seems your package manager failed to install the right deveco-code package. Try manually installing ${packageNames()
207
- .map((name) => JSON.stringify(name))
208
- .join(" or ")}.`,
209
- )
210
- }
211
-
212
- try {
213
- main()
214
- } catch (error) {
215
- console.error(error.message)
216
- process.exit(1)
217
- }
1
+ #!/usr/bin/env node
2
+
3
+ import childProcess from "child_process"
4
+ import fs from "fs"
5
+ import os from "os"
6
+ import path from "path"
7
+ import { createRequire } from "module"
8
+ import { fileURLToPath } from "url"
9
+
10
+ const __dirname = path.dirname(fileURLToPath(import.meta.url))
11
+ const require = createRequire(import.meta.url)
12
+ const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, "package.json"), "utf8"))
13
+
14
+ const platformMap = {
15
+ darwin: "darwin",
16
+ linux: "linux",
17
+ win32: "windows",
18
+ }
19
+ const archMap = {
20
+ x64: "x64",
21
+ arm64: "arm64",
22
+ arm: "arm",
23
+ }
24
+
25
+ const platform = platformMap[os.platform()] ?? os.platform()
26
+ const arch = archMap[os.arch()] ?? os.arch()
27
+ const scope = packageJson.name && packageJson.name.includes("/") ? packageJson.name.split("/")[0] : "@deveco-test"
28
+ const base = `${scope}/deveco-code-${platform}-${arch}`
29
+ const sourceBinary = platform === "windows" ? "deveco.exe" : "deveco"
30
+ const targetBinary = path.join(__dirname, "bin", "deveco.exe")
31
+ const devecoHarnessPackageName = "@deveco-test/deveco-harness"
32
+ const homegraphPackageName = "homegraph"
33
+ const HOMEGRAPH_ENTRY_REL = path.join("dist", "bin", "homegraph.js")
34
+
35
+ function resolveVendoredCliEntryInsideHarness(harnessRoot) {
36
+ const cliRoot = path.join(harnessRoot, "vendor", "deveco-cli", "node_modules", "@deveco", "deveco-cli")
37
+ const pkgPath = path.join(cliRoot, "package.json")
38
+ let binEntry
39
+ if (fs.existsSync(pkgPath)) {
40
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"))
41
+ binEntry = pkg.bin?.devecocli
42
+ }
43
+ const candidates = [binEntry, "dist/cli.js", "cli.js"].filter(Boolean)
44
+ for (const rel of candidates) {
45
+ const entry = path.join(cliRoot, rel)
46
+ if (fs.existsSync(entry)) return entry
47
+ }
48
+ return undefined
49
+ }
50
+
51
+ function resolveLocalDevecoCliEntry() {
52
+ let harnessRoot
53
+ try {
54
+ const harnessPackageJsonPath = require.resolve(`${devecoHarnessPackageName}/package.json`)
55
+ harnessRoot = path.dirname(harnessPackageJsonPath)
56
+ const entry = resolveVendoredCliEntryInsideHarness(harnessRoot)
57
+ if (entry) return entry
58
+ } catch {
59
+ // The harness dependency is not resolvable from here; try the vendor copy.
60
+ }
61
+ // Platform packages copy vendor/deveco-harness next to the binary before
62
+ // the harness dependency is resolvable; fall back to that layout.
63
+ const bundled = resolveVendoredCliEntryInsideHarness(path.join(__dirname, "vendor", "deveco-harness"))
64
+ if (bundled) return bundled
65
+ throw new Error(
66
+ `Dependency "${devecoHarnessPackageName}" is not installed and no vendored deveco-cli entry was found.`,
67
+ )
68
+ }
69
+
70
+ function writeDevecoCliEntryMarker(installRoot) {
71
+ const marker = path.join(installRoot, "vendor", ".deveco-cli-entry")
72
+ fs.mkdirSync(path.dirname(marker), { recursive: true })
73
+ fs.writeFileSync(marker, `${resolveLocalDevecoCliEntry()}\n`, "utf8")
74
+ }
75
+
76
+ function resolveLocalHomegraphEntry() {
77
+ const packageJsonPath = require.resolve(`${homegraphPackageName}/package.json`)
78
+ const entry = path.join(path.dirname(packageJsonPath), HOMEGRAPH_ENTRY_REL)
79
+ if (fs.existsSync(entry)) return entry
80
+ throw new Error(`Local dependency "${homegraphPackageName}" has no entry at ${entry}.`)
81
+ }
82
+
83
+ function writeHomegraphEntryMarker(installRoot) {
84
+ try {
85
+ const marker = path.join(installRoot, "vendor", ".homegraph-entry")
86
+ fs.mkdirSync(path.dirname(marker), { recursive: true })
87
+ fs.writeFileSync(marker, `${resolveLocalHomegraphEntry()}\n`, "utf8")
88
+ } catch (error) {
89
+ console.warn(`[homegraph] postinstall: ${error instanceof Error ? error.message : String(error)}`)
90
+ }
91
+ }
92
+
93
+ function supportsAvx2() {
94
+ if (arch !== "x64") return false
95
+
96
+ if (platform === "linux") {
97
+ try {
98
+ return /(^|\s)avx2(\s|$)/i.test(fs.readFileSync("/proc/cpuinfo", "utf8"))
99
+ } catch {
100
+ return false
101
+ }
102
+ }
103
+
104
+ if (platform === "darwin") {
105
+ try {
106
+ const result = childProcess.spawnSync("sysctl", ["-n", "hw.optional.avx2_0"], {
107
+ encoding: "utf8",
108
+ timeout: 1500,
109
+ })
110
+ if (result.status !== 0) return false
111
+ return (result.stdout || "").trim() === "1"
112
+ } catch {
113
+ return false
114
+ }
115
+ }
116
+
117
+ if (platform === "windows") {
118
+ const command =
119
+ '(Add-Type -MemberDefinition "[DllImport(""kernel32.dll"")] public static extern bool IsProcessorFeaturePresent(int ProcessorFeature);" -Name Kernel32 -Namespace Win32 -PassThru)::IsProcessorFeaturePresent(40)'
120
+
121
+ for (const executable of ["powershell.exe", "pwsh.exe", "pwsh", "powershell"]) {
122
+ try {
123
+ const result = childProcess.spawnSync(executable, ["-NoProfile", "-NonInteractive", "-Command", command], {
124
+ encoding: "utf8",
125
+ timeout: 3000,
126
+ windowsHide: true,
127
+ })
128
+ if (result.status !== 0) continue
129
+ const output = (result.stdout || "").trim().toLowerCase()
130
+ if (output === "true" || output === "1") return true
131
+ if (output === "false" || output === "0") return false
132
+ } catch {
133
+ continue
134
+ }
135
+ }
136
+ }
137
+
138
+ return false
139
+ }
140
+
141
+ function isMusl() {
142
+ if (platform !== "linux") return false
143
+
144
+ try {
145
+ if (fs.existsSync("/etc/alpine-release")) return true
146
+ } catch {
147
+ // Ignore filesystem probes that are blocked by the host.
148
+ }
149
+
150
+ try {
151
+ const result = childProcess.spawnSync("ldd", ["--version"], { encoding: "utf8" })
152
+ return `${result.stdout || ""}${result.stderr || ""}`.toLowerCase().includes("musl")
153
+ } catch {
154
+ return false
155
+ }
156
+ }
157
+
158
+ function packageNames() {
159
+ const baseline = arch === "x64" && !supportsAvx2()
160
+
161
+ if (platform === "linux") {
162
+ if (isMusl()) {
163
+ if (arch === "x64")
164
+ return baseline
165
+ ? [`${base}-baseline-musl`, `${base}-musl`, `${base}-baseline`, base]
166
+ : [`${base}-musl`, `${base}-baseline-musl`, base, `${base}-baseline`]
167
+ return [`${base}-musl`, base]
168
+ }
169
+
170
+ if (arch === "x64")
171
+ return baseline
172
+ ? [`${base}-baseline`, base, `${base}-baseline-musl`, `${base}-musl`]
173
+ : [base, `${base}-baseline`, `${base}-musl`, `${base}-baseline-musl`]
174
+ return [base, `${base}-musl`]
175
+ }
176
+
177
+ if (arch === "x64") return baseline ? [`${base}-baseline`, base] : [base, `${base}-baseline`]
178
+ return [base]
179
+ }
180
+
181
+ function resolvePackageDir(name) {
182
+ const packageJsonPath = require.resolve(`${name}/package.json`)
183
+ return path.dirname(packageJsonPath)
184
+ }
185
+
186
+ function resolveBinary(name) {
187
+ const binaryPath = path.join(resolvePackageDir(name), "bin", sourceBinary)
188
+ if (!fs.existsSync(binaryPath)) throw new Error(`Binary not found at ${binaryPath}`)
189
+ return binaryPath
190
+ }
191
+
192
+ function copyDir(src, dst) {
193
+ if (!fs.existsSync(dst)) fs.mkdirSync(dst, { recursive: true })
194
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
195
+ const srcPath = path.join(src, entry.name)
196
+ const dstPath = path.join(dst, entry.name)
197
+ if (entry.isDirectory()) {
198
+ copyDir(srcPath, dstPath)
199
+ } else {
200
+ fs.copyFileSync(srcPath, dstPath)
201
+ if (process.platform !== "win32") {
202
+ fs.chmodSync(dstPath, fs.statSync(srcPath).mode)
203
+ }
204
+ }
205
+ }
206
+ }
207
+
208
+ function copyVendor(packageDir) {
209
+ const vendorSrc = path.join(packageDir, "vendor")
210
+ const vendorDst = path.join(__dirname, "vendor")
211
+ if (fs.existsSync(vendorSrc)) {
212
+ copyDir(vendorSrc, vendorDst)
213
+ // Windows packs often drop Unix +x; force it back on macOS/Linux install.
214
+ ensureVendorExecutables(vendorDst)
215
+ ensureVendorExecutables(path.join(packageDir, "vendor"))
216
+ }
217
+ }
218
+
219
+ /** Restore execute bits lost when packages are built/published from Windows. */
220
+ function ensureVendorExecutables(vendorRoot) {
221
+ if (process.platform === "win32" || !fs.existsSync(vendorRoot)) return
222
+
223
+ const stack = [vendorRoot]
224
+ while (stack.length > 0) {
225
+ const dir = stack.pop()
226
+ let entries
227
+ try {
228
+ entries = fs.readdirSync(dir, { withFileTypes: true })
229
+ } catch {
230
+ continue
231
+ }
232
+ for (const entry of entries) {
233
+ const full = path.join(dir, entry.name)
234
+ if (entry.isDirectory()) {
235
+ stack.push(full)
236
+ continue
237
+ }
238
+ if (!entry.isFile()) continue
239
+ // Top-level vendor/ripgrep/rg and nested @vscode/ripgrep*/**/rg
240
+ if (entry.name === "rg") {
241
+ try {
242
+ fs.chmodSync(full, 0o755)
243
+ } catch {
244
+ // Best-effort; ignore files we cannot chmod.
245
+ }
246
+ }
247
+ }
248
+ }
249
+ }
250
+
251
+ function installPackage(name) {
252
+ const version = packageJson.optionalDependencies?.[name]
253
+ if (!version) return
254
+
255
+ const temp = fs.mkdtempSync(path.join(os.tmpdir(), "opencode-install-"))
256
+ try {
257
+ const result = childProcess.spawnSync(
258
+ "npm",
259
+ ["install", "--ignore-scripts", "--no-save", "--loglevel=error", "--prefix", temp, `${name}@${version}`],
260
+ { stdio: "inherit", windowsHide: true },
261
+ )
262
+ if (result.status !== 0) return
263
+ const packageDir = path.join(temp, "node_modules", name)
264
+ copyBinary(path.join(packageDir, "bin", sourceBinary), targetBinary)
265
+ copyVendor(packageDir)
266
+ writeDevecoCliEntryMarker(packageDir)
267
+ writeHomegraphEntryMarker(packageDir)
268
+ writeHomegraphEntryMarker(__dirname)
269
+ return true
270
+ } finally {
271
+ fs.rmSync(temp, { recursive: true, force: true })
272
+ }
273
+ }
274
+
275
+ function copyBinary(source, target) {
276
+ if (!fs.existsSync(source)) throw new Error(`Binary not found at ${source}`)
277
+ fs.mkdirSync(path.dirname(target), { recursive: true })
278
+ if (fs.existsSync(target)) fs.unlinkSync(target)
279
+ try {
280
+ fs.linkSync(source, target)
281
+ } catch {
282
+ fs.copyFileSync(source, target)
283
+ }
284
+ fs.chmodSync(target, 0o755)
285
+ }
286
+
287
+ function verifyBinary() {
288
+ const result = childProcess.spawnSync(targetBinary, ["--version"], {
289
+ encoding: "utf8",
290
+ stdio: "ignore",
291
+ windowsHide: true,
292
+ })
293
+ return result.status === 0
294
+ }
295
+
296
+ function main() {
297
+ writeDevecoCliEntryMarker(__dirname)
298
+ writeHomegraphEntryMarker(__dirname)
299
+
300
+ for (const name of packageNames()) {
301
+ try {
302
+ const packageDir = resolvePackageDir(name)
303
+ copyBinary(resolveBinary(name), targetBinary)
304
+ copyVendor(packageDir)
305
+ writeDevecoCliEntryMarker(packageDir)
306
+ writeHomegraphEntryMarker(packageDir)
307
+ if (verifyBinary()) return
308
+ } catch {
309
+ if (installPackage(name) && verifyBinary()) return
310
+ }
311
+ }
312
+
313
+ throw new Error(
314
+ `It seems your package manager failed to install the right deveco-code package. Try manually installing ${packageNames()
315
+ .map((name) => JSON.stringify(name))
316
+ .join(" or ")}.`,
317
+ )
318
+ }
319
+
320
+ try {
321
+ main()
322
+ } catch (error) {
323
+ console.error(error.message)
324
+ process.exit(1)
325
+ }