@_linked/server 3.11.0 → 3.12.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/CHANGELOG.md +12 -0
- package/LICENSE +21 -0
- package/lib/esm/shapes/LinkedServer.d.ts +6 -0
- package/lib/esm/shapes/LinkedServer.js +16 -4
- package/lib/esm/shapes/LinkedServer.js.map +1 -1
- package/lib/esm/utils/effectiveRoutes.d.ts +8 -7
- package/lib/esm/utils/effectiveRoutes.js +2 -2
- package/lib/esm/utils/effectiveRoutes.js.map +1 -1
- package/lib/esm/utils/graphTargets.d.ts +33 -11
- package/lib/esm/utils/graphTargets.js +93 -33
- package/lib/esm/utils/graphTargets.js.map +1 -1
- package/lib/esm/utils/ontologySync.js +1 -1
- package/lib/esm/utils/ontologySync.js.map +1 -1
- package/lib/esm/utils/syncShapes.d.ts +3 -3
- package/lib/esm/utils/syncShapes.js +1 -1
- package/lib/esm/utils/syncShapes.js.map +1 -1
- package/package.json +5 -4
- package/readme.md +26 -18
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncShapes.js","sourceRoot":"","sources":["../../../src/utils/syncShapes.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The shape sync, as the server runs it at boot and when the host asks for a re-sync\n * (`POST /admin/sync-shapes`): core's `syncShapeGraphs` writes each package's shapes into its own\n * named graph of the app's default dataset (`{package IRI}/graph/shapes`, a `ShapesGraph` record\n * in the graph registry), skipped when the stored content hash matches, and the app's generated\n * single-owner shapes into the app's own shape graph, `{DATA_ROOT}/graph/shapes`. Shapes an\n * earlier sync wrote into the default graph are removed there once their package's graph holds\n * them. A store without graph queries gets core's default-graph shape sync instead.\n *\n * Where a package's Turtle comes from ({@link shapeTurtleSource}):\n * - an installed package: its built `lib/esm/data/shapes.ttl` (written by `linked build`); a\n * package without that file gets no shape graph, and nothing is generated for it;\n * - the app's own packages (the app and its workspace packages): in dev, generated in process\n * from their source shapes, through Vite's loader, so the core the SSR graph registered the\n * shapes on writes them (the same bytes as `packageShapesTurtle`, which `linked build` writes);\n * in a built app, their `lib/esm/data/shapes.ttl` when there is one, else generated in process.\n *\n * Kept apart from `LinkedServer` so the choices and the log can be tested without booting a\n * server.\n */\nimport fs from 'fs';\nimport path from 'path';\n\n/** The orphan policies a booting server may run with. */\nexport type BootOrphanScope = 'all' | 'none';\n\n/**\n * The orphan policy for the shape sync.\n *\n * `'none'` unless the operator sets `LINKED_SYNC_SHAPES_PRUNE_ORPHANS=true`, which drops the\n * shape graph of every package that is no longer registered in this process (never the app's own\n * graph).\n *\n * The registry is routinely a subset of what the dataset holds: shapes are deep-importable one\n * file at a time, an app's backend may import no shapes at all, and an app-data dataset also holds\n * shapes other writers put there. So nothing is pruned by default.\n */\nexport function bootOrphanScope(\n env: Record<string, string | undefined> = process.env,\n): BootOrphanScope {\n return env.LINKED_SYNC_SHAPES_PRUNE_ORPHANS === 'true' ? 'all' : 'none';\n}\n\n/** What core's `syncShapeGraphs` reports (`@_linked/core/shapes/syncShapeGraphs`). */\nexport interface ShapeGraphSyncResult {\n written: string[];\n skipped: string[];\n pruned: string[];\n cleaned: number;\n appGraph?: 'written' | 'skipped' | 'dropped';\n defaultGraph?: number;\n /** The store's `shapeGraph` target the run wrote in (core ≥ 2.41): `'package'`, `'default'` or an IRI. */\n target?: string;\n /** Set when a store without graph queries took the default-graph sync instead of `target`. */\n fallback?: true;\n}\n\n/** The subset of core's shape graph API this module calls. */\nexport interface ShapeGraphCore {\n syncShapeGraphs(\n ds: unknown,\n options: {\n orphanScope: BootOrphanScope;\n packages?: string[];\n turtleFor: (packageName: string) => Promise<string | undefined>;\n appShapes?: {graph: string; package?: string};\n },\n ): Promise<ShapeGraphSyncResult>;\n /** Every package with registered shapes (core counted for its built-ins). */\n packagesWithShapes(): string[];\n /** A package's shape graph IRI (`ShapesGraph.iriFor`). */\n shapesGraphFor(packageName: string): string;\n}\n\n/** Import core's shape graph sync. */\nexport async function loadShapeGraphCore(): Promise<ShapeGraphCore> {\n const sync = await import('@_linked/core/shapes/syncShapeGraphs');\n const turtle = await import('@_linked/core/shapes/shapesToTurtle');\n const graphs = await import('@_linked/core/shapes/NamedGraph');\n return {\n syncShapeGraphs: (ds, options) =>\n sync.syncShapeGraphs(ds as Parameters<typeof sync.syncShapeGraphs>[0], options),\n packagesWithShapes: () => turtle.packagesWithShapes(),\n shapesGraphFor: (packageName) => graphs.ShapesGraph.iriFor(packageName),\n };\n}\n\n/** Where `linked build` writes a package's shapes, relative to the package root. */\nexport const SHAPES_TURTLE_FILE = path.join('lib', 'esm', 'data', 'shapes.ttl');\n\n/** A package's built `shapes.ttl`, or undefined when the package root has none. */\nexport function readShapesTurtle(packageDir: string | undefined): string | undefined {\n if (!packageDir) return undefined;\n try {\n return fs.readFileSync(path.join(packageDir, SHAPES_TURTLE_FILE), 'utf-8');\n } catch {\n return undefined;\n }\n}\n\n/** Where one package's Turtle comes from. */\nexport type ShapeTurtleSource =\n | {source: 'file'; text: string}\n | {source: 'generated'}\n | {source: 'none'};\n\n/**\n * Where a registered package's Turtle comes from: in dev an own package is generated; otherwise\n * its built file when it has one; else an own package is generated and an installed one has\n * none (no shape graph, no generation).\n */\nexport function shapeTurtleSource(\n packageName: string,\n {\n own,\n dev,\n packageDir,\n read = readShapesTurtle,\n }: {\n /** Whether the package is the app or one of its workspace packages. */\n own: boolean;\n /** Whether the server runs with Vite (dev). */\n dev: boolean;\n /** The package root, when the server knows it. */\n packageDir: string | undefined;\n read?: (packageDir: string | undefined) => string | undefined;\n },\n): ShapeTurtleSource {\n if (own && dev) return {source: 'generated'};\n const text = read(packageDir);\n if (text !== undefined) return {source: 'file', text};\n return own ? {source: 'generated'} : {source: 'none'};\n}\n\n/**\n * The app's own shape graph, `{DATA_ROOT}/graph/shapes`, or undefined when `DATA_ROOT` is not\n * an absolute IRI.\n */\nexport function appShapesGraph(\n env: Record<string, string | undefined> = process.env,\n): string | undefined {\n const root = env.DATA_ROOT?.trim().replace(/\\/+$/, '');\n if (!root || !/^[a-z][a-z0-9+.-]*:\\/\\/[^/]/i.test(root)) return undefined;\n return `${root}/graph/shapes`;\n}\n\n/**\n * In dev, the generator for the app's own packages: core's `packageShapesTurtle` imported through\n * Vite's `ssrLoadModule`, the core the SSR graph registered the source shapes on. Undefined\n * without Vite.\n */\nexport function viteShapesTurtleGenerator(\n vite: {ssrLoadModule?: (url: string) => Promise<unknown>} | undefined | null,\n): ((packageName: string) => Promise<string | undefined>) | undefined {\n const ssrLoadModule = vite?.ssrLoadModule;\n if (typeof ssrLoadModule !== 'function') return undefined;\n return async (packageName) => {\n const mod = (await ssrLoadModule.call(vite, '@_linked/core/shapes/shapesToTurtle')) as {\n packageShapesTurtle?: (name: string) => string | undefined;\n };\n if (typeof mod?.packageShapesTurtle !== 'function') {\n throw new Error('@_linked/core/shapes/shapesToTurtle has no packageShapesTurtle');\n }\n return mod.packageShapesTurtle(packageName);\n };\n}\n\n/** What one shape sync did, as the boot logs it and `POST /admin/sync-shapes` reports it. */\nexport interface ShapeGraphsReport {\n /** Packages whose shape graph was written, and those left as they were. */\n written: string[];\n skipped: string[];\n /** Packages no longer registered whose shape graph was dropped (`orphanScope: 'all'`). */\n pruned: string[];\n /** The shape graphs written (package graphs, then the app graph), by IRI. */\n graphs: string[];\n /** The app's own shape graph and what the sync did with it; absent without `DATA_ROOT`. */\n appGraph?: {graph: string; status: 'written' | 'skipped' | 'dropped'};\n /**\n * Registered packages with no Turtle, so with no shape graph: an installed package without\n * `shapes.ttl`, or an own package whose shapes could not be generated.\n */\n withoutTurtle: string[];\n /** Shapes an earlier sync had written into the default graph, removed now. */\n cleaned: number;\n /**\n * Set when the shapes went into the default graph (the store's `shapeGraph` is `'default'`, or\n * it has no graph queries): the default-graph sync's writes.\n */\n defaultGraph?: number;\n /** The store's `shapeGraph` target (`'package'`, `'default'` or a shared graph IRI), when core reports it. */\n target?: string;\n /** Set when the store has no graph queries, so the shapes went into the default graph instead of `target`. */\n fallback?: true;\n}\n\nconst list = (names: string[]) => (names.length ? names.join(', ') : 'none');\n\n/**\n * Sync the registered shapes into `ds`, one shape graph per package (see the module doc), and log\n * one line naming what was written and skipped, the graphs written, the packages without\n * `shapes.ttl` and the default-graph shapes removed. Throws when the sync fails.\n */\nexport async function syncShapeGraphsInto(\n ds: unknown,\n {\n core,\n orphanScope,\n isOwn,\n dev,\n packageDirOf,\n generate,\n appGraph,\n appPackage,\n read = readShapesTurtle,\n log = console.log,\n warn = console.warn,\n }: {\n core: ShapeGraphCore;\n orphanScope: BootOrphanScope;\n /** Whether a package is the app or one of its workspace packages. */\n isOwn: (packageName: string) => boolean;\n /** Whether the server runs with Vite (dev). */\n dev: boolean;\n /** A package's root directory, when the server knows it. */\n packageDirOf: (packageName: string) => string | undefined;\n /**\n * Generates an own package's Turtle (in dev through Vite's loader); undefined, or a result of\n * undefined, leaves the generation to the core that runs the sync.\n */\n generate?: (packageName: string) => Promise<string | undefined>;\n /** The app's own shape graph (`{DATA_ROOT}/graph/shapes`). */\n appGraph?: string;\n /** The app's package name, recorded on its shape graph's record. */\n appPackage?: string;\n read?: (packageDir: string | undefined) => string | undefined;\n log?: (message: string) => void;\n warn?: (message: string, err?: unknown) => void;\n },\n): Promise<ShapeGraphsReport> {\n const sources = new Map<string, ShapeTurtleSource>();\n for (const name of core.packagesWithShapes()) {\n sources.set(name, shapeTurtleSource(name, {own: isOwn(name), dev, packageDir: packageDirOf(name), read}));\n }\n const noFile = [...sources].filter(([, s]) => s.source === 'none').map(([name]) => name);\n\n const turtleFor = async (name: string): Promise<string | undefined> => {\n const source = sources.get(name);\n if (source?.source === 'file') return source.text;\n if (source?.source !== 'generated' || !generate) return undefined;\n try {\n return await generate(name);\n } catch (err) {\n warn(`[LinkedServer] generating the shapes of ${name} through the dev loader failed; trying the server's core instead:`, err);\n return undefined;\n }\n };\n\n const result = await core.syncShapeGraphs(ds, {\n orphanScope,\n // A package without Turtle is left out: core would generate it otherwise.\n ...(noFile.length ? {packages: [...sources.keys()].filter((n) => !noFile.includes(n))} : {}),\n turtleFor,\n ...(appGraph ? {appShapes: {graph: appGraph, ...(appPackage ? {package: appPackage} : {})}} : {}),\n });\n\n // A package core neither wrote nor skipped got no Turtle at all: generation produced nothing\n // (in dev, the server's core may not hold the source shapes the dev loader registered). The\n // default-graph sync (a store without graph queries) reports no packages, so it is not checked.\n const covered = new Set([...result.written, ...result.skipped]);\n const notGenerated =\n result.defaultGraph !== undefined\n ? []\n : [...sources.keys()].filter((n) => !noFile.includes(n) && !covered.has(n));\n if (notGenerated.length) {\n warn(\n `[LinkedServer] no shapes could be generated for ${list(notGenerated.sort())}, so ` +\n `${notGenerated.length === 1 ? 'it has' : 'they have'} no shape graph this sync`,\n );\n }\n const withoutTurtle = [...noFile, ...notGenerated].sort();\n\n // A shared graph (the store's `shapeGraph` is an IRI) holds every package and the app's shapes.\n const shared = result.target && result.target !== 'package' && result.target !== 'default' ? result.target : undefined;\n const report: ShapeGraphsReport = {\n written: result.written,\n skipped: result.skipped,\n pruned: result.pruned,\n // A shared graph is written whole or not at all: listed when the run wrote anything into it.\n graphs: shared\n ? result.written.length || result.appGraph === 'written' || result.pruned.length\n ? [shared]\n : []\n : result.written.map((name) => core.shapesGraphFor(name)),\n withoutTurtle,\n cleaned: result.cleaned,\n };\n if (result.target) report.target = result.target;\n if (result.fallback) report.fallback = true;\n if (appGraph && result.appGraph) {\n report.appGraph = {graph: shared ?? appGraph, status: result.appGraph};\n if (result.appGraph === 'written' && !shared) report.graphs.push(appGraph);\n }\n if (result.defaultGraph !== undefined) report.defaultGraph = result.defaultGraph;\n\n if (report.defaultGraph !== undefined) {\n const why =\n result.target === 'default' && !result.fallback\n ? \"shapeGraph is 'default'\"\n : 'the store has no graph queries';\n log(`[LinkedServer] shape sync (default graph: ${why}): ${report.defaultGraph} shape(s) written`);\n } else if (shared) {\n log(\n `[LinkedServer] shape graph sync (one shared graph <${shared}>): written ${list(report.written)}; ` +\n `skipped ${list(report.skipped)}` +\n (report.appGraph ? `; app shapes ${report.appGraph.status}` : '') +\n (report.pruned.length ? `; dropped from the graph ${list(report.pruned)}` : '') +\n (withoutTurtle.length ? `; no shapes.ttl (not in the graph): ${list(withoutTurtle)}` : ''),\n );\n // Unlike package graphs, which stay when a package goes missing, the shared graph is rebuilt\n // from the packages the run covers.\n if (withoutTurtle.length) {\n warn(\n `[LinkedServer] the shared shape graph <${shared}> holds no shapes of ${list(withoutTurtle)}: ` +\n 'a package without Turtle in a run is left out of the rebuilt graph',\n );\n }\n } else {\n log(\n `[LinkedServer] shape graph sync: written ${list(report.written)}; skipped ${list(report.skipped)}` +\n (report.appGraph ? `; app graph ${report.appGraph.status}` : '; no app graph (DATA_ROOT not set)') +\n (report.graphs.length ? `; graphs written ${list(report.graphs)}` : '') +\n (orphanScope === 'all' ? `; pruned ${list(report.pruned)}` : '') +\n (report.cleaned ? `; ${report.cleaned} default-graph shape(s) removed` : '') +\n (withoutTurtle.length ? `; no shapes.ttl (no shape graph): ${list(withoutTurtle)}` : ''),\n );\n }\n if (orphanScope === 'all' && withoutTurtle.length && !shared) {\n warn(\n '[LinkedServer] orphaned shape graphs were not pruned: core prunes only when the sync covers ' +\n `every registered package, and ${list(withoutTurtle)} has no Turtle`,\n );\n }\n return report;\n}\n\n/**\n * @deprecated The default-graph shape sync's callback type; the server now syncs shape graphs with\n * {@link syncShapeGraphsInto}. Kept so code built against an earlier server still compiles.\n */\nexport type SyncShapesFn = (\n ds: unknown,\n options: {orphanScope: BootOrphanScope},\n) => Promise<Array<() => Promise<void>>>;\n\n/**\n * @deprecated Use {@link syncShapeGraphsInto}, which writes each package's shapes into its own\n * shape graph. This runs the old default-graph sync: it plans every registered shape with\n * `syncShapes` (the orphan policy from {@link bootOrphanScope}) and runs the writes in batches\n * of 8. Kept so code built against an earlier server keeps working.\n */\nexport async function materializeShapes(\n ds: unknown,\n syncShapes: SyncShapesFn,\n {\n env = process.env,\n log = console.log,\n }: {\n env?: Record<string, string | undefined>;\n log?: (message: string) => void;\n } = {},\n): Promise<{count: number; orphanScope: BootOrphanScope}> {\n const orphanScope = bootOrphanScope(env);\n const thunks = await syncShapes(ds, {orphanScope});\n for (let i = 0; i < thunks.length; i += 8) {\n await Promise.all(thunks.slice(i, i + 8).map((run) => run()));\n }\n log(\n `[LinkedServer] synced shapes into the default graph with orphanScope '${orphanScope}': ` +\n `${thunks.length} operation(s)`,\n );\n return {count: thunks.length, orphanScope};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"syncShapes.js","sourceRoot":"","sources":["../../../src/utils/syncShapes.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The shape sync, as the server runs it at boot and when the host asks for a re-sync\n * (`POST /admin/sync-shapes`): core's `syncShapeGraphs` writes each package's shapes into its own\n * named graph of the app's default dataset (`{package IRI}/graph/shapes`, a `ShapesGraph` record\n * in the graph registry), skipped when the stored content hash matches, and the app's generated\n * single-owner shapes into the app's own shape graph, `{DATA_ROOT}/graph/shapes`. Shapes an\n * earlier sync wrote into the default graph are removed there once their package's graph holds\n * them. A store without graph queries gets core's default-graph shape sync instead.\n *\n * Where a package's Turtle comes from ({@link shapeTurtleSource}):\n * - an installed package: its built `lib/esm/data/shapes.ttl` (written by `linked build`); a\n * package without that file gets no shape graph, and nothing is generated for it;\n * - the app's own packages (the app and its workspace packages): in dev, generated in process\n * from their source shapes, through Vite's loader, so the core the SSR graph registered the\n * shapes on writes them (the same bytes as `packageShapesTurtle`, which `linked build` writes);\n * in a built app, their `lib/esm/data/shapes.ttl` when there is one, else generated in process.\n *\n * Kept apart from `LinkedServer` so the choices and the log can be tested without booting a\n * server.\n */\nimport fs from 'fs';\nimport path from 'path';\n\n/** The orphan policies a booting server may run with. */\nexport type BootOrphanScope = 'all' | 'none';\n\n/**\n * The orphan policy for the shape sync.\n *\n * `'none'` unless the operator sets `LINKED_SYNC_SHAPES_PRUNE_ORPHANS=true`, which drops the\n * shape graph of every package that is no longer registered in this process (never the app's own\n * graph).\n *\n * The registry is routinely a subset of what the dataset holds: shapes are deep-importable one\n * file at a time, an app's backend may import no shapes at all, and an app-data dataset also holds\n * shapes other writers put there. So nothing is pruned by default.\n */\nexport function bootOrphanScope(\n env: Record<string, string | undefined> = process.env,\n): BootOrphanScope {\n return env.LINKED_SYNC_SHAPES_PRUNE_ORPHANS === 'true' ? 'all' : 'none';\n}\n\n/** What core's `syncShapeGraphs` reports (`@_linked/core/shapes/syncShapeGraphs`). */\nexport interface ShapeGraphSyncResult {\n written: string[];\n skipped: string[];\n pruned: string[];\n cleaned: number;\n appGraph?: 'written' | 'skipped' | 'dropped';\n defaultGraph?: number;\n /** The global `shapeGraph` target the run wrote in (core ≥ 2.41): `'package'`, `'default'` or an IRI. */\n target?: string;\n /** Set when a store without graph queries took the default-graph sync instead of `target`. */\n fallback?: true;\n}\n\n/** The subset of core's shape graph API this module calls. */\nexport interface ShapeGraphCore {\n syncShapeGraphs(\n ds: unknown,\n options: {\n orphanScope: BootOrphanScope;\n packages?: string[];\n turtleFor: (packageName: string) => Promise<string | undefined>;\n appShapes?: {graph: string; package?: string};\n },\n ): Promise<ShapeGraphSyncResult>;\n /** Every package with registered shapes (core counted for its built-ins). */\n packagesWithShapes(): string[];\n /** A package's shape graph IRI (`ShapesGraph.iriFor`). */\n shapesGraphFor(packageName: string): string;\n}\n\n/** Import core's shape graph sync. */\nexport async function loadShapeGraphCore(): Promise<ShapeGraphCore> {\n const sync = await import('@_linked/core/shapes/syncShapeGraphs');\n const turtle = await import('@_linked/core/shapes/shapesToTurtle');\n const graphs = await import('@_linked/core/shapes/NamedGraph');\n return {\n syncShapeGraphs: (ds, options) =>\n sync.syncShapeGraphs(ds as Parameters<typeof sync.syncShapeGraphs>[0], options),\n packagesWithShapes: () => turtle.packagesWithShapes(),\n shapesGraphFor: (packageName) => graphs.ShapesGraph.iriFor(packageName),\n };\n}\n\n/** Where `linked build` writes a package's shapes, relative to the package root. */\nexport const SHAPES_TURTLE_FILE = path.join('lib', 'esm', 'data', 'shapes.ttl');\n\n/** A package's built `shapes.ttl`, or undefined when the package root has none. */\nexport function readShapesTurtle(packageDir: string | undefined): string | undefined {\n if (!packageDir) return undefined;\n try {\n return fs.readFileSync(path.join(packageDir, SHAPES_TURTLE_FILE), 'utf-8');\n } catch {\n return undefined;\n }\n}\n\n/** Where one package's Turtle comes from. */\nexport type ShapeTurtleSource =\n | {source: 'file'; text: string}\n | {source: 'generated'}\n | {source: 'none'};\n\n/**\n * Where a registered package's Turtle comes from: in dev an own package is generated; otherwise\n * its built file when it has one; else an own package is generated and an installed one has\n * none (no shape graph, no generation).\n */\nexport function shapeTurtleSource(\n packageName: string,\n {\n own,\n dev,\n packageDir,\n read = readShapesTurtle,\n }: {\n /** Whether the package is the app or one of its workspace packages. */\n own: boolean;\n /** Whether the server runs with Vite (dev). */\n dev: boolean;\n /** The package root, when the server knows it. */\n packageDir: string | undefined;\n read?: (packageDir: string | undefined) => string | undefined;\n },\n): ShapeTurtleSource {\n if (own && dev) return {source: 'generated'};\n const text = read(packageDir);\n if (text !== undefined) return {source: 'file', text};\n return own ? {source: 'generated'} : {source: 'none'};\n}\n\n/**\n * The app's own shape graph, `{DATA_ROOT}/graph/shapes`, or undefined when `DATA_ROOT` is not\n * an absolute IRI.\n */\nexport function appShapesGraph(\n env: Record<string, string | undefined> = process.env,\n): string | undefined {\n const root = env.DATA_ROOT?.trim().replace(/\\/+$/, '');\n if (!root || !/^[a-z][a-z0-9+.-]*:\\/\\/[^/]/i.test(root)) return undefined;\n return `${root}/graph/shapes`;\n}\n\n/**\n * In dev, the generator for the app's own packages: core's `packageShapesTurtle` imported through\n * Vite's `ssrLoadModule`, the core the SSR graph registered the source shapes on. Undefined\n * without Vite.\n */\nexport function viteShapesTurtleGenerator(\n vite: {ssrLoadModule?: (url: string) => Promise<unknown>} | undefined | null,\n): ((packageName: string) => Promise<string | undefined>) | undefined {\n const ssrLoadModule = vite?.ssrLoadModule;\n if (typeof ssrLoadModule !== 'function') return undefined;\n return async (packageName) => {\n const mod = (await ssrLoadModule.call(vite, '@_linked/core/shapes/shapesToTurtle')) as {\n packageShapesTurtle?: (name: string) => string | undefined;\n };\n if (typeof mod?.packageShapesTurtle !== 'function') {\n throw new Error('@_linked/core/shapes/shapesToTurtle has no packageShapesTurtle');\n }\n return mod.packageShapesTurtle(packageName);\n };\n}\n\n/** What one shape sync did, as the boot logs it and `POST /admin/sync-shapes` reports it. */\nexport interface ShapeGraphsReport {\n /** Packages whose shape graph was written, and those left as they were. */\n written: string[];\n skipped: string[];\n /** Packages no longer registered whose shape graph was dropped (`orphanScope: 'all'`). */\n pruned: string[];\n /** The shape graphs written (package graphs, then the app graph), by IRI. */\n graphs: string[];\n /** The app's own shape graph and what the sync did with it; absent without `DATA_ROOT`. */\n appGraph?: {graph: string; status: 'written' | 'skipped' | 'dropped'};\n /**\n * Registered packages with no Turtle, so with no shape graph: an installed package without\n * `shapes.ttl`, or an own package whose shapes could not be generated.\n */\n withoutTurtle: string[];\n /** Shapes an earlier sync had written into the default graph, removed now. */\n cleaned: number;\n /**\n * Set when the shapes went into the default graph (the global `shapeGraph` is `'default'`, or\n * it has no graph queries): the default-graph sync's writes.\n */\n defaultGraph?: number;\n /** The global `shapeGraph` target (`'package'`, `'default'` or a shared graph IRI), when core reports it. */\n target?: string;\n /** Set when the store has no graph queries, so the shapes went into the default graph instead of `target`. */\n fallback?: true;\n}\n\nconst list = (names: string[]) => (names.length ? names.join(', ') : 'none');\n\n/**\n * Sync the registered shapes into `ds`, one shape graph per package (see the module doc), and log\n * one line naming what was written and skipped, the graphs written, the packages without\n * `shapes.ttl` and the default-graph shapes removed. Throws when the sync fails.\n */\nexport async function syncShapeGraphsInto(\n ds: unknown,\n {\n core,\n orphanScope,\n isOwn,\n dev,\n packageDirOf,\n generate,\n appGraph,\n appPackage,\n read = readShapesTurtle,\n log = console.log,\n warn = console.warn,\n }: {\n core: ShapeGraphCore;\n orphanScope: BootOrphanScope;\n /** Whether a package is the app or one of its workspace packages. */\n isOwn: (packageName: string) => boolean;\n /** Whether the server runs with Vite (dev). */\n dev: boolean;\n /** A package's root directory, when the server knows it. */\n packageDirOf: (packageName: string) => string | undefined;\n /**\n * Generates an own package's Turtle (in dev through Vite's loader); undefined, or a result of\n * undefined, leaves the generation to the core that runs the sync.\n */\n generate?: (packageName: string) => Promise<string | undefined>;\n /** The app's own shape graph (`{DATA_ROOT}/graph/shapes`). */\n appGraph?: string;\n /** The app's package name, recorded on its shape graph's record. */\n appPackage?: string;\n read?: (packageDir: string | undefined) => string | undefined;\n log?: (message: string) => void;\n warn?: (message: string, err?: unknown) => void;\n },\n): Promise<ShapeGraphsReport> {\n const sources = new Map<string, ShapeTurtleSource>();\n for (const name of core.packagesWithShapes()) {\n sources.set(name, shapeTurtleSource(name, {own: isOwn(name), dev, packageDir: packageDirOf(name), read}));\n }\n const noFile = [...sources].filter(([, s]) => s.source === 'none').map(([name]) => name);\n\n const turtleFor = async (name: string): Promise<string | undefined> => {\n const source = sources.get(name);\n if (source?.source === 'file') return source.text;\n if (source?.source !== 'generated' || !generate) return undefined;\n try {\n return await generate(name);\n } catch (err) {\n warn(`[LinkedServer] generating the shapes of ${name} through the dev loader failed; trying the server's core instead:`, err);\n return undefined;\n }\n };\n\n const result = await core.syncShapeGraphs(ds, {\n orphanScope,\n // A package without Turtle is left out: core would generate it otherwise.\n ...(noFile.length ? {packages: [...sources.keys()].filter((n) => !noFile.includes(n))} : {}),\n turtleFor,\n ...(appGraph ? {appShapes: {graph: appGraph, ...(appPackage ? {package: appPackage} : {})}} : {}),\n });\n\n // A package core neither wrote nor skipped got no Turtle at all: generation produced nothing\n // (in dev, the server's core may not hold the source shapes the dev loader registered). The\n // default-graph sync (a store without graph queries) reports no packages, so it is not checked.\n const covered = new Set([...result.written, ...result.skipped]);\n const notGenerated =\n result.defaultGraph !== undefined\n ? []\n : [...sources.keys()].filter((n) => !noFile.includes(n) && !covered.has(n));\n if (notGenerated.length) {\n warn(\n `[LinkedServer] no shapes could be generated for ${list(notGenerated.sort())}, so ` +\n `${notGenerated.length === 1 ? 'it has' : 'they have'} no shape graph this sync`,\n );\n }\n const withoutTurtle = [...noFile, ...notGenerated].sort();\n\n // A shared graph (the global `shapeGraph` is an IRI) holds every package and the app's shapes.\n const shared = result.target && result.target !== 'package' && result.target !== 'default' ? result.target : undefined;\n const report: ShapeGraphsReport = {\n written: result.written,\n skipped: result.skipped,\n pruned: result.pruned,\n // A shared graph is written whole or not at all: listed when the run wrote anything into it.\n graphs: shared\n ? result.written.length || result.appGraph === 'written' || result.pruned.length\n ? [shared]\n : []\n : result.written.map((name) => core.shapesGraphFor(name)),\n withoutTurtle,\n cleaned: result.cleaned,\n };\n if (result.target) report.target = result.target;\n if (result.fallback) report.fallback = true;\n if (appGraph && result.appGraph) {\n report.appGraph = {graph: shared ?? appGraph, status: result.appGraph};\n if (result.appGraph === 'written' && !shared) report.graphs.push(appGraph);\n }\n if (result.defaultGraph !== undefined) report.defaultGraph = result.defaultGraph;\n\n if (report.defaultGraph !== undefined) {\n const why =\n result.target === 'default' && !result.fallback\n ? \"shapeGraph is 'default'\"\n : 'the store has no graph queries';\n log(`[LinkedServer] shape sync (default graph: ${why}): ${report.defaultGraph} shape(s) written`);\n } else if (shared) {\n log(\n `[LinkedServer] shape graph sync (one shared graph <${shared}>): written ${list(report.written)}; ` +\n `skipped ${list(report.skipped)}` +\n (report.appGraph ? `; app shapes ${report.appGraph.status}` : '') +\n (report.pruned.length ? `; dropped from the graph ${list(report.pruned)}` : '') +\n (withoutTurtle.length ? `; no shapes.ttl (not in the graph): ${list(withoutTurtle)}` : ''),\n );\n // Unlike package graphs, which stay when a package goes missing, the shared graph is rebuilt\n // from the packages the run covers.\n if (withoutTurtle.length) {\n warn(\n `[LinkedServer] the shared shape graph <${shared}> holds no shapes of ${list(withoutTurtle)}: ` +\n 'a package without Turtle in a run is left out of the rebuilt graph',\n );\n }\n } else {\n log(\n `[LinkedServer] shape graph sync: written ${list(report.written)}; skipped ${list(report.skipped)}` +\n (report.appGraph ? `; app graph ${report.appGraph.status}` : '; no app graph (DATA_ROOT not set)') +\n (report.graphs.length ? `; graphs written ${list(report.graphs)}` : '') +\n (orphanScope === 'all' ? `; pruned ${list(report.pruned)}` : '') +\n (report.cleaned ? `; ${report.cleaned} default-graph shape(s) removed` : '') +\n (withoutTurtle.length ? `; no shapes.ttl (no shape graph): ${list(withoutTurtle)}` : ''),\n );\n }\n if (orphanScope === 'all' && withoutTurtle.length && !shared) {\n warn(\n '[LinkedServer] orphaned shape graphs were not pruned: core prunes only when the sync covers ' +\n `every registered package, and ${list(withoutTurtle)} has no Turtle`,\n );\n }\n return report;\n}\n\n/**\n * @deprecated The default-graph shape sync's callback type; the server now syncs shape graphs with\n * {@link syncShapeGraphsInto}. Kept so code built against an earlier server still compiles.\n */\nexport type SyncShapesFn = (\n ds: unknown,\n options: {orphanScope: BootOrphanScope},\n) => Promise<Array<() => Promise<void>>>;\n\n/**\n * @deprecated Use {@link syncShapeGraphsInto}, which writes each package's shapes into its own\n * shape graph. This runs the old default-graph sync: it plans every registered shape with\n * `syncShapes` (the orphan policy from {@link bootOrphanScope}) and runs the writes in batches\n * of 8. Kept so code built against an earlier server keeps working.\n */\nexport async function materializeShapes(\n ds: unknown,\n syncShapes: SyncShapesFn,\n {\n env = process.env,\n log = console.log,\n }: {\n env?: Record<string, string | undefined>;\n log?: (message: string) => void;\n } = {},\n): Promise<{count: number; orphanScope: BootOrphanScope}> {\n const orphanScope = bootOrphanScope(env);\n const thunks = await syncShapes(ds, {orphanScope});\n for (let i = 0; i < thunks.length; i += 8) {\n await Promise.all(thunks.slice(i, i + 8).map((run) => run()));\n }\n log(\n `[LinkedServer] synced shapes into the default graph with orphanScope '${orphanScope}': ` +\n `${thunks.length} operation(s)`,\n );\n return {count: thunks.length, orphanScope};\n}\n"]}
|
package/package.json
CHANGED
|
@@ -10,17 +10,18 @@
|
|
|
10
10
|
"type": "git",
|
|
11
11
|
"url": "git+https://github.com/linked-fw/server.git"
|
|
12
12
|
},
|
|
13
|
-
"version": "3.
|
|
13
|
+
"version": "3.12.1",
|
|
14
14
|
"packageManager": "npm@12.2.0",
|
|
15
15
|
"linkedPackage": true,
|
|
16
16
|
"type": "module",
|
|
17
17
|
"main": "lib/esm/index.js",
|
|
18
18
|
"types": "index.d.ts",
|
|
19
|
-
"license": "
|
|
19
|
+
"license": "MIT",
|
|
20
20
|
"files": [
|
|
21
21
|
"lib",
|
|
22
22
|
"styles",
|
|
23
|
-
"CHANGELOG.md"
|
|
23
|
+
"CHANGELOG.md",
|
|
24
|
+
"LICENSE"
|
|
24
25
|
],
|
|
25
26
|
"scripts": {
|
|
26
27
|
"start": "npm exec linked dev",
|
|
@@ -39,7 +40,7 @@
|
|
|
39
40
|
],
|
|
40
41
|
"dependencies": {
|
|
41
42
|
"@_linked/cli": "^1.54.0",
|
|
42
|
-
"@_linked/core": "^2.
|
|
43
|
+
"@_linked/core": "^2.42.0",
|
|
43
44
|
"@_linked/server-utils": "^1.16.1",
|
|
44
45
|
"autoprefixer": "^10.4.18",
|
|
45
46
|
"compression": "^1.7.4",
|
package/readme.md
CHANGED
|
@@ -60,7 +60,7 @@ NODE_ENV=development
|
|
|
60
60
|
# Usually no longer needed: see "Where asset URLs come from" below.
|
|
61
61
|
STATIC_ACCESS_URL=https://cdn.my-site.com/releases/1.5.0-2a77e89f
|
|
62
62
|
|
|
63
|
-
# Optional. Where the
|
|
63
|
+
# Optional. Where the boot syncs keep the packages' ontology data and shapes:
|
|
64
64
|
# 'package' (the default), 'default', or the absolute IRI of one shared graph.
|
|
65
65
|
# See "Ontology and shape graphs" below.
|
|
66
66
|
LINKED_ONTOLOGY_GRAPH=package
|
|
@@ -70,7 +70,8 @@ LINKED_SHAPE_GRAPH=package
|
|
|
70
70
|
### Ontology and shape graphs
|
|
71
71
|
|
|
72
72
|
`LINKED_ONTOLOGY_GRAPH` and `LINKED_SHAPE_GRAPH` set core's graph targets (`ontologyGraph`,
|
|
73
|
-
`shapeGraph`)
|
|
73
|
+
`shapeGraph`). They are **one global setting of the process**, not a store's: no store, store
|
|
74
|
+
option or datasets config entry takes them.
|
|
74
75
|
|
|
75
76
|
| Value | The ontology sync writes | The shape sync writes |
|
|
76
77
|
|---|---|---|
|
|
@@ -78,16 +79,24 @@ LINKED_SHAPE_GRAPH=package
|
|
|
78
79
|
| `default` | the whole ontology into the default graph | every shape into the default graph |
|
|
79
80
|
| an absolute IRI | one shared graph at that IRI, holding every package | one shared graph at that IRI, holding every package and the app's generated shapes |
|
|
80
81
|
|
|
81
|
-
At boot, before the stores
|
|
82
|
-
neither keyword nor an absolute IRI, one IRI for both, a portable graph name
|
|
83
|
-
store-native name (`urn:x-arq:…`) or a package's own graph name
|
|
84
|
-
`/graph/shapes`) stops the boot with a fatal error naming the
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
82
|
+
At boot, before the boot initialises the stores and before the syncs, the server checks both variables:
|
|
83
|
+
a value that is neither keyword nor an absolute IRI, one IRI for both, a portable graph name
|
|
84
|
+
(`graphs.*`), a store-native name (`urn:x-arq:…`) or a package's own graph name
|
|
85
|
+
(`…/pkg/{slug}/graph/ontology` or `/graph/shapes`) stops the boot with a fatal error naming the
|
|
86
|
+
variable. It then calls core's `setGraphTargets` once with them (an unset variable is `package`).
|
|
87
|
+
Every store's readers follow the same setting (`graphs.allOntologies`, `graphs.allShapes`).
|
|
88
|
+
`GET /admin/routes` reports the setting (`graphTargets`) and the variables as set.
|
|
89
|
+
|
|
90
|
+
**The frontend needs nothing.** A browser's `.from(graphs.allOntologies)` or
|
|
91
|
+
`.from(graphs.allShapes)` reaches the backend as the portable name, and the backend's store
|
|
92
|
+
expands it under the backend's setting.
|
|
93
|
+
|
|
94
|
+
**The syncs write into the default dataset only.** When the app's routing pins the shape shapes
|
|
95
|
+
(`NodeShape`, `PropertyShape`) or the ontology term shapes (the class and property shapes core,
|
|
96
|
+
`@_linked/rdfs` and `@_linked/owl` register: `rdfs:Class`, `owl:Class`, `rdf:Property`,
|
|
97
|
+
`owl:ObjectProperty`, `owl:DatatypeProperty`, `owl:AnnotationProperty`) to another dataset, the
|
|
98
|
+
boot logs one warning naming those shapes (and their sub-shapes) and their dataset: reads of them
|
|
99
|
+
there do not see what the syncs wrote.
|
|
91
100
|
|
|
92
101
|
Switching modes needs clearing first: the syncs never copy data from one mode's place to another's,
|
|
93
102
|
and a sync that finds another mode's data logs one warning and leaves it. The modes, the rule that a
|
|
@@ -449,7 +458,7 @@ A host that starts the app process controls it over HTTP routes on the app's own
|
|
|
449
458
|
| `GET /admin/health` | 200 `{status: 'ok'}` once the server listens (the boot ontology sync, shape check and shape sync have finished by then) |
|
|
450
459
|
| `POST /admin/restart` | 202, then the process exits; the host starts it again |
|
|
451
460
|
| `POST /admin/graph-registry-changed` | body `{dataset}`: the host changed that dataset's named graphs; the process drops its cached graph registry and answers 200 `{invalidated: dataset}`; 400 without a dataset name |
|
|
452
|
-
| `GET /admin/routes` | 200 `{datasets: [{store, id?, default, routes, defaultGraphShapes
|
|
461
|
+
| `GET /admin/routes` | 200 `{datasets: [{store, id?, default, routes, defaultGraphShapes}], graphTargets, graphTargetEnv}`: the effective graph routes and graph targets (see below) |
|
|
453
462
|
| `POST /admin/sync-shapes` | 200 `{written, orphanScope, shapeGraphs, reloaded, shapes, ontologies: {written, skipped, graphs, droppedGraphs}, shapeCheck: {errors, warnings}}` (or `{written: 0, skipped, …}` when shape sync is off); 400 `{error}` for a malformed body or a package it may not reload; 500 `{error}` when the sync fails or times out |
|
|
454
463
|
|
|
455
464
|
`POST /admin/sync-shapes` runs the ontology sync and the shape check (see [Ontology sync and the shape check](#ontology-sync-and-the-shape-check)), then re-syncs the registered shapes into the app's data exactly as the boot does (see [Shape graphs](#shape-graphs): only graphs whose stored content hash differs are written, with the boot's orphan policy and `syncShapesOnBoot` / `LINKED_SYNC_SHAPES_ON_BOOT` switches). `written` counts the shape graphs written, and `shapeGraphs` reports them. The optional body `{packages: [...]}` names packages whose source the host changed; each must be a valid npm package name and the app itself or one of its direct dependencies, never an `@_linked/*` package; the list only says what to reload, it never filters the syncs. In dev their modules are invalidated in Vite and their backends reloaded before the sync, so a shape file written a moment ago is registered; a built app reloads nothing. `reloaded` lists the packages actually reloaded and `shapes` the node shape IRIs registered afterwards, so the host can check that the shape it wrote is there. Syncs run one at a time, as the system; one that takes longer than `LINKED_SHAPE_SYNC_TIMEOUT_MS` (default 120000) fails and releases the queue. A source reload by itself (HMR) never syncs shapes. A failed ontology sync does not stop the shape sync; the route then answers 500 with the ontology error.
|
|
@@ -460,15 +469,14 @@ A host that starts the app process controls it over HTTP routes on the app's own
|
|
|
460
469
|
- `default`: whether it is the default dataset (the one for every shape without a pin).
|
|
461
470
|
- `routes`: `{<shape IRI>: <graph IRI>}` as registered. A sub-shape without a route of its own is written to its nearest routed super-shape's graph and is not listed.
|
|
462
471
|
- `defaultGraphShapes`: the registered shapes that resolve to this dataset and are written to its default graph (no route of their own, no routed super-shape), sorted.
|
|
463
|
-
- `ontologyGraph`, `shapeGraph`: the store's graph targets (`package`, `default` or a shared graph IRI; see [Ontology and shape graphs](#ontology-and-shape-graphs)), when the store has them.
|
|
464
472
|
|
|
465
|
-
`graphTargetEnv` holds `LINKED_ONTOLOGY_GRAPH` / `LINKED_SHAPE_GRAPH` as the process has them (unset ones left out), so a host
|
|
473
|
+
`graphTargets` is the process's one graph-target setting, `{ontologyGraph, shapeGraph}` (`package`, `default` or a shared graph IRI each; see [Ontology and shape graphs](#ontology-and-shape-graphs)): where the boot syncs write, for every dataset. `graphTargetEnv` holds `LINKED_ONTOLOGY_GRAPH` / `LINKED_SHAPE_GRAPH` as the process has them (unset ones left out), so a host can tell where the setting came from.
|
|
466
474
|
|
|
467
475
|
```json
|
|
468
476
|
{"datasets": [{"store": "FusekiStore", "default": true,
|
|
469
477
|
"routes": {"https://example.org/shape/Article": "https://example.org/data/graph/articles"},
|
|
470
|
-
"defaultGraphShapes": ["https://example.org/shape/Person"],
|
|
471
|
-
|
|
478
|
+
"defaultGraphShapes": ["https://example.org/shape/Person"]}],
|
|
479
|
+
"graphTargets": {"ontologyGraph": "package", "shapeGraph": "package"},
|
|
472
480
|
"graphTargetEnv": {}}
|
|
473
481
|
```
|
|
474
482
|
|
|
@@ -504,7 +512,7 @@ The boot logs one line, for example:
|
|
|
504
512
|
[LinkedServer] shape graph sync: written @acme/shop; skipped @_linked/schema; app graph written; graphs written https://linked.cm/pkg/acme-shop/graph/shapes, https://acme.example/data/graph/shapes; no shapes.ttl (no shape graph): @acme/legacy
|
|
505
513
|
```
|
|
506
514
|
|
|
507
|
-
`POST /admin/sync-shapes` answers the same as `shapeGraphs`: `{written, skipped, pruned, graphs, appGraph: {graph, status}, withoutTurtle, cleaned, target}` (plus `defaultGraph`, the default-graph sync's writes, under `LINKED_SHAPE_GRAPH=default` or on a store without graph queries). `target` is the
|
|
515
|
+
`POST /admin/sync-shapes` answers the same as `shapeGraphs`: `{written, skipped, pruned, graphs, appGraph: {graph, status}, withoutTurtle, cleaned, target}` (plus `defaultGraph`, the default-graph sync's writes, under `LINKED_SHAPE_GRAPH=default` or on a store without graph queries). `target` is the process's `shapeGraph` setting (see [Ontology and shape graphs](#ontology-and-shape-graphs)); with `fallback` set the store had no graph queries and the shapes went into the default graph instead. In a shared graph the rebuild covers the packages with Turtle: a package without it is left out (and logged), where the package mode keeps its old graph.
|
|
508
516
|
|
|
509
517
|
## Provider lifecycle and HMR
|
|
510
518
|
|