arcway 0.3.0 → 0.3.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 +1 -1
- package/server/constants.js +9 -0
- package/server/db/seeds.js +1 -1
- package/server/events/handler.js +4 -3
- package/server/jobs/worker-pool.js +8 -3
- package/server/mcp/index.js +1 -2
- package/server/mcp/tools/introspection.js +0 -1
- package/server/pages/build-cache.js +2 -4
- package/server/pages/build-plugins.js +39 -12
- package/server/pages/handler.js +1 -1
- package/server/pages/lazy-context.js +3 -17
- package/server/plugins/bundle.js +2 -0
- package/server/static/index.js +0 -1
package/package.json
CHANGED
package/server/constants.js
CHANGED
|
@@ -34,10 +34,19 @@ const SERVER_ONLY_PACKAGES = new Set([
|
|
|
34
34
|
'commander',
|
|
35
35
|
'glob',
|
|
36
36
|
'esbuild',
|
|
37
|
+
'vite',
|
|
38
|
+
'@vitejs/plugin-react',
|
|
39
|
+
'@babel/core',
|
|
40
|
+
'@babel/preset-typescript',
|
|
41
|
+
'@tailwindcss/node',
|
|
42
|
+
'@tailwindcss/vite',
|
|
37
43
|
'postcss',
|
|
38
44
|
'@tailwindcss/postcss',
|
|
39
45
|
'tailwindcss',
|
|
40
46
|
'@tailwindcss/oxide',
|
|
47
|
+
'playwright',
|
|
48
|
+
'playwright-core',
|
|
49
|
+
'chromium-bidi',
|
|
41
50
|
'tsx',
|
|
42
51
|
'cache-manager',
|
|
43
52
|
'rate-limiter-flexible',
|
package/server/db/seeds.js
CHANGED
|
@@ -3,7 +3,7 @@ import { discoverModules } from '../discovery.js';
|
|
|
3
3
|
async function runSeeds(db, seedsDir) {
|
|
4
4
|
const entries = await discoverModules(seedsDir, { label: 'seed file' });
|
|
5
5
|
const results = [];
|
|
6
|
-
for (const { name,
|
|
6
|
+
for (const { name, module } of entries) {
|
|
7
7
|
const seedFn = module.default;
|
|
8
8
|
if (typeof seedFn !== 'function') {
|
|
9
9
|
throw new Error(`Seed file "${name}" must export a default function`);
|
package/server/events/handler.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import { discoverModules } from '../discovery.js';
|
|
3
2
|
import { buildContext } from '../context.js';
|
|
4
3
|
|
|
@@ -64,7 +63,7 @@ class EventHandler {
|
|
|
64
63
|
const groupName =
|
|
65
64
|
consumerGroup === false
|
|
66
65
|
? undefined
|
|
67
|
-
: consumerGroup ?? `listener:${relativePath}:${items.length > 1 ? i : 0}
|
|
66
|
+
: (consumerGroup ?? `listener:${relativePath}:${items.length > 1 ? i : 0}`);
|
|
68
67
|
this._events.subscribe(
|
|
69
68
|
event,
|
|
70
69
|
(payload, _eventName) => {
|
|
@@ -75,7 +74,9 @@ class EventHandler {
|
|
|
75
74
|
);
|
|
76
75
|
this._listeners.push({ event, fileName: relativePath });
|
|
77
76
|
}
|
|
78
|
-
this._log?.info(
|
|
77
|
+
this._log?.info(
|
|
78
|
+
` ${relativePath} → ${event}${items.length > 1 ? ` (${items.length} listeners)` : ''}`,
|
|
79
|
+
);
|
|
79
80
|
}
|
|
80
81
|
}
|
|
81
82
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Worker } from 'node:worker_threads';
|
|
2
2
|
import { fileURLToPath } from 'node:url';
|
|
3
|
-
import path from 'node:path';
|
|
4
3
|
|
|
5
4
|
const WORKER_ENTRY_URL = new URL('./worker-entry.js', import.meta.url);
|
|
6
5
|
|
|
@@ -210,7 +209,10 @@ class WorkerPool {
|
|
|
210
209
|
resolve();
|
|
211
210
|
};
|
|
212
211
|
const timer = setTimeout(() => {
|
|
213
|
-
worker
|
|
212
|
+
worker
|
|
213
|
+
.terminate()
|
|
214
|
+
.catch(() => {})
|
|
215
|
+
.finally(done);
|
|
214
216
|
}, gracefulExitMs);
|
|
215
217
|
if (typeof timer.unref === 'function') timer.unref();
|
|
216
218
|
worker.once('exit', done);
|
|
@@ -219,7 +221,10 @@ class WorkerPool {
|
|
|
219
221
|
worker.postMessage({ id: 0, task: { __shutdown: true } });
|
|
220
222
|
} catch {
|
|
221
223
|
// Worker already down or channel closed — terminate to be safe.
|
|
222
|
-
worker
|
|
224
|
+
worker
|
|
225
|
+
.terminate()
|
|
226
|
+
.catch(() => {})
|
|
227
|
+
.finally(done);
|
|
223
228
|
}
|
|
224
229
|
});
|
|
225
230
|
}
|
package/server/mcp/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { createMcpRuntime } from './runtime.js';
|
|
3
|
-
import { createDebugHandler
|
|
4
|
-
import { startMcpServer } from './server.js';
|
|
3
|
+
import { createDebugHandler } from './debug-api.js';
|
|
5
4
|
|
|
6
5
|
const DEBUG_PREFIX = '/_mcp';
|
|
7
6
|
|
|
@@ -44,7 +44,7 @@ async function hashFileContent(filePath) {
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
function resolveInputPath(p
|
|
47
|
+
function resolveInputPath(p) {
|
|
48
48
|
if (path.isAbsolute(p)) return p;
|
|
49
49
|
// esbuild metafile paths may be relative to cwd; try that first, then rootDir.
|
|
50
50
|
const abs = path.resolve(p);
|
|
@@ -473,9 +473,7 @@ async function pruneStaleCache({ rootDir, kind }) {
|
|
|
473
473
|
const metaPath = path.join(bucket, metaFile);
|
|
474
474
|
const meta = await readJson(metaPath);
|
|
475
475
|
const stale =
|
|
476
|
-
!meta ||
|
|
477
|
-
!Array.isArray(meta.inputs) ||
|
|
478
|
-
(await hashInputs(meta.inputs)) !== meta.inputsHash;
|
|
476
|
+
!meta || !Array.isArray(meta.inputs) || (await hashInputs(meta.inputs)) !== meta.inputsHash;
|
|
479
477
|
|
|
480
478
|
if (!stale) {
|
|
481
479
|
kept += 1;
|
|
@@ -1,18 +1,27 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';
|
|
2
2
|
import { NODE_BUILTINS, SERVER_ONLY_PACKAGES } from '../constants.js';
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
function packageNameForImport(specifier) {
|
|
5
|
+
const parts = specifier.split('/');
|
|
6
|
+
return specifier.startsWith('@') && parts.length >= 2 ? `${parts[0]}/${parts[1]}` : parts[0];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function isBarePackageImport(specifier) {
|
|
10
|
+
if (/^[A-Za-z]:/.test(specifier)) return false;
|
|
11
|
+
if (specifier.startsWith('node:')) return false;
|
|
12
|
+
return /^[^.\/\#]/.test(specifier);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function packageExternalsPlugin({ name, shouldBundlePackage }) {
|
|
4
16
|
const resolvedCache = new Map();
|
|
5
17
|
return {
|
|
6
|
-
name
|
|
18
|
+
name,
|
|
7
19
|
setup(build) {
|
|
8
20
|
build.onResolve({ filter: /^[^.\/\#]/ }, (args) => {
|
|
9
|
-
if (
|
|
10
|
-
|
|
11
|
-
const parts = args.path.split('/');
|
|
12
|
-
const pkgName =
|
|
13
|
-
args.path.startsWith('@') && parts.length >= 2 ? `${parts[0]}/${parts[1]}` : parts[0];
|
|
21
|
+
if (!isBarePackageImport(args.path)) return void 0;
|
|
22
|
+
const pkgName = packageNameForImport(args.path);
|
|
14
23
|
if (!resolvedCache.has(pkgName)) {
|
|
15
|
-
resolvedCache.set(pkgName,
|
|
24
|
+
resolvedCache.set(pkgName, shouldBundlePackage(pkgName, args.resolveDir));
|
|
16
25
|
}
|
|
17
26
|
if (resolvedCache.get(pkgName)) return void 0;
|
|
18
27
|
return { path: args.path, external: true };
|
|
@@ -20,6 +29,21 @@ function serverExternalsPlugin() {
|
|
|
20
29
|
},
|
|
21
30
|
};
|
|
22
31
|
}
|
|
32
|
+
|
|
33
|
+
function serverExternalsPlugin() {
|
|
34
|
+
return packageExternalsPlugin({
|
|
35
|
+
name: 'arcway-server-externals',
|
|
36
|
+
shouldBundlePackage: needsBundling,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function pluginPackageExternalsPlugin() {
|
|
41
|
+
return packageExternalsPlugin({
|
|
42
|
+
name: 'arcway-plugin-package-externals',
|
|
43
|
+
shouldBundlePackage: () => false,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
23
47
|
function needsBundling(pkgName, resolveDir) {
|
|
24
48
|
try {
|
|
25
49
|
const require2 = createRequire(resolveDir + '/');
|
|
@@ -44,9 +68,7 @@ function clientIsolationPlugin() {
|
|
|
44
68
|
return void 0;
|
|
45
69
|
});
|
|
46
70
|
build.onResolve({ filter: /.*/ }, (args) => {
|
|
47
|
-
const
|
|
48
|
-
const pkgName =
|
|
49
|
-
args.path.startsWith('@') && parts.length >= 2 ? `${parts[0]}/${parts[1]}` : parts[0];
|
|
71
|
+
const pkgName = packageNameForImport(args.path);
|
|
50
72
|
if (SERVER_ONLY_PACKAGES.has(pkgName)) {
|
|
51
73
|
return { path: args.path, namespace: STUB_NAMESPACE };
|
|
52
74
|
}
|
|
@@ -73,4 +95,9 @@ function clientIsolationPlugin() {
|
|
|
73
95
|
},
|
|
74
96
|
};
|
|
75
97
|
}
|
|
76
|
-
export {
|
|
98
|
+
export {
|
|
99
|
+
clientIsolationPlugin,
|
|
100
|
+
packageNameForImport,
|
|
101
|
+
pluginPackageExternalsPlugin,
|
|
102
|
+
serverExternalsPlugin,
|
|
103
|
+
};
|
package/server/pages/handler.js
CHANGED
|
@@ -391,7 +391,7 @@ async function runPageMiddleware(
|
|
|
391
391
|
}
|
|
392
392
|
return null;
|
|
393
393
|
}
|
|
394
|
-
function buildClientManifestJson(manifest, { rootDir,
|
|
394
|
+
function buildClientManifestJson(manifest, { rootDir, viteDev } = {}) {
|
|
395
395
|
if (viteDev) {
|
|
396
396
|
return buildViteClientManifestJson(manifest, rootDir);
|
|
397
397
|
}
|
|
@@ -104,12 +104,7 @@ async function createLazyPagesContext(options) {
|
|
|
104
104
|
{ srcPath: path.resolve(m.filePath), built: false, stale: false },
|
|
105
105
|
]),
|
|
106
106
|
),
|
|
107
|
-
loadings: new Map(
|
|
108
|
-
loadings.map((l) => [
|
|
109
|
-
l.dirPath,
|
|
110
|
-
{ srcPath: path.resolve(l.filePath) },
|
|
111
|
-
]),
|
|
112
|
-
),
|
|
107
|
+
loadings: new Map(loadings.map((l) => [l.dirPath, { srcPath: path.resolve(l.filePath) }])),
|
|
113
108
|
stylesPath: stylesPath ? path.resolve(stylesPath) : null,
|
|
114
109
|
version: 0,
|
|
115
110
|
};
|
|
@@ -312,10 +307,7 @@ async function createLazyPagesContext(options) {
|
|
|
312
307
|
}
|
|
313
308
|
const existing = inFlightPages.get(pattern);
|
|
314
309
|
if (existing) return existing;
|
|
315
|
-
const task = Promise.all([
|
|
316
|
-
limit(() => buildPageServer(entry)),
|
|
317
|
-
ensureChainBuilt(entry),
|
|
318
|
-
])
|
|
310
|
+
const task = Promise.all([limit(() => buildPageServer(entry)), ensureChainBuilt(entry)])
|
|
319
311
|
.then(() => {
|
|
320
312
|
entry.layoutServerBundles = entry.layoutDirs
|
|
321
313
|
.map((d) => manifest.layouts.get(d)?.serverBundle)
|
|
@@ -452,7 +444,6 @@ async function createLazyPagesContext(options) {
|
|
|
452
444
|
|
|
453
445
|
const task = (async () => {
|
|
454
446
|
const previousMetafile = currentClientMetafile;
|
|
455
|
-
const previousCssBundle = manifest.cssBundle ?? null;
|
|
456
447
|
const timestamp = Date.now();
|
|
457
448
|
|
|
458
449
|
const [clientResult, cssBundle] = await Promise.all([
|
|
@@ -535,12 +526,7 @@ async function createLazyPagesContext(options) {
|
|
|
535
526
|
if (disposed) throw new Error('Lazy pages context is disposed');
|
|
536
527
|
if (inFlightRediscover) return inFlightRediscover;
|
|
537
528
|
const task = (async () => {
|
|
538
|
-
const [
|
|
539
|
-
nextPages,
|
|
540
|
-
nextLayouts,
|
|
541
|
-
nextLoadings,
|
|
542
|
-
nextMiddlewares,
|
|
543
|
-
] = await Promise.all([
|
|
529
|
+
const [nextPages, nextLayouts, nextLoadings, nextMiddlewares] = await Promise.all([
|
|
544
530
|
discoverPages(pagesDir),
|
|
545
531
|
discoverLayouts(pagesDir),
|
|
546
532
|
discoverLoadings(pagesDir),
|
package/server/plugins/bundle.js
CHANGED
|
@@ -4,6 +4,7 @@ import { pathToFileURL } from 'node:url';
|
|
|
4
4
|
import { build } from 'esbuild';
|
|
5
5
|
import { discoverFiles } from '../discovery.js';
|
|
6
6
|
import { loadModule } from '../module-loader.js';
|
|
7
|
+
import { pluginPackageExternalsPlugin } from '../pages/build-plugins.js';
|
|
7
8
|
|
|
8
9
|
let bundleCounter = 0;
|
|
9
10
|
|
|
@@ -101,6 +102,7 @@ async function loadPluginBundle(packageDir) {
|
|
|
101
102
|
platform: 'node',
|
|
102
103
|
target: 'node20',
|
|
103
104
|
logLevel: 'silent',
|
|
105
|
+
plugins: [pluginPackageExternalsPlugin()],
|
|
104
106
|
});
|
|
105
107
|
|
|
106
108
|
const bundled = await loadModule(outFile);
|
package/server/static/index.js
CHANGED