@meridianjs/framework 0.1.1 → 0.1.3
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/dist/index.js +110 -98
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -138,9 +138,9 @@ async function resolveModuleDefinition(config, rootDir) {
|
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
// src/plugin-loader.ts
|
|
141
|
-
import
|
|
142
|
-
import
|
|
143
|
-
import { pathToFileURL as
|
|
141
|
+
import path7 from "path";
|
|
142
|
+
import fs5 from "fs/promises";
|
|
143
|
+
import { pathToFileURL as pathToFileURL7 } from "url";
|
|
144
144
|
import { createRequire } from "module";
|
|
145
145
|
|
|
146
146
|
// src/route-loader.ts
|
|
@@ -316,13 +316,94 @@ async function loadJobs(container, jobsDir) {
|
|
|
316
316
|
}
|
|
317
317
|
}
|
|
318
318
|
|
|
319
|
+
// src/link-loader.ts
|
|
320
|
+
import fs4 from "fs/promises";
|
|
321
|
+
import path6 from "path";
|
|
322
|
+
import { pathToFileURL as pathToFileURL6 } from "url";
|
|
323
|
+
async function loadLinks(container, linksDir) {
|
|
324
|
+
const logger = container.resolve("logger");
|
|
325
|
+
const definitions = [];
|
|
326
|
+
try {
|
|
327
|
+
await fs4.access(linksDir);
|
|
328
|
+
} catch {
|
|
329
|
+
logger.debug(`No links directory at ${linksDir}, skipping.`);
|
|
330
|
+
registerEmptyServices(container);
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
const files = await fs4.readdir(linksDir);
|
|
334
|
+
for (const file of files) {
|
|
335
|
+
if (!/\.(ts|mts|js|mjs|cjs)$/.test(file)) continue;
|
|
336
|
+
const fullPath = path6.join(linksDir, file);
|
|
337
|
+
let mod;
|
|
338
|
+
try {
|
|
339
|
+
mod = await import(pathToFileURL6(fullPath).href);
|
|
340
|
+
} catch (err) {
|
|
341
|
+
logger.error(`Failed to load link file ${file}: ${err.message}`);
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
const def = mod.default;
|
|
345
|
+
if (def?.linkTableName) {
|
|
346
|
+
definitions.push(def);
|
|
347
|
+
logger.debug(`Link loaded: ${def.linkTableName}`);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
let existingDefs = [];
|
|
351
|
+
try {
|
|
352
|
+
const existingLink = container.resolve("link");
|
|
353
|
+
existingDefs = existingLink.getDefinitions?.() ?? [];
|
|
354
|
+
} catch {
|
|
355
|
+
}
|
|
356
|
+
const allDefs = [...existingDefs, ...definitions];
|
|
357
|
+
const linkService = new LinkService(allDefs, container, logger);
|
|
358
|
+
const queryService = new QueryService(allDefs, container, logger);
|
|
359
|
+
container.register({
|
|
360
|
+
link: linkService,
|
|
361
|
+
query: queryService
|
|
362
|
+
});
|
|
363
|
+
logger.info(`Loaded ${allDefs.length} module link(s)`);
|
|
364
|
+
}
|
|
365
|
+
function registerEmptyServices(container) {
|
|
366
|
+
const link = new LinkService([], container, null);
|
|
367
|
+
const query = new QueryService([], container, null);
|
|
368
|
+
container.register({ link, query });
|
|
369
|
+
}
|
|
370
|
+
var LinkService = class {
|
|
371
|
+
constructor(defs, container, logger) {
|
|
372
|
+
this.defs = defs;
|
|
373
|
+
this.container = container;
|
|
374
|
+
this.logger = logger;
|
|
375
|
+
this.defsByTable = new Map(defs.map((d) => [d.linkTableName, d]));
|
|
376
|
+
}
|
|
377
|
+
defsByTable;
|
|
378
|
+
async create(linkTableName, leftId, rightId, data) {
|
|
379
|
+
this.logger?.debug(`Link.create: ${linkTableName} ${leftId} \u2192 ${rightId}`);
|
|
380
|
+
}
|
|
381
|
+
async dismiss(linkTableName, leftId, rightId) {
|
|
382
|
+
this.logger?.debug(`Link.dismiss: ${linkTableName} ${leftId} \u2192 ${rightId}`);
|
|
383
|
+
}
|
|
384
|
+
getDefinitions() {
|
|
385
|
+
return this.defs;
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
var QueryService = class {
|
|
389
|
+
constructor(defs, container, logger) {
|
|
390
|
+
this.defs = defs;
|
|
391
|
+
this.container = container;
|
|
392
|
+
this.logger = logger;
|
|
393
|
+
}
|
|
394
|
+
async graph(options) {
|
|
395
|
+
this.logger?.debug(`Query.graph: ${options.entity}`, { fields: options.fields });
|
|
396
|
+
return { data: [] };
|
|
397
|
+
}
|
|
398
|
+
};
|
|
399
|
+
|
|
319
400
|
// src/plugin-loader.ts
|
|
320
401
|
async function loadPlugins(container, plugins, rootDir) {
|
|
321
402
|
const logger = container.resolve("logger");
|
|
322
403
|
for (const plugin of plugins) {
|
|
323
404
|
logger.info(`Loading plugin: ${plugin.resolve}`);
|
|
324
|
-
const isLocalPath = plugin.resolve.startsWith(".") ||
|
|
325
|
-
const importPath = isLocalPath ?
|
|
405
|
+
const isLocalPath = plugin.resolve.startsWith(".") || path7.isAbsolute(plugin.resolve);
|
|
406
|
+
const importPath = isLocalPath ? pathToFileURL7(path7.resolve(rootDir, plugin.resolve)).href : plugin.resolve;
|
|
326
407
|
let pluginMod;
|
|
327
408
|
try {
|
|
328
409
|
pluginMod = await import(importPath);
|
|
@@ -334,12 +415,12 @@ async function loadPlugins(container, plugins, rootDir) {
|
|
|
334
415
|
if (pluginMod.pluginRoot && typeof pluginMod.pluginRoot === "string") {
|
|
335
416
|
scanRoot = pluginMod.pluginRoot;
|
|
336
417
|
} else if (isLocalPath) {
|
|
337
|
-
const resolvedPath =
|
|
418
|
+
const resolvedPath = path7.resolve(rootDir, plugin.resolve);
|
|
338
419
|
try {
|
|
339
|
-
const stat = await
|
|
340
|
-
scanRoot = stat.isDirectory() ? resolvedPath :
|
|
420
|
+
const stat = await fs5.stat(resolvedPath);
|
|
421
|
+
scanRoot = stat.isDirectory() ? resolvedPath : path7.dirname(resolvedPath);
|
|
341
422
|
} catch {
|
|
342
|
-
scanRoot =
|
|
423
|
+
scanRoot = path7.dirname(resolvedPath);
|
|
343
424
|
}
|
|
344
425
|
} else {
|
|
345
426
|
scanRoot = resolveNpmPackageRoot(plugin.resolve, rootDir);
|
|
@@ -366,23 +447,28 @@ async function loadPlugins(container, plugins, rootDir) {
|
|
|
366
447
|
}
|
|
367
448
|
}
|
|
368
449
|
async function autoScanPlugin(scanRoot, container, logger) {
|
|
369
|
-
|
|
450
|
+
let server = null;
|
|
451
|
+
try {
|
|
452
|
+
server = container.resolve("server");
|
|
453
|
+
} catch {
|
|
454
|
+
}
|
|
370
455
|
const candidates = [
|
|
371
456
|
scanRoot,
|
|
372
457
|
// pluginRoot already points to compiled dir
|
|
373
|
-
|
|
458
|
+
path7.join(scanRoot, "dist"),
|
|
374
459
|
// package root → try dist/ first
|
|
375
|
-
|
|
460
|
+
path7.join(scanRoot, "src")
|
|
376
461
|
// package root → try src/ (tsx dev mode)
|
|
377
462
|
];
|
|
378
463
|
for (const candidate of candidates) {
|
|
379
|
-
const apiDir =
|
|
464
|
+
const apiDir = path7.join(candidate, "api");
|
|
380
465
|
try {
|
|
381
|
-
await
|
|
466
|
+
await fs5.access(apiDir);
|
|
382
467
|
await Promise.all([
|
|
383
|
-
loadRoutes(server, container, apiDir),
|
|
384
|
-
loadSubscribers(container,
|
|
385
|
-
loadJobs(container,
|
|
468
|
+
server ? loadRoutes(server, container, apiDir) : Promise.resolve(),
|
|
469
|
+
loadSubscribers(container, path7.join(candidate, "subscribers")),
|
|
470
|
+
loadJobs(container, path7.join(candidate, "jobs")),
|
|
471
|
+
loadLinks(container, path7.join(candidate, "links"))
|
|
386
472
|
]);
|
|
387
473
|
logger.debug(`Plugin auto-scanned from: ${candidate}`);
|
|
388
474
|
return;
|
|
@@ -393,20 +479,20 @@ async function autoScanPlugin(scanRoot, container, logger) {
|
|
|
393
479
|
}
|
|
394
480
|
function resolveNpmPackageRoot(packageName, fromDir) {
|
|
395
481
|
try {
|
|
396
|
-
const require2 = createRequire(
|
|
482
|
+
const require2 = createRequire(path7.join(fromDir, "synthetic.cjs"));
|
|
397
483
|
const pkgJsonPath = require2.resolve(`${packageName}/package.json`);
|
|
398
|
-
return
|
|
484
|
+
return path7.dirname(pkgJsonPath);
|
|
399
485
|
} catch {
|
|
400
486
|
try {
|
|
401
|
-
const require2 = createRequire(
|
|
487
|
+
const require2 = createRequire(path7.join(fromDir, "synthetic.cjs"));
|
|
402
488
|
const mainPath = require2.resolve(packageName);
|
|
403
|
-
let dir =
|
|
404
|
-
while (dir !==
|
|
489
|
+
let dir = path7.dirname(mainPath);
|
|
490
|
+
while (dir !== path7.dirname(dir)) {
|
|
405
491
|
try {
|
|
406
|
-
require2.resolve(
|
|
492
|
+
require2.resolve(path7.join(dir, "package.json"));
|
|
407
493
|
return dir;
|
|
408
494
|
} catch {
|
|
409
|
-
dir =
|
|
495
|
+
dir = path7.dirname(dir);
|
|
410
496
|
}
|
|
411
497
|
}
|
|
412
498
|
} catch {
|
|
@@ -415,80 +501,6 @@ function resolveNpmPackageRoot(packageName, fromDir) {
|
|
|
415
501
|
}
|
|
416
502
|
}
|
|
417
503
|
|
|
418
|
-
// src/link-loader.ts
|
|
419
|
-
import fs5 from "fs/promises";
|
|
420
|
-
import path7 from "path";
|
|
421
|
-
import { pathToFileURL as pathToFileURL7 } from "url";
|
|
422
|
-
async function loadLinks(container, linksDir) {
|
|
423
|
-
const logger = container.resolve("logger");
|
|
424
|
-
const definitions = [];
|
|
425
|
-
try {
|
|
426
|
-
await fs5.access(linksDir);
|
|
427
|
-
} catch {
|
|
428
|
-
logger.debug(`No links directory at ${linksDir}, skipping.`);
|
|
429
|
-
registerEmptyServices(container);
|
|
430
|
-
return;
|
|
431
|
-
}
|
|
432
|
-
const files = await fs5.readdir(linksDir);
|
|
433
|
-
for (const file of files) {
|
|
434
|
-
if (!/\.(ts|mts|js|mjs|cjs)$/.test(file)) continue;
|
|
435
|
-
const fullPath = path7.join(linksDir, file);
|
|
436
|
-
let mod;
|
|
437
|
-
try {
|
|
438
|
-
mod = await import(pathToFileURL7(fullPath).href);
|
|
439
|
-
} catch (err) {
|
|
440
|
-
logger.error(`Failed to load link file ${file}: ${err.message}`);
|
|
441
|
-
continue;
|
|
442
|
-
}
|
|
443
|
-
const def = mod.default;
|
|
444
|
-
if (def?.linkTableName) {
|
|
445
|
-
definitions.push(def);
|
|
446
|
-
logger.debug(`Link loaded: ${def.linkTableName}`);
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
const linkService = new LinkService(definitions, container, logger);
|
|
450
|
-
const queryService = new QueryService(definitions, container, logger);
|
|
451
|
-
container.register({
|
|
452
|
-
link: linkService,
|
|
453
|
-
query: queryService
|
|
454
|
-
});
|
|
455
|
-
logger.info(`Loaded ${definitions.length} module link(s)`);
|
|
456
|
-
}
|
|
457
|
-
function registerEmptyServices(container) {
|
|
458
|
-
const link = new LinkService([], container, null);
|
|
459
|
-
const query = new QueryService([], container, null);
|
|
460
|
-
container.register({ link, query });
|
|
461
|
-
}
|
|
462
|
-
var LinkService = class {
|
|
463
|
-
constructor(defs, container, logger) {
|
|
464
|
-
this.defs = defs;
|
|
465
|
-
this.container = container;
|
|
466
|
-
this.logger = logger;
|
|
467
|
-
this.defsByTable = new Map(defs.map((d) => [d.linkTableName, d]));
|
|
468
|
-
}
|
|
469
|
-
defsByTable;
|
|
470
|
-
async create(linkTableName, leftId, rightId, data) {
|
|
471
|
-
this.logger?.debug(`Link.create: ${linkTableName} ${leftId} \u2192 ${rightId}`);
|
|
472
|
-
}
|
|
473
|
-
async dismiss(linkTableName, leftId, rightId) {
|
|
474
|
-
this.logger?.debug(`Link.dismiss: ${linkTableName} ${leftId} \u2192 ${rightId}`);
|
|
475
|
-
}
|
|
476
|
-
getDefinitions() {
|
|
477
|
-
return this.defs;
|
|
478
|
-
}
|
|
479
|
-
};
|
|
480
|
-
var QueryService = class {
|
|
481
|
-
constructor(defs, container, logger) {
|
|
482
|
-
this.defs = defs;
|
|
483
|
-
this.container = container;
|
|
484
|
-
this.logger = logger;
|
|
485
|
-
}
|
|
486
|
-
async graph(options) {
|
|
487
|
-
this.logger?.debug(`Query.graph: ${options.entity}`, { fields: options.fields });
|
|
488
|
-
return { data: [] };
|
|
489
|
-
}
|
|
490
|
-
};
|
|
491
|
-
|
|
492
504
|
// src/server.ts
|
|
493
505
|
import express from "express";
|
|
494
506
|
import cors from "cors";
|
package/package.json
CHANGED