@_linked/cli 1.31.0 → 1.33.0
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 +60 -0
- package/README.md +15 -0
- package/defaults/app-react-native/packages/app-shapes/src/index.ts +2 -0
- package/defaults/app-react-native/packages/app-shapes/src/shapes/index.ts +5 -0
- package/defaults/package/src/shapes/index.ts +3 -1
- package/lib/esm/cli-methods.d.ts.map +1 -1
- package/lib/esm/cli-methods.js +144 -118
- package/lib/esm/cli-methods.js.map +1 -1
- package/lib/esm/cli.js +7 -0
- package/lib/esm/cli.js.map +1 -1
- package/lib/esm/client-dep-includes.d.ts +144 -0
- package/lib/esm/client-dep-includes.d.ts.map +1 -0
- package/lib/esm/client-dep-includes.js +827 -0
- package/lib/esm/client-dep-includes.js.map +1 -0
- package/lib/esm/commands/doctor.d.ts +19 -0
- package/lib/esm/commands/doctor.d.ts.map +1 -0
- package/lib/esm/commands/doctor.js +167 -0
- package/lib/esm/commands/doctor.js.map +1 -0
- package/lib/esm/installed-packages.d.ts +18 -0
- package/lib/esm/installed-packages.d.ts.map +1 -0
- package/lib/esm/installed-packages.js +66 -0
- package/lib/esm/installed-packages.js.map +1 -0
- package/lib/esm/utils/shapeReferences.d.ts +10 -7
- package/lib/esm/utils/shapeReferences.d.ts.map +1 -1
- package/lib/esm/utils/shapeReferences.js +13 -18
- package/lib/esm/utils/shapeReferences.js.map +1 -1
- package/lib/esm/utils/shapesIndex.d.ts +21 -0
- package/lib/esm/utils/shapesIndex.d.ts.map +1 -0
- package/lib/esm/utils/shapesIndex.js +204 -0
- package/lib/esm/utils/shapesIndex.js.map +1 -0
- package/lib/esm/vite-config.d.ts +37 -0
- package/lib/esm/vite-config.d.ts.map +1 -1
- package/lib/esm/vite-config.js +70 -51
- package/lib/esm/vite-config.js.map +1 -1
- package/package.json +5 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shapeReferences.js","sourceRoot":"","sources":["../../../src/utils/shapeReferences.ts"],"names":[],"mappings":"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","sourcesContent":["import {execFile} from 'child_process';\nimport fs from 'fs';\nimport os from 'os';\nimport path from 'path';\nimport {declaresShape} from './shapeNames.js';\n\n/**\n * Checking shape references: does loading a compiled shape module, on its own,\n * register every shape its properties point at?\n *\n * A property can name its value shape by `[package, name]` instead of by class\n * (`shape: ['@_linked/schema', 'ImageObject']`), usually because importing the\n * class would close an import cycle. That names the shape without loading it.\n * A shape registers only when its module is evaluated, and consumers deep-import\n * single shape modules (`@_linked/schema/shapes/Thing`), so nothing guarantees\n * the named shape is registered when a query traverses the property. The query\n * then throws `Shape class not found for …/ImageObject` — in a production bundle,\n * far from the cause. A reference to a package under an old name\n * (`['lincd-sioc', …]`) can never resolve at all.\n *\n * So each module is loaded the way a consumer's fresh process would load it: in\n * a child `node` of its own, with nothing else imported first. Separate processes\n * rather than one process re-importing: ESM has no module-cache eviction, and the\n * shape registry lives on `globalThis`, so a second module in the same process\n * would see every shape the first one registered.\n */\n\n/** One module that could not be evaluated. */\nexport interface ShapeModuleLoadError {\n module: string;\n error: string;\n}\n\n/**\n * A property whose value shape was not registered after loading `modules`\n * (each on its own). One entry per distinct reference, however many modules\n * showed it.\n */\nexport interface UnresolvedShapeReference {\n shape: string;\n property: string;\n valueShape: string;\n modules: string[];\n /**\n * What the target package's entry does for it: `registered` — loading the\n * entry registers it, so the referencing module just does not import it;\n * `missing` — not even the entry registers it, so the name or package is\n * wrong; `not-a-dependency` — the IRI's package is neither this package nor\n * one of its dependencies; `unknown` — the entry could not be loaded.\n */\n target: 'registered' | 'missing' | 'not-a-dependency' | 'unknown';\n /** The package the IRI's slug maps to, when one does. */\n targetPackage?: string;\n}\n\nexport interface ShapeReferenceReport {\n modules: string[];\n loadErrors: ShapeModuleLoadError[];\n unresolved: UnresolvedShapeReference[];\n /** Unresolved references that match {@link KNOWN_UNRESOLVED}. */\n known: UnresolvedShapeReference[];\n /** Set when the registry could not be inspected, so nothing was checked. */\n skipped?: string;\n}\n\n/**\n * References known to be unresolved, reported as warnings rather than failures.\n *\n * This is deliberately a list in the CLI rather than an opt-out a package can\n * write for itself: every entry is a shipped bug with a tracked fix, not an\n * accepted design. No package was found with a legitimate reason to leave a\n * reference unresolved; add an opt-out mechanism when one turns up.\n *\n * - `@_linked/core`: `PropertyShape.in` names `List` by `[package, name]`\n * because `List`'s module depends on the SHACL shapes. Only core's entry\n * loads `List`, so a process that deep-imports core without its entry cannot\n * traverse `sh:in`. Tracked as core's backlog-045; core builds with `linked\n * build-all`, which must not fail on it meanwhile. Remove this entry once\n * core registers `List` wherever `PropertyShape` is registered.\n */\nexport const KNOWN_UNRESOLVED: {\n package: string;\n shape: string;\n property: string;\n valueShape: string;\n}[] = [\n {\n package: '@_linked/core',\n shape: '/shape/core/PropertyShape',\n property: 'in',\n valueShape: '/shape/core/List',\n },\n];\n\n/** arch-02: the `{slug}` in `{baseUri}shape/{slug}/{Name}`. Mirrors core's `packageNameToSlug`. */\nexport const packageNameToSlug = (packageName: string): string =>\n packageName\n .replace(/^@[^/]+\\//, '')\n .replace(/[^a-zA-Z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .toLowerCase();\n\n/** The slug in a node-shape IRI, or undefined when it is not shaped like one. */\nconst slugOf = (iri: string): string | undefined =>\n iri.match(/\\/shape\\/([^/]+)\\/[^/]+$/)?.[1];\n\n/**\n * A loader hook for the child: asset imports (`import styles from\n * './X.module.css'`) evaluate to a stub. Node cannot load them and a consumer's\n * bundler always can, so without this a shape module whose file also holds a\n * component would look broken when it is not. A CSS-module stub maps every\n * class name to itself.\n */\nconst ASSET_HOOK = `\nconst ASSET = /\\\\.(css|scss|sass|less|styl|svg|png|jpe?g|gif|webp|avif|ico|woff2?|ttf|otf|eot)$/i;\nexport async function load(url, context, next) {\n if (url.startsWith('file:') && ASSET.test(new URL(url).pathname)) {\n return {format: 'module', shortCircuit: true,\n source: 'export default new Proxy({}, {get: (_, k) => typeof k === \"string\" ? k : undefined});'};\n }\n return next(url, context);\n}\n`;\n\n/**\n * The script each child runs. Plain JS, passed with `-e`, so it runs the same\n * from `src` under a test runner as from the published `lib`.\n *\n * It reads the registry from `globalThis.__linkedShapeRegistry` rather than\n * importing `@_linked/core`: the module under test decides which copy of core\n * it loads, and the registry is shared by every copy.\n */\nconst PROBE = `\nimport {register} from 'node:module';\nregister('data:text/javascript,' + encodeURIComponent(${JSON.stringify(ASSET_HOOK)}));\nconst MARK = '__LINKED_SHAPE_REFERENCES__';\nconst out = {error: null, unresolved: [], registry: true};\nconst reg = () => globalThis.__linkedShapeRegistry;\nconst ownSlug = process.env.LINKED_PROBE_SLUG;\nconst report = () => {\n process.stdout.write('\\\\n' + MARK + JSON.stringify(out) + '\\\\n', () => process.exit(0));\n};\ntry {\n await import(process.env.LINKED_PROBE_MODULE);\n const r = reg();\n if (!r || !r.nodeShapeRegistry) {\n out.registry = false;\n } else {\n for (const [id, ns] of r.nodeShapeRegistry) {\n if (!id.includes('/shape/' + ownSlug + '/')) continue;\n for (const ps of ns.propertyShapes || []) {\n const v = ps.valueShape && ps.valueShape.id;\n if (v && !r.nodeShapeRegistry.has(v)) {\n out.unresolved.push({shape: id, property: ps.label, valueShape: v});\n }\n }\n }\n // For each unresolved target, load its package's entry and look again: that\n // tells a missing import apart from a name that can never resolve.\n const entries = JSON.parse(process.env.LINKED_PROBE_ENTRIES || '{}');\n const tried = {};\n for (const u of out.unresolved) {\n const slug = (u.valueShape.match(/\\\\/shape\\\\/([^/]+)\\\\/[^/]+$/) || [])[1];\n const entry = entries[slug];\n if (!entry) { u.target = 'not-a-dependency'; continue; }\n u.targetPackage = entry.name;\n if (!(slug in tried)) {\n try { await import(entry.specifier); tried[slug] = true; }\n catch (e) { tried[slug] = false; }\n }\n u.target = !tried[slug] ? 'unknown'\n : reg().nodeShapeRegistry.has(u.valueShape) ? 'registered' : 'missing';\n }\n }\n} catch (e) {\n out.error = e && e.stack ? e.stack.split('\\\\n').slice(0, 4).join('\\\\n') : String(e);\n}\nreport();\n`;\n\ninterface ProbeResult {\n error: string | null;\n registry: boolean;\n unresolved: {\n shape: string;\n property: string;\n valueShape: string;\n target: UnresolvedShapeReference['target'];\n targetPackage?: string;\n }[];\n}\n\nconst MARK = '__LINKED_SHAPE_REFERENCES__';\n\nconst runProbe = (\n modulePath: string,\n packagePath: string,\n env: Record<string, string>,\n timeoutMs: number,\n): Promise<ProbeResult> =>\n new Promise((resolve) => {\n execFile(\n process.execPath,\n ['--input-type=module', '-e', PROBE],\n {\n cwd: packagePath,\n env: {\n ...process.env,\n ...env,\n LINKED_PROBE_MODULE: 'file://' + modulePath,\n },\n timeout: timeoutMs,\n maxBuffer: 64 * 1024 * 1024,\n },\n (err, stdout, stderr) => {\n const line = String(stdout)\n .split('\\n')\n .reverse()\n .find((l) => l.startsWith(MARK));\n if (line) {\n resolve(JSON.parse(line.slice(MARK.length)));\n return;\n }\n const why =\n err && (err as any).killed\n ? `did not finish loading within ${timeoutMs}ms`\n : String(stderr).trim().split('\\n').slice(-4).join('\\n') ||\n String(err || 'exited without reporting');\n resolve({error: why, registry: true, unresolved: []});\n },\n );\n });\n\n/** Every compiled module that declares a shape: all of `shapes/`, plus decorated classes elsewhere. */\nexport const findShapeModules = (libEsm: string): string[] => {\n const found: string[] = [];\n const walk = (dir: string) => {\n for (const entry of fs.readdirSync(dir, {withFileTypes: true})) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n walk(full);\n } else if (\n entry.name.endsWith('.js') &&\n !/\\.(test|spec|class)\\.js$/.test(entry.name)\n ) {\n const rel = path.relative(libEsm, full);\n if (\n rel.split(path.sep)[0] === 'shapes' ||\n declaresShape(fs.readFileSync(full, 'utf8'))\n ) {\n found.push(full);\n }\n }\n }\n };\n if (fs.existsSync(libEsm)) walk(libEsm);\n return found.sort();\n};\n\n/** The name the package registers its shapes under: `linkedPackage('<name>')` in `package.js`. */\nconst runtimePackageName = (libEsm: string, pkgJson: any): string => {\n const pkgModule = path.join(libEsm, 'package.js');\n if (fs.existsSync(pkgModule)) {\n const m = fs\n .readFileSync(pkgModule, 'utf8')\n .match(/linkedPackage\\(\\s*['\"]([^'\"]+)['\"]/);\n if (m) return m[1];\n }\n return pkgJson.name;\n};\n\nconst DEPENDENCY_FIELDS = [\n 'dependencies',\n 'peerDependencies',\n 'optionalDependencies',\n];\n\n/**\n * Load each shape module of the package at `packagePath` in isolation and\n * collect load errors and unresolved property value shapes.\n */\nexport const inspectShapeReferences = async (\n packagePath: string,\n {\n concurrency = Math.min(8, Math.max(1, os.cpus().length - 1)),\n timeoutMs = 60000,\n } = {},\n): Promise<ShapeReferenceReport> => {\n const libEsm = path.join(packagePath, 'lib', 'esm');\n const pkgJson = JSON.parse(\n fs.readFileSync(path.join(packagePath, 'package.json'), 'utf8'),\n );\n const modules = findShapeModules(libEsm);\n const report: ShapeReferenceReport = {\n modules: modules.map((m) => path.relative(libEsm, m)),\n loadErrors: [],\n unresolved: [],\n known: [],\n };\n if (modules.length === 0) return report;\n\n const ownName = runtimePackageName(libEsm, pkgJson);\n // The entry each slug's package is loaded through for the second look. This\n // package's own entry is loaded by path: a package cannot always import\n // itself by name.\n const entries: Record<string, {name: string; specifier: string}> = {};\n for (const field of DEPENDENCY_FIELDS) {\n for (const dep of Object.keys(pkgJson[field] || {})) {\n entries[packageNameToSlug(dep)] = {name: dep, specifier: dep};\n }\n }\n const ownEntry = path.join(\n packagePath,\n pkgJson.module || pkgJson.main || 'lib/esm/index.js',\n );\n for (const name of new Set([ownName, pkgJson.name])) {\n entries[packageNameToSlug(name)] = {\n name,\n specifier: fs.existsSync(ownEntry) ? 'file://' + ownEntry : name,\n };\n }\n const env = {\n LINKED_PROBE_SLUG: packageNameToSlug(ownName),\n LINKED_PROBE_ENTRIES: JSON.stringify(entries),\n };\n\n const results: ProbeResult[] = new Array(modules.length);\n let next = 0;\n await Promise.all(\n Array.from({length: Math.min(concurrency, modules.length)}, async () => {\n while (next < modules.length) {\n const i = next++;\n results[i] = await runProbe(modules[i], packagePath, env, timeoutMs);\n }\n }),\n );\n\n // No registry on `globalThis` after loading a module that declares a shape\n // means a core older than 2.22.3, whose registry is module-scoped. A module\n // under `shapes/` that declares none (a store, a helper) registers nothing.\n const stale = results.findIndex(\n (r, i) =>\n !r.error &&\n !r.registry &&\n declaresShape(fs.readFileSync(modules[i], 'utf8')),\n );\n if (stale !== -1) {\n report.skipped =\n `no shape registry on globalThis after loading ${report.modules[stale]}: the ` +\n '@_linked/core it loads is older than 2.22.3, whose registry cannot be inspected from outside';\n return report;\n }\n\n const byReference = new Map<string, UnresolvedShapeReference>();\n results.forEach((r, i) => {\n const module = report.modules[i];\n if (r.error) {\n report.loadErrors.push({module, error: r.error});\n return;\n }\n for (const u of r.unresolved) {\n const key = `${u.shape}\\u0000${u.property}\\u0000${u.valueShape}`;\n const existing = byReference.get(key);\n if (existing) existing.modules.push(module);\n else byReference.set(key, {...u, modules: [module]});\n }\n });\n for (const ref of byReference.values()) {\n const isKnown = KNOWN_UNRESOLVED.some(\n (k) =>\n k.package === ownName &&\n ref.shape.endsWith(k.shape) &&\n ref.property === k.property &&\n ref.valueShape.endsWith(k.valueShape),\n );\n (isKnown ? report.known : report.unresolved).push(ref);\n }\n return report;\n};\n\nconst shortIri = (iri: string) => iri.replace(/^.*\\/shape\\//, '');\n\nconst modulesList = (modules: string[]) =>\n modules.length <= 3\n ? modules.join(', ')\n : `${modules.slice(0, 3).join(', ')} and ${modules.length - 3} more`;\n\nconst describeReference = (ref: UnresolvedShapeReference): string => {\n const label = `${shortIri(ref.shape)}.${ref.property} -> ${ref.valueShape}`;\n const fix =\n ref.target === 'registered'\n ? `${ref.targetPackage}'s entry registers it, so the module that declares the property must import the module that declares ${shortIri(ref.valueShape)}`\n : ref.target === 'missing'\n ? `not registered even by ${ref.targetPackage}'s entry: the shape name is wrong or ${ref.targetPackage} does not define it`\n : ref.target === 'not-a-dependency'\n ? `'${slugOf(ref.valueShape)}' is neither this package nor one of its dependencies (an old package name?)`\n : `${ref.targetPackage}'s entry could not be loaded to tell why`;\n return ` ${label}\\n unresolved after loading ${modulesList(ref.modules)}\\n ${fix}`;\n};\n\n/**\n * Build step. Load errors and unresolved references fail the build: each is a\n * bug the package would ship, and it only surfaces in a consumer's bundle. The\n * references in {@link KNOWN_UNRESOLVED} warn instead.\n */\nexport const checkShapeReferences = async (\n packagePath: string,\n options?: Parameters<typeof inspectShapeReferences>[1],\n): Promise<true | string | {error: string}> => {\n const report = await inspectShapeReferences(packagePath, options);\n if (report.skipped) return `skipped: ${report.skipped}`;\n const problems: string[] = [];\n if (report.loadErrors.length > 0) {\n problems.push(\n `${report.loadErrors.length} shape module(s) throw when loaded on their own:\\n` +\n report.loadErrors\n .map((e) => ` ${e.module}: ${e.error.split('\\n').join('\\n ')}`)\n .join('\\n'),\n );\n }\n if (report.unresolved.length > 0) {\n problems.push(\n `${report.unresolved.length} property value shape(s) are not registered when the module that ` +\n `declares the property is loaded on its own, so a query traversing them throws ` +\n `\"Shape class not found\":\\n` +\n report.unresolved.map(describeReference).join('\\n'),\n );\n }\n if (problems.length > 0) return {error: problems.join('\\n')};\n if (report.known.length > 0) {\n return (\n `${report.known.length} known unresolved reference(s), tracked for a fix:\\n` +\n report.known.map(describeReference).join('\\n')\n );\n }\n return true;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"shapeReferences.js","sourceRoot":"","sources":["../../../src/utils/shapeReferences.ts"],"names":[],"mappings":"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","sourcesContent":["import {execFile} from 'child_process';\nimport fs from 'fs';\nimport os from 'os';\nimport path from 'path';\nimport {declaresShape} from './shapeNames.js';\n\n/**\n * Checking shape references: does loading a compiled shape module, on its own,\n * register every shape its properties point at?\n *\n * A property can name its value shape by `[package, name]` instead of by class\n * (`shape: ['@_linked/schema', 'ImageObject']`), usually because importing the\n * class would close an import cycle. That names the shape without loading it.\n * A shape registers only when its module is evaluated, and consumers deep-import\n * single shape modules (`@_linked/schema/shapes/Thing`), so nothing guarantees\n * the named shape is registered when a query traverses the property. The query\n * then throws `Shape class not found for …/ImageObject` — in a production bundle,\n * far from the cause. A reference to a package under an old name\n * (`['lincd-sioc', …]`) can never resolve at all.\n *\n * So each module is loaded the way a consumer's fresh process would load it: in\n * a child `node` of its own, with nothing else imported first. Separate processes\n * rather than one process re-importing: ESM has no module-cache eviction, and the\n * shape registry lives on `globalThis`, so a second module in the same process\n * would see every shape the first one registered.\n */\n\n/** One module that could not be evaluated. */\nexport interface ShapeModuleLoadError {\n module: string;\n error: string;\n}\n\n/**\n * A property whose value shape was not registered after loading `modules`\n * (each on its own). One entry per distinct reference, however many modules\n * showed it.\n */\nexport interface UnresolvedShapeReference {\n shape: string;\n property: string;\n valueShape: string;\n modules: string[];\n /**\n * What the target package's entry does for it: `registered` — loading the\n * entry registers it, so the referencing module just does not import it;\n * `missing` — not even the entry registers it, so the name or package is\n * wrong; `not-a-dependency` — the IRI's package is neither this package nor\n * one of its dependencies; `unknown` — the entry could not be loaded.\n */\n target: 'registered' | 'missing' | 'not-a-dependency' | 'unknown';\n /** The package the IRI's slug maps to, when one does. */\n targetPackage?: string;\n}\n\nexport interface ShapeReferenceReport {\n modules: string[];\n loadErrors: ShapeModuleLoadError[];\n unresolved: UnresolvedShapeReference[];\n /** Unresolved references that match {@link KNOWN_UNRESOLVED}. */\n known: UnresolvedShapeReference[];\n /**\n * The package's own shapes (by IRI) registered after loading each module on\n * its own, keyed like {@link modules}. Read before the probe loads any entry\n * for its second look, so it is exactly what that one module registers.\n * Modules that threw are absent.\n */\n registered: Record<string, string[]>;\n /** Set when the registry could not be inspected, so nothing was checked. */\n skipped?: string;\n}\n\n/**\n * References known to be unresolved, reported as warnings rather than failures.\n *\n * This is deliberately a list in the CLI rather than an opt-out a package can\n * write for itself: every entry is a shipped bug with a tracked fix, not an\n * accepted design. No package was found with a legitimate reason to leave a\n * reference unresolved; add an opt-out mechanism when one turns up.\n *\n * Empty: `@_linked/core`'s `PropertyShape.in -> List`, the one entry this held,\n * is fixed in core (List is registered wherever PropertyShape is).\n */\nexport const KNOWN_UNRESOLVED: {\n package: string;\n shape: string;\n property: string;\n valueShape: string;\n}[] = [];\n\n/** arch-02: the `{slug}` in `{baseUri}shape/{slug}/{Name}`. Mirrors core's `packageNameToSlug`. */\nexport const packageNameToSlug = (packageName: string): string =>\n packageName\n .replace(/^@[^/]+\\//, '')\n .replace(/[^a-zA-Z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .toLowerCase();\n\n/** The slug in a node-shape IRI, or undefined when it is not shaped like one. */\nconst slugOf = (iri: string): string | undefined =>\n iri.match(/\\/shape\\/([^/]+)\\/[^/]+$/)?.[1];\n\n/**\n * A loader hook for the child: asset imports (`import styles from\n * './X.module.css'`) evaluate to a stub. Node cannot load them and a consumer's\n * bundler always can, so without this a shape module whose file also holds a\n * component would look broken when it is not. A CSS-module stub maps every\n * class name to itself.\n */\nconst ASSET_HOOK = `\nconst ASSET = /\\\\.(css|scss|sass|less|styl|svg|png|jpe?g|gif|webp|avif|ico|woff2?|ttf|otf|eot)$/i;\nexport async function load(url, context, next) {\n if (url.startsWith('file:') && ASSET.test(new URL(url).pathname)) {\n return {format: 'module', shortCircuit: true,\n source: 'export default new Proxy({}, {get: (_, k) => typeof k === \"string\" ? k : undefined});'};\n }\n return next(url, context);\n}\n`;\n\n/**\n * The script each child runs. Plain JS, passed with `-e`, so it runs the same\n * from `src` under a test runner as from the published `lib`.\n *\n * It reads the registry from `globalThis.__linkedShapeRegistry` rather than\n * importing `@_linked/core`: the module under test decides which copy of core\n * it loads, and the registry is shared by every copy.\n */\nconst PROBE = `\nimport {register} from 'node:module';\nregister('data:text/javascript,' + encodeURIComponent(${JSON.stringify(ASSET_HOOK)}));\nconst MARK = '__LINKED_SHAPE_REFERENCES__';\nconst out = {error: null, unresolved: [], registry: true, registered: []};\nconst reg = () => globalThis.__linkedShapeRegistry;\nconst ownSlug = process.env.LINKED_PROBE_SLUG;\nconst report = () => {\n process.stdout.write('\\\\n' + MARK + JSON.stringify(out) + '\\\\n', () => process.exit(0));\n};\ntry {\n await import(process.env.LINKED_PROBE_MODULE);\n const r = reg();\n if (!r || !r.nodeShapeRegistry) {\n out.registry = false;\n } else {\n // Before the second look below: that loads whole entries and would add theirs.\n for (const id of r.nodeShapeRegistry.keys()) {\n if (id.includes('/shape/' + ownSlug + '/')) out.registered.push(id);\n }\n for (const [id, ns] of r.nodeShapeRegistry) {\n if (!id.includes('/shape/' + ownSlug + '/')) continue;\n for (const ps of ns.propertyShapes || []) {\n const v = ps.valueShape && ps.valueShape.id;\n if (v && !r.nodeShapeRegistry.has(v)) {\n out.unresolved.push({shape: id, property: ps.label, valueShape: v});\n }\n }\n }\n // For each unresolved target, load its package's entry and look again: that\n // tells a missing import apart from a name that can never resolve.\n const entries = JSON.parse(process.env.LINKED_PROBE_ENTRIES || '{}');\n const tried = {};\n for (const u of out.unresolved) {\n const slug = (u.valueShape.match(/\\\\/shape\\\\/([^/]+)\\\\/[^/]+$/) || [])[1];\n const entry = entries[slug];\n if (!entry) { u.target = 'not-a-dependency'; continue; }\n u.targetPackage = entry.name;\n if (!(slug in tried)) {\n try { await import(entry.specifier); tried[slug] = true; }\n catch (e) { tried[slug] = false; }\n }\n u.target = !tried[slug] ? 'unknown'\n : reg().nodeShapeRegistry.has(u.valueShape) ? 'registered' : 'missing';\n }\n }\n} catch (e) {\n out.error = e && e.stack ? e.stack.split('\\\\n').slice(0, 4).join('\\\\n') : String(e);\n}\nreport();\n`;\n\ninterface ProbeResult {\n error: string | null;\n registry: boolean;\n registered: string[];\n unresolved: {\n shape: string;\n property: string;\n valueShape: string;\n target: UnresolvedShapeReference['target'];\n targetPackage?: string;\n }[];\n}\n\nconst MARK = '__LINKED_SHAPE_REFERENCES__';\n\nconst runProbe = (\n modulePath: string,\n packagePath: string,\n env: Record<string, string>,\n timeoutMs: number,\n): Promise<ProbeResult> =>\n new Promise((resolve) => {\n execFile(\n process.execPath,\n ['--input-type=module', '-e', PROBE],\n {\n cwd: packagePath,\n env: {\n ...process.env,\n ...env,\n LINKED_PROBE_MODULE: 'file://' + modulePath,\n },\n timeout: timeoutMs,\n maxBuffer: 64 * 1024 * 1024,\n },\n (err, stdout, stderr) => {\n const line = String(stdout)\n .split('\\n')\n .reverse()\n .find((l) => l.startsWith(MARK));\n if (line) {\n resolve(JSON.parse(line.slice(MARK.length)));\n return;\n }\n const why =\n err && (err as any).killed\n ? `did not finish loading within ${timeoutMs}ms`\n : String(stderr).trim().split('\\n').slice(-4).join('\\n') ||\n String(err || 'exited without reporting');\n resolve({error: why, registry: true, registered: [], unresolved: []});\n },\n );\n });\n\n/** Every compiled module that declares a shape: all of `shapes/`, plus decorated classes elsewhere. */\nexport const findShapeModules = (libEsm: string): string[] => {\n const found: string[] = [];\n const walk = (dir: string) => {\n for (const entry of fs.readdirSync(dir, {withFileTypes: true})) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n walk(full);\n } else if (\n entry.name.endsWith('.js') &&\n !/\\.(test|spec|class)\\.js$/.test(entry.name)\n ) {\n const rel = path.relative(libEsm, full);\n if (\n rel.split(path.sep)[0] === 'shapes' ||\n declaresShape(fs.readFileSync(full, 'utf8'))\n ) {\n found.push(full);\n }\n }\n }\n };\n if (fs.existsSync(libEsm)) walk(libEsm);\n return found.sort();\n};\n\n/** The name the package registers its shapes under: `linkedPackage('<name>')` in `package.js`. */\nconst runtimePackageName = (libEsm: string, pkgJson: any): string => {\n const pkgModule = path.join(libEsm, 'package.js');\n if (fs.existsSync(pkgModule)) {\n const m = fs\n .readFileSync(pkgModule, 'utf8')\n .match(/linkedPackage\\(\\s*['\"]([^'\"]+)['\"]/);\n if (m) return m[1];\n }\n return pkgJson.name;\n};\n\nconst DEPENDENCY_FIELDS = [\n 'dependencies',\n 'peerDependencies',\n 'optionalDependencies',\n];\n\n/**\n * Load each shape module of the package at `packagePath` in isolation and\n * collect load errors and unresolved property value shapes.\n */\nexport const inspectShapeReferences = async (\n packagePath: string,\n {\n concurrency = Math.min(8, Math.max(1, os.cpus().length - 1)),\n timeoutMs = 60000,\n } = {},\n): Promise<ShapeReferenceReport> => {\n const libEsm = path.join(packagePath, 'lib', 'esm');\n const pkgJson = JSON.parse(\n fs.readFileSync(path.join(packagePath, 'package.json'), 'utf8'),\n );\n const modules = findShapeModules(libEsm);\n const report: ShapeReferenceReport = {\n modules: modules.map((m) => path.relative(libEsm, m)),\n loadErrors: [],\n unresolved: [],\n known: [],\n registered: {},\n };\n if (modules.length === 0) return report;\n\n const ownName = runtimePackageName(libEsm, pkgJson);\n // The entry each slug's package is loaded through for the second look. This\n // package's own entry is loaded by path: a package cannot always import\n // itself by name.\n const entries: Record<string, {name: string; specifier: string}> = {};\n for (const field of DEPENDENCY_FIELDS) {\n for (const dep of Object.keys(pkgJson[field] || {})) {\n entries[packageNameToSlug(dep)] = {name: dep, specifier: dep};\n }\n }\n const ownEntry = path.join(\n packagePath,\n pkgJson.module || pkgJson.main || 'lib/esm/index.js',\n );\n for (const name of new Set([ownName, pkgJson.name])) {\n entries[packageNameToSlug(name)] = {\n name,\n specifier: fs.existsSync(ownEntry) ? 'file://' + ownEntry : name,\n };\n }\n const env = {\n LINKED_PROBE_SLUG: packageNameToSlug(ownName),\n LINKED_PROBE_ENTRIES: JSON.stringify(entries),\n };\n\n const results: ProbeResult[] = new Array(modules.length);\n let next = 0;\n await Promise.all(\n Array.from({length: Math.min(concurrency, modules.length)}, async () => {\n while (next < modules.length) {\n const i = next++;\n results[i] = await runProbe(modules[i], packagePath, env, timeoutMs);\n }\n }),\n );\n\n // No registry on `globalThis` after loading a module that declares a shape\n // means a core older than 2.22.3, whose registry is module-scoped. A module\n // under `shapes/` that declares none (a store, a helper) registers nothing.\n const stale = results.findIndex(\n (r, i) =>\n !r.error &&\n !r.registry &&\n declaresShape(fs.readFileSync(modules[i], 'utf8')),\n );\n if (stale !== -1) {\n report.skipped =\n `no shape registry on globalThis after loading ${report.modules[stale]}: the ` +\n '@_linked/core it loads is older than 2.22.3, whose registry cannot be inspected from outside';\n return report;\n }\n\n const byReference = new Map<string, UnresolvedShapeReference>();\n results.forEach((r, i) => {\n const module = report.modules[i];\n if (r.error) {\n report.loadErrors.push({module, error: r.error});\n return;\n }\n report.registered[module] = r.registered;\n for (const u of r.unresolved) {\n const key = `${u.shape}\\u0000${u.property}\\u0000${u.valueShape}`;\n const existing = byReference.get(key);\n if (existing) existing.modules.push(module);\n else byReference.set(key, {...u, modules: [module]});\n }\n });\n for (const ref of byReference.values()) {\n const isKnown = KNOWN_UNRESOLVED.some(\n (k) =>\n k.package === ownName &&\n ref.shape.endsWith(k.shape) &&\n ref.property === k.property &&\n ref.valueShape.endsWith(k.valueShape),\n );\n (isKnown ? report.known : report.unresolved).push(ref);\n }\n return report;\n};\n\nconst shortIri = (iri: string) => iri.replace(/^.*\\/shape\\//, '');\n\nconst modulesList = (modules: string[]) =>\n modules.length <= 3\n ? modules.join(', ')\n : `${modules.slice(0, 3).join(', ')} and ${modules.length - 3} more`;\n\nconst describeReference = (ref: UnresolvedShapeReference): string => {\n const label = `${shortIri(ref.shape)}.${ref.property} -> ${ref.valueShape}`;\n const fix =\n ref.target === 'registered'\n ? `${ref.targetPackage}'s entry registers it, so the module that declares the property must import the module that declares ${shortIri(ref.valueShape)}`\n : ref.target === 'missing'\n ? `not registered even by ${ref.targetPackage}'s entry: the shape name is wrong or ${ref.targetPackage} does not define it`\n : ref.target === 'not-a-dependency'\n ? `'${slugOf(ref.valueShape)}' is neither this package nor one of its dependencies (an old package name?)`\n : `${ref.targetPackage}'s entry could not be loaded to tell why`;\n return ` ${label}\\n unresolved after loading ${modulesList(ref.modules)}\\n ${fix}`;\n};\n\n/**\n * Build step. Load errors and unresolved references fail the build: each is a\n * bug the package would ship, and it only surfaces in a consumer's bundle. The\n * references in {@link KNOWN_UNRESOLVED} warn instead.\n */\nexport const checkShapeReferences = async (\n packagePath: string,\n options?: Parameters<typeof inspectShapeReferences>[1],\n inspection?: Promise<ShapeReferenceReport>,\n): Promise<true | string | {error: string}> => {\n const report = await (inspection ?? inspectShapeReferences(packagePath, options));\n if (report.skipped) return `skipped: ${report.skipped}`;\n const problems: string[] = [];\n if (report.loadErrors.length > 0) {\n problems.push(\n `${report.loadErrors.length} shape module(s) throw when loaded on their own:\\n` +\n report.loadErrors\n .map((e) => ` ${e.module}: ${e.error.split('\\n').join('\\n ')}`)\n .join('\\n'),\n );\n }\n if (report.unresolved.length > 0) {\n problems.push(\n `${report.unresolved.length} property value shape(s) are not registered when the module that ` +\n `declares the property is loaded on its own, so a query traversing them throws ` +\n `\"Shape class not found\":\\n` +\n report.unresolved.map(describeReference).join('\\n'),\n );\n }\n if (problems.length > 0) return {error: problems.join('\\n')};\n if (report.known.length > 0) {\n return (\n `${report.known.length} known unresolved reference(s), tracked for a fix:\\n` +\n report.known.map(describeReference).join('\\n')\n );\n }\n return true;\n};\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { inspectShapeReferences, type ShapeReferenceReport } from './shapeReferences.js';
|
|
2
|
+
/**
|
|
3
|
+
* Build step: does loading `lib/esm/shapes/index.js` alone, in a fresh
|
|
4
|
+
* process, register every one of this package's shapes that loading its
|
|
5
|
+
* shape modules one by one registers?
|
|
6
|
+
*
|
|
7
|
+
* Fails when the package has shapes but no shapes/index, when the index throws
|
|
8
|
+
* on load, or when it misses a shape. A package without shapes passes.
|
|
9
|
+
*/
|
|
10
|
+
export declare const checkShapesIndex: (packagePath: string, options?: Parameters<typeof inspectShapeReferences>[1], inspection?: Promise<ShapeReferenceReport>) => Promise<true | string | {
|
|
11
|
+
error: string;
|
|
12
|
+
}>;
|
|
13
|
+
/**
|
|
14
|
+
* Build step: `package.json` must not declare any `lib/esm/shapes` module
|
|
15
|
+
* side-effect-free. A pure match of the field against the emitted files; no
|
|
16
|
+
* bundling.
|
|
17
|
+
*/
|
|
18
|
+
export declare const checkShapesSideEffects: (packagePath: string) => true | {
|
|
19
|
+
error: string;
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=shapesIndex.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shapesIndex.d.ts","sourceRoot":"","sources":["../../../src/utils/shapesIndex.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,sBAAsB,EACtB,KAAK,oBAAoB,EAC1B,MAAM,sBAAsB,CAAC;AAoE9B;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,GAC3B,aAAa,MAAM,EACnB,UAAU,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC,CAAC,CAAC,EACtD,aAAa,OAAO,CAAC,oBAAoB,CAAC,KACzC,OAAO,CAAC,IAAI,GAAG,MAAM,GAAG;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,CAkEzC,CAAC;AA6BF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,GACjC,aAAa,MAAM,KAClB,IAAI,GAAG;IAAC,KAAK,EAAE,MAAM,CAAA;CA+CvB,CAAC"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import fs from 'fs';
|
|
11
|
+
import path from 'path';
|
|
12
|
+
import { minimatch } from 'minimatch';
|
|
13
|
+
import { inspectShapeReferences, } from './shapeReferences.js';
|
|
14
|
+
/**
|
|
15
|
+
* The shape-registration standard, checked against a package's build output.
|
|
16
|
+
*
|
|
17
|
+
* Every package has `src/shapes/index.ts`: side-effect-only imports of every
|
|
18
|
+
* shape module, so an app can register the whole set with one import
|
|
19
|
+
* (`import '@_linked/<pkg>/shapes/index'`). A shape registers only when its
|
|
20
|
+
* module is evaluated, so a shape the index forgets is a shape an app that
|
|
21
|
+
* trusts the index never has, and a query naming it throws "Shape class not
|
|
22
|
+
* found" in that app's bundle. And a bundler that believes a package's
|
|
23
|
+
* `sideEffects` drops a side-effect-only import outright, so declaring shape
|
|
24
|
+
* modules side-effect-free empties the index in production while dev (which
|
|
25
|
+
* does not tree-shake) keeps working.
|
|
26
|
+
*/
|
|
27
|
+
/** The index, relative to lib/esm, as the per-module inspection keys it. */
|
|
28
|
+
const INDEX = path.join('shapes', 'index.js');
|
|
29
|
+
const shortIri = (iri) => iri.replace(/^.*\/shape\//, '');
|
|
30
|
+
/** `lib/esm/shapes/X.js` → `src/shapes/X.ts`, for messages. */
|
|
31
|
+
const srcPath = (module) => path.join('src', module).replace(/\.js$/, '.ts');
|
|
32
|
+
/** The line shapes/index.ts needs to load `module` (relative to lib/esm). */
|
|
33
|
+
const importLine = (module) => {
|
|
34
|
+
let rel = path
|
|
35
|
+
.relative('shapes', module)
|
|
36
|
+
.split(path.sep)
|
|
37
|
+
.join('/');
|
|
38
|
+
if (!rel.startsWith('.'))
|
|
39
|
+
rel = './' + rel;
|
|
40
|
+
return `import '${rel}';`;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* For each shape, the module the fix should import: the one named after the
|
|
44
|
+
* shape, else the one whose source declares its class, else the module
|
|
45
|
+
* registering the fewest shapes (the most specific).
|
|
46
|
+
*/
|
|
47
|
+
const moduleFor = (shape, registered, libEsm) => {
|
|
48
|
+
var _a, _b;
|
|
49
|
+
const name = shape.replace(/^.*\//, '');
|
|
50
|
+
const declares = (m) => {
|
|
51
|
+
try {
|
|
52
|
+
return new RegExp(`\\b(?:class ${name}|${name} = class)\\b`).test(fs.readFileSync(path.join(libEsm, m), 'utf8'));
|
|
53
|
+
}
|
|
54
|
+
catch (_a) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const candidates = Object.keys(registered)
|
|
59
|
+
.filter((m) => m !== INDEX && registered[m].includes(shape))
|
|
60
|
+
.sort((a, b) => registered[a].length - registered[b].length || a.localeCompare(b));
|
|
61
|
+
return ((_b = (_a = candidates.find((m) => path.basename(m, '.js') === name)) !== null && _a !== void 0 ? _a : candidates.find(declares)) !== null && _b !== void 0 ? _b : candidates[0]);
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Build step: does loading `lib/esm/shapes/index.js` alone, in a fresh
|
|
65
|
+
* process, register every one of this package's shapes that loading its
|
|
66
|
+
* shape modules one by one registers?
|
|
67
|
+
*
|
|
68
|
+
* Fails when the package has shapes but no shapes/index, when the index throws
|
|
69
|
+
* on load, or when it misses a shape. A package without shapes passes.
|
|
70
|
+
*/
|
|
71
|
+
export const checkShapesIndex = (packagePath, options, inspection) => __awaiter(void 0, void 0, void 0, function* () {
|
|
72
|
+
const report = yield (inspection !== null && inspection !== void 0 ? inspection : inspectShapeReferences(packagePath, options));
|
|
73
|
+
if (report.skipped)
|
|
74
|
+
return `skipped: ${report.skipped}`;
|
|
75
|
+
const libEsm = path.join(packagePath, 'lib', 'esm');
|
|
76
|
+
const all = new Set();
|
|
77
|
+
for (const [module, shapes] of Object.entries(report.registered)) {
|
|
78
|
+
if (module !== INDEX)
|
|
79
|
+
shapes.forEach((s) => all.add(s));
|
|
80
|
+
}
|
|
81
|
+
if (all.size === 0)
|
|
82
|
+
return true;
|
|
83
|
+
const hasIndex = report.modules.includes(INDEX);
|
|
84
|
+
const indexError = report.loadErrors.find((e) => e.module === INDEX);
|
|
85
|
+
if (indexError) {
|
|
86
|
+
return {
|
|
87
|
+
error: `lib/esm/shapes/index.js throws when loaded on its own, so an app importing ` +
|
|
88
|
+
`'<package>/shapes/index' registers nothing:\n ${indexError.error.split('\n').join('\n ')}`,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
const covered = new Set(hasIndex ? report.registered[INDEX] : []);
|
|
92
|
+
const missing = [...all].filter((s) => !covered.has(s)).sort();
|
|
93
|
+
if (missing.length === 0)
|
|
94
|
+
return true;
|
|
95
|
+
const lines = [
|
|
96
|
+
...new Set(missing.map((s) => {
|
|
97
|
+
const m = moduleFor(s, report.registered, libEsm);
|
|
98
|
+
return m ? importLine(m) : `// ${shortIri(s)}: no single module registers it`;
|
|
99
|
+
})),
|
|
100
|
+
].sort();
|
|
101
|
+
const listing = missing
|
|
102
|
+
.map((s) => {
|
|
103
|
+
const m = moduleFor(s, report.registered, libEsm);
|
|
104
|
+
return ` ${shortIri(s)}${m ? ` (${srcPath(m)})` : ''}`;
|
|
105
|
+
})
|
|
106
|
+
.join('\n');
|
|
107
|
+
const outside = missing
|
|
108
|
+
.map((s) => moduleFor(s, report.registered, libEsm))
|
|
109
|
+
.filter((m) => m && m.split(path.sep)[0] !== 'shapes');
|
|
110
|
+
const moveNote = outside.length > 0
|
|
111
|
+
? `\nShapes declared outside src/shapes/ belong in src/shapes/; until they move, the index imports their module.`
|
|
112
|
+
: '';
|
|
113
|
+
if (!hasIndex) {
|
|
114
|
+
return {
|
|
115
|
+
error: `This package declares ${all.size} shape(s) but has no src/shapes/index.ts, so an app ` +
|
|
116
|
+
`cannot register them with import '<package>/shapes/index':\n${listing}\n` +
|
|
117
|
+
`Create src/shapes/index.ts holding only side-effect imports (no exports):\n` +
|
|
118
|
+
lines.map((l) => ` ${l}`).join('\n') +
|
|
119
|
+
`\nand import it from src/index.ts: import './shapes/index.js';` +
|
|
120
|
+
moveNote,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
error: `${missing.length} shape(s) are not registered by loading lib/esm/shapes/index.js on its own, ` +
|
|
125
|
+
`so an app that imports '<package>/shapes/index' never has them:\n${listing}\n` +
|
|
126
|
+
`Add to src/shapes/index.ts:\n` +
|
|
127
|
+
lines.map((l) => ` ${l}`).join('\n') +
|
|
128
|
+
moveNote,
|
|
129
|
+
};
|
|
130
|
+
});
|
|
131
|
+
/** Every emitted module under lib/esm/shapes, relative to the package root, `/`-separated. */
|
|
132
|
+
const emittedShapeModules = (packagePath) => {
|
|
133
|
+
const root = path.join(packagePath, 'lib', 'esm', 'shapes');
|
|
134
|
+
const out = [];
|
|
135
|
+
const walk = (dir) => {
|
|
136
|
+
for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
137
|
+
const full = path.join(dir, e.name);
|
|
138
|
+
if (e.isDirectory())
|
|
139
|
+
walk(full);
|
|
140
|
+
else if (e.name.endsWith('.js'))
|
|
141
|
+
out.push(path.relative(packagePath, full).split(path.sep).join('/'));
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
if (fs.existsSync(root))
|
|
145
|
+
walk(root);
|
|
146
|
+
return out.sort();
|
|
147
|
+
};
|
|
148
|
+
/**
|
|
149
|
+
* Whether a `sideEffects` pattern matches a package-relative path, the way
|
|
150
|
+
* webpack and Rollup's node-resolve read it: a leading `./` is dropped and a
|
|
151
|
+
* pattern without a `/` matches the file name anywhere.
|
|
152
|
+
*/
|
|
153
|
+
const sideEffectsMatch = (pattern, file) => {
|
|
154
|
+
let p = pattern.replace(/^\.\//, '');
|
|
155
|
+
if (!p.includes('/'))
|
|
156
|
+
p = '**/' + p;
|
|
157
|
+
return minimatch(file, p, { dot: true });
|
|
158
|
+
};
|
|
159
|
+
/**
|
|
160
|
+
* Build step: `package.json` must not declare any `lib/esm/shapes` module
|
|
161
|
+
* side-effect-free. A pure match of the field against the emitted files; no
|
|
162
|
+
* bundling.
|
|
163
|
+
*/
|
|
164
|
+
export const checkShapesSideEffects = (packagePath) => {
|
|
165
|
+
const pkgJson = JSON.parse(fs.readFileSync(path.join(packagePath, 'package.json'), 'utf8'));
|
|
166
|
+
const sideEffects = pkgJson.sideEffects;
|
|
167
|
+
if (sideEffects === undefined || sideEffects === true)
|
|
168
|
+
return true;
|
|
169
|
+
const files = emittedShapeModules(packagePath);
|
|
170
|
+
if (files.length === 0)
|
|
171
|
+
return true;
|
|
172
|
+
const fix = `Remove the "sideEffects" field, or list the shape modules in it:\n` +
|
|
173
|
+
` "sideEffects": ["lib/esm/shapes/index.js", "lib/esm/shapes/*.js"]` +
|
|
174
|
+
(files.some((f) => f.split('/').length > 4)
|
|
175
|
+
? `\n (with "lib/esm/shapes/**/*.js" for the nested folders)`
|
|
176
|
+
: '');
|
|
177
|
+
const why = `A bundler drops a side-effect-only import of a module it is told is side-effect-free, ` +
|
|
178
|
+
`so shapes/index would register nothing in a production build.`;
|
|
179
|
+
if (sideEffects === false) {
|
|
180
|
+
return {
|
|
181
|
+
error: `package.json declares "sideEffects": false, which marks every shape module side-effect-free. ${why}\n${fix}`,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
if (!Array.isArray(sideEffects) ||
|
|
185
|
+
sideEffects.some((p) => typeof p !== 'string')) {
|
|
186
|
+
return {
|
|
187
|
+
error: `package.json "sideEffects" must be true, false or a list of globs; found ${JSON.stringify(sideEffects)}.\n${fix}`,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
const unmatched = files.filter((f) => !sideEffects.some((p) => sideEffectsMatch(p, f)));
|
|
191
|
+
if (unmatched.length === 0)
|
|
192
|
+
return true;
|
|
193
|
+
return {
|
|
194
|
+
error: `package.json "sideEffects" does not cover ${unmatched.length} shape module(s), so they are declared ` +
|
|
195
|
+
`side-effect-free:\n` +
|
|
196
|
+
unmatched
|
|
197
|
+
.slice(0, 10)
|
|
198
|
+
.map((f) => ` ${f}`)
|
|
199
|
+
.join('\n') +
|
|
200
|
+
(unmatched.length > 10 ? `\n and ${unmatched.length - 10} more` : '') +
|
|
201
|
+
`\n${why}\n${fix}`,
|
|
202
|
+
};
|
|
203
|
+
};
|
|
204
|
+
//# sourceMappingURL=shapesIndex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shapesIndex.js","sourceRoot":"","sources":["../../../src/utils/shapesIndex.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\nimport path from 'path';\nimport {minimatch} from 'minimatch';\nimport {\n inspectShapeReferences,\n type ShapeReferenceReport,\n} from './shapeReferences.js';\n\n/**\n * The shape-registration standard, checked against a package's build output.\n *\n * Every package has `src/shapes/index.ts`: side-effect-only imports of every\n * shape module, so an app can register the whole set with one import\n * (`import '@_linked/<pkg>/shapes/index'`). A shape registers only when its\n * module is evaluated, so a shape the index forgets is a shape an app that\n * trusts the index never has, and a query naming it throws \"Shape class not\n * found\" in that app's bundle. And a bundler that believes a package's\n * `sideEffects` drops a side-effect-only import outright, so declaring shape\n * modules side-effect-free empties the index in production while dev (which\n * does not tree-shake) keeps working.\n */\n\n/** The index, relative to lib/esm, as the per-module inspection keys it. */\nconst INDEX = path.join('shapes', 'index.js');\n\nconst shortIri = (iri: string) => iri.replace(/^.*\\/shape\\//, '');\n\n/** `lib/esm/shapes/X.js` → `src/shapes/X.ts`, for messages. */\nconst srcPath = (module: string) =>\n path.join('src', module).replace(/\\.js$/, '.ts');\n\n/** The line shapes/index.ts needs to load `module` (relative to lib/esm). */\nconst importLine = (module: string) => {\n let rel = path\n .relative('shapes', module)\n .split(path.sep)\n .join('/');\n if (!rel.startsWith('.')) rel = './' + rel;\n return `import '${rel}';`;\n};\n\n/**\n * For each shape, the module the fix should import: the one named after the\n * shape, else the one whose source declares its class, else the module\n * registering the fewest shapes (the most specific).\n */\nconst moduleFor = (\n shape: string,\n registered: Record<string, string[]>,\n libEsm: string,\n): string | undefined => {\n const name = shape.replace(/^.*\\//, '');\n const declares = (m: string) => {\n try {\n return new RegExp(`\\\\b(?:class ${name}|${name} = class)\\\\b`).test(\n fs.readFileSync(path.join(libEsm, m), 'utf8'),\n );\n } catch {\n return false;\n }\n };\n const candidates = Object.keys(registered)\n .filter((m) => m !== INDEX && registered[m].includes(shape))\n .sort(\n (a, b) =>\n registered[a].length - registered[b].length || a.localeCompare(b),\n );\n return (\n candidates.find((m) => path.basename(m, '.js') === name) ??\n candidates.find(declares) ??\n candidates[0]\n );\n};\n\n/**\n * Build step: does loading `lib/esm/shapes/index.js` alone, in a fresh\n * process, register every one of this package's shapes that loading its\n * shape modules one by one registers?\n *\n * Fails when the package has shapes but no shapes/index, when the index throws\n * on load, or when it misses a shape. A package without shapes passes.\n */\nexport const checkShapesIndex = async (\n packagePath: string,\n options?: Parameters<typeof inspectShapeReferences>[1],\n inspection?: Promise<ShapeReferenceReport>,\n): Promise<true | string | {error: string}> => {\n const report = await (inspection ??\n inspectShapeReferences(packagePath, options));\n if (report.skipped) return `skipped: ${report.skipped}`;\n\n const libEsm = path.join(packagePath, 'lib', 'esm');\n const all = new Set<string>();\n for (const [module, shapes] of Object.entries(report.registered)) {\n if (module !== INDEX) shapes.forEach((s) => all.add(s));\n }\n if (all.size === 0) return true;\n\n const hasIndex = report.modules.includes(INDEX);\n const indexError = report.loadErrors.find((e) => e.module === INDEX);\n if (indexError) {\n return {\n error:\n `lib/esm/shapes/index.js throws when loaded on its own, so an app importing ` +\n `'<package>/shapes/index' registers nothing:\\n ${indexError.error.split('\\n').join('\\n ')}`,\n };\n }\n const covered = new Set(hasIndex ? report.registered[INDEX] : []);\n const missing = [...all].filter((s) => !covered.has(s)).sort();\n if (missing.length === 0) return true;\n\n const lines = [\n ...new Set(\n missing.map((s) => {\n const m = moduleFor(s, report.registered, libEsm);\n return m ? importLine(m) : `// ${shortIri(s)}: no single module registers it`;\n }),\n ),\n ].sort();\n const listing = missing\n .map((s) => {\n const m = moduleFor(s, report.registered, libEsm);\n return ` ${shortIri(s)}${m ? ` (${srcPath(m)})` : ''}`;\n })\n .join('\\n');\n const outside = missing\n .map((s) => moduleFor(s, report.registered, libEsm))\n .filter((m) => m && m.split(path.sep)[0] !== 'shapes');\n const moveNote =\n outside.length > 0\n ? `\\nShapes declared outside src/shapes/ belong in src/shapes/; until they move, the index imports their module.`\n : '';\n\n if (!hasIndex) {\n return {\n error:\n `This package declares ${all.size} shape(s) but has no src/shapes/index.ts, so an app ` +\n `cannot register them with import '<package>/shapes/index':\\n${listing}\\n` +\n `Create src/shapes/index.ts holding only side-effect imports (no exports):\\n` +\n lines.map((l) => ` ${l}`).join('\\n') +\n `\\nand import it from src/index.ts: import './shapes/index.js';` +\n moveNote,\n };\n }\n return {\n error:\n `${missing.length} shape(s) are not registered by loading lib/esm/shapes/index.js on its own, ` +\n `so an app that imports '<package>/shapes/index' never has them:\\n${listing}\\n` +\n `Add to src/shapes/index.ts:\\n` +\n lines.map((l) => ` ${l}`).join('\\n') +\n moveNote,\n };\n};\n\n/** Every emitted module under lib/esm/shapes, relative to the package root, `/`-separated. */\nconst emittedShapeModules = (packagePath: string): string[] => {\n const root = path.join(packagePath, 'lib', 'esm', 'shapes');\n const out: string[] = [];\n const walk = (dir: string) => {\n for (const e of fs.readdirSync(dir, {withFileTypes: true})) {\n const full = path.join(dir, e.name);\n if (e.isDirectory()) walk(full);\n else if (e.name.endsWith('.js'))\n out.push(path.relative(packagePath, full).split(path.sep).join('/'));\n }\n };\n if (fs.existsSync(root)) walk(root);\n return out.sort();\n};\n\n/**\n * Whether a `sideEffects` pattern matches a package-relative path, the way\n * webpack and Rollup's node-resolve read it: a leading `./` is dropped and a\n * pattern without a `/` matches the file name anywhere.\n */\nconst sideEffectsMatch = (pattern: string, file: string): boolean => {\n let p = pattern.replace(/^\\.\\//, '');\n if (!p.includes('/')) p = '**/' + p;\n return minimatch(file, p, {dot: true});\n};\n\n/**\n * Build step: `package.json` must not declare any `lib/esm/shapes` module\n * side-effect-free. A pure match of the field against the emitted files; no\n * bundling.\n */\nexport const checkShapesSideEffects = (\n packagePath: string,\n): true | {error: string} => {\n const pkgJson = JSON.parse(\n fs.readFileSync(path.join(packagePath, 'package.json'), 'utf8'),\n );\n const sideEffects = pkgJson.sideEffects;\n if (sideEffects === undefined || sideEffects === true) return true;\n const files = emittedShapeModules(packagePath);\n if (files.length === 0) return true;\n\n const fix =\n `Remove the \"sideEffects\" field, or list the shape modules in it:\\n` +\n ` \"sideEffects\": [\"lib/esm/shapes/index.js\", \"lib/esm/shapes/*.js\"]` +\n (files.some((f) => f.split('/').length > 4)\n ? `\\n (with \"lib/esm/shapes/**/*.js\" for the nested folders)`\n : '');\n const why =\n `A bundler drops a side-effect-only import of a module it is told is side-effect-free, ` +\n `so shapes/index would register nothing in a production build.`;\n\n if (sideEffects === false) {\n return {\n error: `package.json declares \"sideEffects\": false, which marks every shape module side-effect-free. ${why}\\n${fix}`,\n };\n }\n if (\n !Array.isArray(sideEffects) ||\n sideEffects.some((p) => typeof p !== 'string')\n ) {\n return {\n error: `package.json \"sideEffects\" must be true, false or a list of globs; found ${JSON.stringify(sideEffects)}.\\n${fix}`,\n };\n }\n const unmatched = files.filter(\n (f) => !sideEffects.some((p: string) => sideEffectsMatch(p, f)),\n );\n if (unmatched.length === 0) return true;\n return {\n error:\n `package.json \"sideEffects\" does not cover ${unmatched.length} shape module(s), so they are declared ` +\n `side-effect-free:\\n` +\n unmatched\n .slice(0, 10)\n .map((f) => ` ${f}`)\n .join('\\n') +\n (unmatched.length > 10 ? `\\n and ${unmatched.length - 10} more` : '') +\n `\\n${why}\\n${fix}`,\n };\n};\n"]}
|
package/lib/esm/vite-config.d.ts
CHANGED
|
@@ -29,6 +29,32 @@ import type { Plugin } from 'vite';
|
|
|
29
29
|
*/
|
|
30
30
|
export declare const chunkForModuleId: (id: string) => string | undefined;
|
|
31
31
|
export declare function hmrPortFor(devPort: unknown): number;
|
|
32
|
+
/**
|
|
33
|
+
* Whether `port` can be listened on the way Vite's HMR websocket server
|
|
34
|
+
* listens: every interface, since `createViteConfig` sets no `hmr.host`.
|
|
35
|
+
*/
|
|
36
|
+
export declare function isPortFree(port: number, host?: string): Promise<boolean>;
|
|
37
|
+
export interface ResolveHmrPortOptions {
|
|
38
|
+
/** The dev port the HMR port is derived from (`process.env.PORT ?? opts.port`). */
|
|
39
|
+
devPort: unknown;
|
|
40
|
+
env?: NodeJS.ProcessEnv;
|
|
41
|
+
isFree?: (port: number) => Promise<boolean>;
|
|
42
|
+
log?: (message: string) => void;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The HMR websocket port for this dev server.
|
|
46
|
+
*
|
|
47
|
+
* `LINKED_HMR_PORT` wins outright. Otherwise the port derived from the dev port
|
|
48
|
+
* (`hmrPortFor`) is used if it is free, and the next free port above it if it
|
|
49
|
+
* is not: the derivation keeps apps on distinct dev ports apart, but not an app
|
|
50
|
+
* from an unrelated process (or a second checkout of the same app) that already
|
|
51
|
+
* holds the derived port. Vite injects the configured `hmr.port` into the
|
|
52
|
+
* client it serves, so the browser connects to whichever port was chosen.
|
|
53
|
+
*
|
|
54
|
+
* If nothing in range is free the derived port is returned and Vite reports the
|
|
55
|
+
* conflict, as it did before.
|
|
56
|
+
*/
|
|
57
|
+
export declare function resolveHmrPort({ devPort, env, isFree, log, }: ResolveHmrPortOptions): Promise<number>;
|
|
32
58
|
export interface LinkedViteConfigOptions {
|
|
33
59
|
/** Dev server port. Default 4040. */
|
|
34
60
|
port?: number;
|
|
@@ -61,6 +87,17 @@ export interface LinkedViteConfigOptions {
|
|
|
61
87
|
* exactly like the app's own `workspaces` field.
|
|
62
88
|
*/
|
|
63
89
|
workspaceGlobs?: string[];
|
|
90
|
+
/**
|
|
91
|
+
* Add the third-party client dependencies of the excluded framework packages
|
|
92
|
+
* to `optimizeDeps.include` in dev (see ./client-dep-includes.ts). Default on;
|
|
93
|
+
* `false` (or `LINKED_CLIENT_DEP_INCLUDES=0`) turns it off, and `deny` keeps
|
|
94
|
+
* entries out — matched against the entry (`'@_linked/primitives > vaul'`),
|
|
95
|
+
* the specifier (`'vaul'`) or the package name. Run with `DEBUG=linked` to see
|
|
96
|
+
* what was added.
|
|
97
|
+
*/
|
|
98
|
+
clientDepIncludes?: boolean | {
|
|
99
|
+
deny?: (string | RegExp)[];
|
|
100
|
+
};
|
|
64
101
|
}
|
|
65
102
|
interface WorkspaceEntry {
|
|
66
103
|
name: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite-config.d.ts","sourceRoot":"","sources":["../../src/vite-config.ts"],"names":[],"mappings":"AAWA,OAAO,EAAC,YAAY,EAAC,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"vite-config.d.ts","sourceRoot":"","sources":["../../src/vite-config.ts"],"names":[],"mappings":"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"}
|
package/lib/esm/vite-config.js
CHANGED
|
@@ -7,6 +7,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
+
var _a;
|
|
11
|
+
var _b, _c;
|
|
10
12
|
// Vite config helper for linked apps. The one dev + build pipeline.
|
|
11
13
|
//
|
|
12
14
|
// Apps use this from their own vite.config.ts:
|
|
@@ -25,18 +27,8 @@ import path from 'node:path';
|
|
|
25
27
|
import { generateScopedName } from './utils.js';
|
|
26
28
|
import { parseWorkspacePatterns, isWorkspacePathNegated } from './workspace-globs.js';
|
|
27
29
|
import { pinCompiledClassNames } from './plugins/pin-compiled-class-names.js';
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
* module-level state (`@_linked/core`'s shape registry, `LinkedStorage`, the query
|
|
31
|
-
* context) or register shapes into it. Two copies in one runtime split that state
|
|
32
|
-
* and mangle shape identity (`Person`→`Person2`). This ONE list is the single source
|
|
33
|
-
* of truth for the standalone `optimizeDeps.exclude` (`linkedDeps`). In workspace mode
|
|
34
|
-
* `ssr.noExternal` is keyed on the discovered source workspaces instead (see
|
|
35
|
-
* `ssrNoExternal`), so published framework packages stay external and single-instance
|
|
36
|
-
* under Node.
|
|
37
|
-
*/
|
|
38
|
-
const FRAMEWORK_PKG_PATTERNS = [/^@_linked\//, /^lincd-/];
|
|
39
|
-
const isFrameworkPkg = (name) => FRAMEWORK_PKG_PATTERNS.some((re) => re.test(name));
|
|
30
|
+
import { isFrameworkPkg, readInstalledPkg } from './installed-packages.js';
|
|
31
|
+
import { linkedClientDepIncludesPlugin } from './client-dep-includes.js';
|
|
40
32
|
/** Default dev server port, and Vite's default HMR websocket port. */
|
|
41
33
|
const DEFAULT_DEV_PORT = 4040;
|
|
42
34
|
const DEFAULT_HMR_PORT = 24678;
|
|
@@ -130,44 +122,63 @@ export function hmrPortFor(devPort) {
|
|
|
130
122
|
const derived = DEFAULT_HMR_PORT + (validDevPort - DEFAULT_DEV_PORT);
|
|
131
123
|
return Math.min(MAX_HMR_PORT, Math.max(MIN_HMR_PORT, derived));
|
|
132
124
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}
|
|
147
|
-
catch (_a) {
|
|
148
|
-
return false;
|
|
149
|
-
}
|
|
150
|
-
});
|
|
125
|
+
/** How far past the derived port `resolveHmrPort` looks for a free one. */
|
|
126
|
+
const HMR_PORT_SEARCH_RANGE = 100;
|
|
127
|
+
/**
|
|
128
|
+
* Whether `port` can be listened on the way Vite's HMR websocket server
|
|
129
|
+
* listens: every interface, since `createViteConfig` sets no `hmr.host`.
|
|
130
|
+
*/
|
|
131
|
+
export function isPortFree(port, host) {
|
|
132
|
+
return import('node:net').then((net) => new Promise((resolve) => {
|
|
133
|
+
const probe = net.createServer();
|
|
134
|
+
probe.unref();
|
|
135
|
+
probe.once('error', () => resolve(false));
|
|
136
|
+
probe.listen({ port, host, exclusive: true }, () => probe.close(() => resolve(true)));
|
|
137
|
+
}));
|
|
151
138
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
139
|
+
/**
|
|
140
|
+
* Ports this process already chose, by derived port. Vite re-evaluates the
|
|
141
|
+
* config when it restarts the server (a vite.config edit), and it does so while
|
|
142
|
+
* the old server still holds the port — probing again would see our own socket
|
|
143
|
+
* and move to the next port on every restart.
|
|
144
|
+
*/
|
|
145
|
+
const chosenHmrPorts = ((_a = (_b = globalThis)[_c = Symbol.for('@_linked/cli.hmrPorts')]) !== null && _a !== void 0 ? _a : (_b[_c] = new Map()));
|
|
146
|
+
/**
|
|
147
|
+
* The HMR websocket port for this dev server.
|
|
148
|
+
*
|
|
149
|
+
* `LINKED_HMR_PORT` wins outright. Otherwise the port derived from the dev port
|
|
150
|
+
* (`hmrPortFor`) is used if it is free, and the next free port above it if it
|
|
151
|
+
* is not: the derivation keeps apps on distinct dev ports apart, but not an app
|
|
152
|
+
* from an unrelated process (or a second checkout of the same app) that already
|
|
153
|
+
* holds the derived port. Vite injects the configured `hmr.port` into the
|
|
154
|
+
* client it serves, so the browser connects to whichever port was chosen.
|
|
155
|
+
*
|
|
156
|
+
* If nothing in range is free the derived port is returned and Vite reports the
|
|
157
|
+
* conflict, as it did before.
|
|
158
|
+
*/
|
|
159
|
+
export function resolveHmrPort(_a) {
|
|
160
|
+
return __awaiter(this, arguments, void 0, function* ({ devPort, env = process.env, isFree = isPortFree, log = (m) => console.log(m), }) {
|
|
161
|
+
const override = env.LINKED_HMR_PORT;
|
|
162
|
+
if (override !== undefined && override.trim() !== '') {
|
|
163
|
+
const port = Number(override);
|
|
164
|
+
if (Number.isInteger(port) && port >= 1 && port <= MAX_HMR_PORT)
|
|
165
|
+
return port;
|
|
166
|
+
log(`[linked] ignoring LINKED_HMR_PORT=${override}: not a port number`);
|
|
167
|
+
}
|
|
168
|
+
const derived = hmrPortFor(devPort);
|
|
169
|
+
const remembered = chosenHmrPorts.get(derived);
|
|
170
|
+
if (remembered !== undefined)
|
|
171
|
+
return remembered;
|
|
172
|
+
for (let port = derived; port <= Math.min(MAX_HMR_PORT, derived + HMR_PORT_SEARCH_RANGE); port++) {
|
|
173
|
+
if (yield isFree(port)) {
|
|
174
|
+
chosenHmrPorts.set(derived, port);
|
|
175
|
+
if (port !== derived) {
|
|
176
|
+
log(`[linked] HMR port ${derived} is in use; using ${port} (set LINKED_HMR_PORT to choose one)`);
|
|
164
177
|
}
|
|
178
|
+
return port;
|
|
165
179
|
}
|
|
166
|
-
const parent = path.dirname(dir);
|
|
167
|
-
if (parent === dir || (yield isWorkspaceRoot(dir)))
|
|
168
|
-
return null;
|
|
169
|
-
dir = parent;
|
|
170
180
|
}
|
|
181
|
+
return derived;
|
|
171
182
|
});
|
|
172
183
|
}
|
|
173
184
|
/**
|
|
@@ -551,13 +562,15 @@ export function createViteConfig(opts = {}) {
|
|
|
551
562
|
/* best-effort — no package.json is fine */
|
|
552
563
|
}
|
|
553
564
|
}
|
|
565
|
+
const devPort = (_b = process.env.PORT) !== null && _b !== void 0 ? _b : opts.port;
|
|
566
|
+
const clientDepIncludes = isDev && opts.clientDepIncludes !== false && process.env.LINKED_CLIENT_DEP_INCLUDES !== '0';
|
|
554
567
|
const config = Object.assign(Object.assign(Object.assign({ server: {
|
|
555
|
-
port: (
|
|
568
|
+
port: (_c = opts.port) !== null && _c !== void 0 ? _c : 4040,
|
|
556
569
|
middlewareMode: true,
|
|
557
|
-
// Unique HMR websocket port per app/worktree
|
|
558
|
-
//
|
|
559
|
-
// their own `server.hmr` in mergeConfig.
|
|
560
|
-
hmr: { port:
|
|
570
|
+
// Unique HMR websocket port per app/worktree, derived from the dev port
|
|
571
|
+
// and moved to a free one when taken — see `resolveHmrPort`. Apps can
|
|
572
|
+
// still override this with their own `server.hmr` in mergeConfig.
|
|
573
|
+
hmr: { port: isDev ? yield resolveHmrPort({ devPort }) : hmrPortFor(devPort) },
|
|
561
574
|
}, build: {
|
|
562
575
|
outDir: (_d = opts.outDir) !== null && _d !== void 0 ? _d : 'public/bundles',
|
|
563
576
|
manifest: true,
|
|
@@ -659,6 +672,12 @@ export function createViteConfig(opts = {}) {
|
|
|
659
672
|
},
|
|
660
673
|
}
|
|
661
674
|
: null,
|
|
675
|
+
clientDepIncludes
|
|
676
|
+
? linkedClientDepIncludesPlugin({
|
|
677
|
+
sourceWorkspaces: workspaces,
|
|
678
|
+
deny: typeof opts.clientDepIncludes === 'object' ? opts.clientDepIncludes.deny : undefined,
|
|
679
|
+
})
|
|
680
|
+
: null,
|
|
662
681
|
...((_f = opts.plugins) !== null && _f !== void 0 ? _f : []),
|
|
663
682
|
].filter(Boolean), css: {
|
|
664
683
|
modules: {
|