@whxway/loom 1.0.0 → 1.0.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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@whxway/loom",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Self-hosted AI testing platform — try models and MCP servers, log every request, and front your apps through an OpenAI-compatible gateway.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
".next",
|
|
36
36
|
"drizzle",
|
|
37
37
|
"public",
|
|
38
|
+
"scripts/postinstall.mjs",
|
|
38
39
|
"README.md",
|
|
39
40
|
"LICENSE"
|
|
40
41
|
],
|
|
@@ -43,12 +44,14 @@
|
|
|
43
44
|
},
|
|
44
45
|
"scripts": {
|
|
45
46
|
"dev": "next dev",
|
|
46
|
-
"build": "bun run build:cli && next build",
|
|
47
|
+
"build": "bun run build:cli && next build && bun run build:aliases",
|
|
47
48
|
"build:cli": "node scripts/build-cli.mjs",
|
|
49
|
+
"build:aliases": "node scripts/generate-external-aliases.mjs",
|
|
48
50
|
"start": "next start",
|
|
49
51
|
"lint": "eslint",
|
|
50
52
|
"test": "node scripts/run-e2e.mjs",
|
|
51
53
|
"prepare": "node scripts/build-cli.mjs",
|
|
54
|
+
"postinstall": "node scripts/postinstall.mjs",
|
|
52
55
|
"prepublishOnly": "bun run build"
|
|
53
56
|
},
|
|
54
57
|
"dependencies": {
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Install-time: recreate the .next/node_modules/<pkg>-<hash> symlinks that
|
|
3
|
+
// Turbopack hard-codes into the built chunks. npm pack drops `node_modules`
|
|
4
|
+
// directories from the tarball, so these symlinks are missing on the user's
|
|
5
|
+
// machine. We read the manifest written at build time, locate each real
|
|
6
|
+
// package via createRequire, and rebuild the symlink.
|
|
7
|
+
//
|
|
8
|
+
// Safe to run multiple times: existing valid symlinks are left untouched,
|
|
9
|
+
// missing manifests skipped silently (e.g. when this script runs inside the
|
|
10
|
+
// source repo before the first build).
|
|
11
|
+
|
|
12
|
+
import { existsSync, lstatSync, mkdirSync, readFileSync, readlinkSync, rmSync, symlinkSync } from "node:fs";
|
|
13
|
+
import { createRequire } from "node:module";
|
|
14
|
+
import { dirname, relative, resolve } from "node:path";
|
|
15
|
+
import { fileURLToPath } from "node:url";
|
|
16
|
+
|
|
17
|
+
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
18
|
+
const PKG_ROOT = resolve(HERE, "..");
|
|
19
|
+
const MANIFEST = resolve(PKG_ROOT, ".next/external-aliases.json");
|
|
20
|
+
const MODULES_DIR = resolve(PKG_ROOT, ".next/node_modules");
|
|
21
|
+
|
|
22
|
+
if (!existsSync(MANIFEST)) {
|
|
23
|
+
process.exit(0);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let aliases;
|
|
27
|
+
try {
|
|
28
|
+
aliases = JSON.parse(readFileSync(MANIFEST, "utf8"));
|
|
29
|
+
} catch (err) {
|
|
30
|
+
console.error(`[loom] failed to parse ${MANIFEST}:`, err.message);
|
|
31
|
+
process.exit(0);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (!aliases || typeof aliases !== "object" || Object.keys(aliases).length === 0) {
|
|
35
|
+
process.exit(0);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
mkdirSync(MODULES_DIR, { recursive: true });
|
|
39
|
+
|
|
40
|
+
const requireFromPkg = createRequire(resolve(PKG_ROOT, "package.json"));
|
|
41
|
+
|
|
42
|
+
let created = 0;
|
|
43
|
+
let skipped = 0;
|
|
44
|
+
for (const [hashed, real] of Object.entries(aliases)) {
|
|
45
|
+
const linkPath = resolve(MODULES_DIR, hashed);
|
|
46
|
+
let realPkgDir;
|
|
47
|
+
try {
|
|
48
|
+
// Resolve the real package's package.json to find its directory.
|
|
49
|
+
const pkgJsonPath = requireFromPkg.resolve(`${real}/package.json`);
|
|
50
|
+
realPkgDir = dirname(pkgJsonPath);
|
|
51
|
+
} catch (err) {
|
|
52
|
+
console.warn(`[loom] couldn't resolve "${real}" for alias "${hashed}": ${err.message}`);
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// If the link already exists and points somewhere valid, leave it.
|
|
57
|
+
try {
|
|
58
|
+
const stat = lstatSync(linkPath);
|
|
59
|
+
if (stat.isSymbolicLink()) {
|
|
60
|
+
const target = resolve(MODULES_DIR, readlinkSync(linkPath));
|
|
61
|
+
if (existsSync(target)) {
|
|
62
|
+
skipped++;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
rmSync(linkPath, { recursive: true, force: true });
|
|
67
|
+
} catch {
|
|
68
|
+
// Doesn't exist — fine.
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Symlink with junction type so Windows works without admin rights.
|
|
72
|
+
const target = relative(MODULES_DIR, realPkgDir);
|
|
73
|
+
try {
|
|
74
|
+
symlinkSync(target, linkPath, "junction");
|
|
75
|
+
created++;
|
|
76
|
+
} catch (err) {
|
|
77
|
+
console.warn(`[loom] failed to symlink "${hashed}" -> "${target}": ${err.message}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (created > 0 || skipped > 0) {
|
|
82
|
+
console.log(`[loom] external aliases: ${created} created, ${skipped} already in place`);
|
|
83
|
+
}
|