@dxos/app-framework 0.14.0 → 0.16.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 +73 -0
- package/dist/lib/App.mjs +1 -2
- package/dist/lib/Hooks.mjs +1 -2
- package/dist/lib/chunk-App.mjs +11 -0
- package/dist/lib/chunk-App.mjs.map +1 -0
- package/dist/lib/chunk-Cli.mjs +8 -0
- package/dist/lib/chunk-Cli.mjs.map +1 -0
- package/dist/lib/chunk-Devtools.mjs +112 -0
- package/dist/lib/chunk-Devtools.mjs.map +1 -0
- package/dist/lib/chunk-Hooks2.mjs +35 -0
- package/dist/lib/chunk-Hooks2.mjs.map +1 -0
- package/dist/lib/chunk-PluginManagerProvider.mjs +12 -0
- package/dist/lib/chunk-PluginManagerProvider.mjs.map +1 -0
- package/dist/lib/chunk-ProcessManagerPlugin.mjs +3 -3
- package/dist/lib/chunk-ProcessManagerPlugin.mjs.map +1 -1
- package/dist/lib/chunk-Role.mjs +19 -0
- package/dist/lib/chunk-Role.mjs.map +1 -0
- package/dist/lib/chunk-SharedPackages.mjs +11 -0
- package/dist/lib/chunk-SharedPackages.mjs.map +1 -0
- package/dist/lib/chunk-Surface.mjs.map +1 -1
- package/dist/lib/chunk-Surface2.mjs +37 -0
- package/dist/lib/chunk-Surface2.mjs.map +1 -0
- package/dist/lib/chunk-SurfaceManager.mjs +3 -3
- package/dist/lib/chunk-SurfaceManager.mjs.map +1 -1
- package/dist/lib/chunk-activation-event.mjs +86 -0
- package/dist/lib/chunk-activation-event.mjs.map +1 -0
- package/dist/lib/chunk-activation-events.mjs +66 -0
- package/dist/lib/chunk-activation-events.mjs.map +1 -0
- package/dist/lib/chunk-capabilities.mjs +202 -0
- package/dist/lib/chunk-capabilities.mjs.map +1 -0
- package/dist/lib/chunk-capability-manager.mjs +203 -0
- package/dist/lib/chunk-capability-manager.mjs.map +1 -0
- package/dist/lib/chunk-capability2.mjs +2 -2
- package/dist/lib/chunk-capability2.mjs.map +1 -1
- package/dist/lib/chunk-history-tracker.mjs +1 -1
- package/dist/lib/chunk-hooks.mjs +5 -5
- package/dist/lib/chunk-hooks.mjs.map +1 -1
- package/dist/lib/chunk-plugin-asset-cache.mjs +28 -0
- package/dist/lib/chunk-plugin-asset-cache.mjs.map +1 -0
- package/dist/lib/chunk-plugin-manager.mjs +68 -35
- package/dist/lib/chunk-plugin-manager.mjs.map +1 -1
- package/dist/lib/chunk-plugin-manager2.mjs +22 -0
- package/dist/lib/chunk-plugin-manager2.mjs.map +1 -0
- package/dist/lib/chunk-plugin-manifest.mjs +126 -0
- package/dist/lib/chunk-plugin-manifest.mjs.map +1 -0
- package/dist/lib/chunk-plugin.mjs +354 -0
- package/dist/lib/chunk-plugin.mjs.map +1 -0
- package/dist/lib/chunk-process-manager-capability.mjs +11 -10
- package/dist/lib/chunk-process-manager-capability.mjs.map +1 -1
- package/dist/lib/chunk-registry.mjs.map +1 -1
- package/dist/lib/chunk-undo-mapping.mjs +47 -0
- package/dist/lib/{plugin-process-manager/history/undo-mapping.mjs.map → chunk-undo-mapping.mjs.map} +1 -1
- package/dist/lib/chunk-undo-registry.mjs +22 -0
- package/dist/lib/{plugin-process-manager/history/undo-registry.mjs.map → chunk-undo-registry.mjs.map} +1 -1
- package/dist/lib/chunk-url-loader.mjs +345 -0
- package/dist/lib/chunk-url-loader.mjs.map +1 -0
- package/dist/lib/cli.mjs +3 -3
- package/dist/lib/cli.mjs.map +1 -1
- package/dist/lib/common/Role.mjs +1 -19
- package/dist/lib/common/activation-events.mjs +1 -57
- package/dist/lib/common/capabilities.mjs +1 -202
- package/dist/lib/config.mjs +1 -2
- package/dist/lib/core/activation-event.mjs +1 -86
- package/dist/lib/core/capability-manager.mjs +1 -203
- package/dist/lib/core/capability.mjs +1 -2
- package/dist/lib/core/plugin-asset-cache.mjs +1 -28
- package/dist/lib/core/plugin-manager.mjs +2 -19
- package/dist/lib/core/plugin-manifest.mjs +1 -126
- package/dist/lib/core/plugin.mjs +1 -354
- package/dist/lib/core/registry.mjs +1 -2
- package/dist/lib/core/url-loader.mjs +1 -345
- package/dist/lib/index.mjs +19 -19
- package/dist/lib/ns/App.mjs +2 -11
- package/dist/lib/ns/Cli.mjs +2 -8
- package/dist/lib/ns/Devtools.mjs +1 -112
- package/dist/lib/ns/Hooks.mjs +2 -35
- package/dist/lib/ns/PluginManagerProvider.mjs +2 -12
- package/dist/lib/ns/SharedPackages.mjs +2 -11
- package/dist/lib/ns/Surface.mjs +2 -35
- package/dist/lib/ns/Translations.mjs +1 -2
- package/dist/lib/plugin-cli.mjs +2 -4
- package/dist/lib/plugin-cli.mjs.map +1 -1
- package/dist/lib/plugin-process-manager/ProcessManagerPlugin.mjs +1 -2
- package/dist/lib/plugin-process-manager/history/history-tracker.mjs +1 -2
- package/dist/lib/plugin-process-manager/history/undo-mapping.mjs +1 -47
- package/dist/lib/plugin-process-manager/history/undo-registry.mjs +1 -22
- package/dist/lib/testing/react.mjs +1 -1
- package/dist/lib/testing/react.mjs.map +1 -1
- package/dist/lib/testing.mjs +5 -5
- package/dist/lib/testing.mjs.map +1 -1
- package/dist/lib/vite-plugin.mjs +3 -3
- package/dist/lib/vite-plugin.mjs.map +1 -1
- package/dist/types/src/common/activation-events.d.ts +8 -0
- package/dist/types/src/common/activation-events.d.ts.map +1 -1
- package/dist/types/src/core/plugin-manager/manager-state.d.ts.map +1 -1
- package/dist/types/src/core/plugin-manager/module-loader.d.ts +0 -10
- package/dist/types/src/core/plugin-manager/module-loader.d.ts.map +1 -1
- package/dist/types/src/core/plugin-manager/plugin-manager.d.ts.map +1 -1
- package/dist/types/src/plugin-process-manager/process-manager-capability.d.ts.map +1 -1
- package/dist/types/src/ui/components/Surface/SurfaceComponent.stories.d.ts.map +1 -1
- package/dist/types/src/ui/hooks/useApp.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +32 -32
- package/src/common/activation-events.ts +9 -0
- package/src/core/plugin-manager/manager-state.ts +14 -12
- package/src/core/plugin-manager/module-loader.ts +43 -7
- package/src/core/plugin-manager/plugin-manager.ts +2 -1
- package/src/plugin-process-manager/process-manager-capability.test.ts +66 -1
- package/src/plugin-process-manager/process-manager-capability.ts +22 -2
- package/src/ui/components/Surface/SurfaceComponent.stories.tsx +9 -7
- package/src/ui/hooks/useApp.tsx +2 -1
- package/src/vite-plugin/boot-loader/loader-app/boot-loader.css +19 -1
- package/dist/lib/common/Role.mjs.map +0 -1
- package/dist/lib/common/activation-events.mjs.map +0 -1
- package/dist/lib/common/capabilities.mjs.map +0 -1
- package/dist/lib/core/activation-event.mjs.map +0 -1
- package/dist/lib/core/capability-manager.mjs.map +0 -1
- package/dist/lib/core/plugin-asset-cache.mjs.map +0 -1
- package/dist/lib/core/plugin-manager.mjs.map +0 -1
- package/dist/lib/core/plugin-manifest.mjs.map +0 -1
- package/dist/lib/core/plugin.mjs.map +0 -1
- package/dist/lib/core/url-loader.mjs.map +0 -1
- package/dist/lib/ns/App.mjs.map +0 -1
- package/dist/lib/ns/Cli.mjs.map +0 -1
- package/dist/lib/ns/Devtools.mjs.map +0 -1
- package/dist/lib/ns/Hooks.mjs.map +0 -1
- package/dist/lib/ns/PluginManagerProvider.mjs.map +0 -1
- package/dist/lib/ns/SharedPackages.mjs.map +0 -1
- package/dist/lib/ns/Surface.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-cli.mjs","names":[],"sources":["../../src/plugin-cli/ts-util.ts","../../src/plugin-cli/maker-defaults.ts","../../src/plugin-cli/barrel.ts","../../src/plugin-cli/generate.ts","../../src/plugin-cli/main.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport fs from 'node:fs';\nimport { createRequire as nodeCreateRequire } from 'node:module';\nimport path from 'node:path';\n\n// The tool operates on the consumer's TypeScript source, so it borrows an existing compiler-API\n// install instead of adding a heavyweight runtime dependency to app-framework that every browser\n// consumer would download.\n//\n// `@typescript/typescript6` first: the `typescript` specifier now resolves to the 7.x native\n// preview, which ships only `version` — no `createSourceFile`, no `ScriptTarget`. Resolution\n// succeeding therefore proves nothing, so each candidate is probed for the API actually used here\n// and skipped when it is absent; the same package the protobuf compiler imports for this reason.\nconst TYPESCRIPT_CANDIDATES = ['@typescript/typescript6', 'typescript'] as const;\n\nconst resolveTypescript = (): typeof import('@typescript/typescript6') => {\n const bases = [path.join(process.cwd(), 'package.json'), import.meta.url];\n for (const base of bases) {\n for (const specifier of TYPESCRIPT_CANDIDATES) {\n try {\n const module = nodeCreateRequire(base)(specifier);\n if (typeof module?.createSourceFile === 'function' && module.ScriptTarget) {\n return module;\n }\n } catch {\n continue;\n }\n }\n }\n throw new Error(\n `dx-plugin needs a TypeScript compiler API: install one of ${TYPESCRIPT_CANDIDATES.join(' or ')} in the target package or workspace.`,\n );\n};\n\nexport const ts = resolveTypescript();\n\ntype SourceFile = import('@typescript/typescript6').SourceFile;\ntype Node = import('@typescript/typescript6').Node;\ntype Statement = import('@typescript/typescript6').Statement;\ntype Expression = import('@typescript/typescript6').Expression;\n\n/** Parse a file into a ts.SourceFile, or null if it doesn't exist. */\nexport const parseFile = (filePath: string): SourceFile | null => {\n if (!fs.existsSync(filePath)) {\n return null;\n }\n const text = fs.readFileSync(filePath, 'utf8');\n return ts.createSourceFile(filePath, text, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);\n};\n\n/** Full source text of a node, as written (not re-printed). */\nexport const nodeText = (sourceFile: SourceFile, node: Node): string =>\n sourceFile.text.slice(node.getStart(sourceFile), node.getEnd());\n\n/** Flattened text of a member-access chain, e.g. `AppCapability.schema`. */\nexport const calleeText = (sourceFile: SourceFile, expr: Expression): string => {\n if (ts.isIdentifier(expr)) {\n return expr.text;\n }\n if (ts.isPropertyAccessExpression(expr)) {\n return `${calleeText(sourceFile, expr.expression)}.${expr.name.text}`;\n }\n return nodeText(sourceFile, expr);\n};\n\n/** Statement text including the comments directly above it — sliced verbatim into generated barrels. */\nexport const statementTextWithLeadingComments = (sourceFile: SourceFile, statement: Statement): string => {\n const fullStart = statement.getFullStart();\n const start = statement.getStart(sourceFile);\n const leading = sourceFile.text.slice(fullStart, start).replace(/^\\s*\\n+/, '');\n const body = sourceFile.text.slice(start, statement.getEnd());\n return (leading + body).trimEnd();\n};\n\nexport type ExportConst = {\n name: string;\n statement: Statement;\n initializer: Expression;\n};\n\n/** All `export const NAME = ...` at top level. */\nexport const topLevelExportConsts = (sourceFile: SourceFile): ExportConst[] => {\n const out: ExportConst[] = [];\n for (const stmt of sourceFile.statements) {\n if (!ts.isVariableStatement(stmt)) {\n continue;\n }\n if (!stmt.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword)) {\n continue;\n }\n for (const decl of stmt.declarationList.declarations) {\n if (!ts.isIdentifier(decl.name) || !decl.initializer) {\n continue;\n }\n out.push({ name: decl.name.text, statement: stmt, initializer: decl.initializer });\n }\n }\n return out;\n};\n\nexport type LocalDeclaration = {\n name: string;\n text: string;\n};\n\n/**\n * Top-level declarations a file keeps to itself — `const` and `function` without `export`. A kept\n * module statement can reference one (a helper the barrel author factored out), and it has to\n * travel with the statement or the generated barrel will not compile.\n */\nexport const topLevelLocalDeclarations = (sourceFile: SourceFile): LocalDeclaration[] => {\n const out: LocalDeclaration[] = [];\n const exported = (stmt: Statement): boolean =>\n (ts.canHaveModifiers(stmt) ? ts.getModifiers(stmt) : undefined)?.some(\n (modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword,\n ) ?? false;\n\n for (const stmt of sourceFile.statements) {\n if (exported(stmt)) {\n continue;\n }\n if (ts.isVariableStatement(stmt)) {\n for (const decl of stmt.declarationList.declarations) {\n if (ts.isIdentifier(decl.name)) {\n out.push({ name: decl.name.text, text: statementTextWithLeadingComments(sourceFile, stmt) });\n }\n }\n } else if (\n (ts.isFunctionDeclaration(stmt) || ts.isTypeAliasDeclaration(stmt) || ts.isInterfaceDeclaration(stmt)) &&\n stmt.name\n ) {\n out.push({ name: stmt.name.text, text: statementTextWithLeadingComments(sourceFile, stmt) });\n }\n }\n return out;\n};\n\nexport type ExportDeclarationEntry =\n | { kind: 'star'; moduleSpecifier: string | null }\n | { kind: 'named'; isTypeOnly: boolean; localName: string; exportedName: string; moduleSpecifier: string | null };\n\n/** All `export * from '...'` / `export { A as B } from '...'` entries. */\nexport const topLevelExportDeclarations = (sourceFile: SourceFile): ExportDeclarationEntry[] => {\n const out: ExportDeclarationEntry[] = [];\n for (const stmt of sourceFile.statements) {\n if (!ts.isExportDeclaration(stmt)) {\n continue;\n }\n const moduleSpecifier =\n stmt.moduleSpecifier && ts.isStringLiteral(stmt.moduleSpecifier) ? stmt.moduleSpecifier.text : null;\n if (stmt.exportClause === undefined) {\n out.push({ kind: 'star', moduleSpecifier });\n } else if (ts.isNamedExports(stmt.exportClause)) {\n for (const el of stmt.exportClause.elements) {\n out.push({\n kind: 'named',\n isTypeOnly: stmt.isTypeOnly || el.isTypeOnly,\n localName: (el.propertyName ?? el.name).text,\n exportedName: el.name.text,\n moduleSpecifier,\n });\n }\n }\n }\n return out;\n};\n\n/** Resolve a relative import specifier to a file on disk. */\nexport const resolveRelativeModule = (fromDir: string, spec: string): string | null => {\n if (!spec.startsWith('.')) {\n return null;\n }\n const base = path.resolve(fromDir, spec);\n // The specifier may already carry its extension (`./foo/index.ts`) — resolve it directly rather\n // than appending another one on top, which would never exist on disk.\n if (/\\.tsx?$/.test(base)) {\n return fs.existsSync(base) ? base : null;\n }\n const candidates = [`${base}.ts`, `${base}.tsx`, path.join(base, 'index.ts'), path.join(base, 'index.tsx')];\n return candidates.find((candidate) => fs.existsSync(candidate)) ?? null;\n};\n\nexport type ImportDeclarationEntry = {\n text: string;\n boundNames: Set<string>;\n specifier: string;\n /** Whole-clause `import type`, distinct from a per-element `type` modifier. */\n isTypeOnly: boolean;\n defaultName: string | null;\n namespaceName: string | null;\n /** Named bindings as written, e.g. `Foo`, `Foo as Bar`, `type Foo`. */\n named: string[];\n};\n\n/** Every top-level import declaration, with the local identifiers it binds. */\nexport const topLevelImportDeclarations = (sourceFile: SourceFile): ImportDeclarationEntry[] => {\n const out: ImportDeclarationEntry[] = [];\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt) || !stmt.importClause) {\n continue;\n }\n const boundNames = new Set<string>();\n const clause = stmt.importClause;\n if (clause.name) {\n boundNames.add(clause.name.text);\n }\n if (clause.namedBindings) {\n if (ts.isNamespaceImport(clause.namedBindings)) {\n boundNames.add(clause.namedBindings.name.text);\n } else if (ts.isNamedImports(clause.namedBindings)) {\n for (const el of clause.namedBindings.elements) {\n boundNames.add(el.name.text);\n }\n }\n }\n const named: string[] = [];\n let namespaceName: string | null = null;\n if (clause.namedBindings) {\n if (ts.isNamespaceImport(clause.namedBindings)) {\n namespaceName = clause.namedBindings.name.text;\n } else if (ts.isNamedImports(clause.namedBindings)) {\n for (const el of clause.namedBindings.elements) {\n named.push(nodeText(sourceFile, el));\n }\n }\n }\n out.push({\n text: nodeText(sourceFile, stmt),\n boundNames,\n specifier: ts.isStringLiteralLike(stmt.moduleSpecifier) ? stmt.moduleSpecifier.text : '',\n isTypeOnly: clause.isTypeOnly,\n defaultName: clause.name?.text ?? null,\n namespaceName,\n named,\n });\n }\n return out;\n};\n\n/**\n * Free identifiers referenced in a standalone snippet. Skips member-access property names and\n * non-computed object keys; otherwise over-collects — harmless, since callers only test membership\n * against known import bindings.\n */\nexport const collectFreeIdentifiers = (snippet: string): Set<string> => {\n const sf = ts.createSourceFile('snippet.tsx', snippet, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);\n const names = new Set<string>();\n const isSkipped = (node: Node): boolean => {\n const parent = node.parent;\n if (!parent) {\n return false;\n }\n if (ts.isPropertyAccessExpression(parent) && parent.name === node) {\n return true;\n }\n if (\n (ts.isPropertyAssignment(parent) ||\n ts.isPropertySignature(parent) ||\n ts.isMethodDeclaration(parent) ||\n ts.isMethodSignature(parent)) &&\n parent.name === node\n ) {\n return true;\n }\n return false;\n };\n const visit = (node: Node): void => {\n if (ts.isIdentifier(node) && !isSkipped(node)) {\n names.add(node.text);\n }\n ts.forEachChild(node, visit);\n };\n visit(sf);\n return names;\n};\n\n/**\n * Rewrite every relative module specifier in a snippet (static `from '...'` and dynamic\n * `import('...')`) so text authored in `originDir` stays correct when emitted into `outDir`.\n */\n/** Re-bases one relative module specifier from `originDir` to `outDir`; absolute ones pass through. */\nexport const rebaseSpecifier = (specifier: string, originDir: string, outDir: string): string => {\n if (!specifier.startsWith('.')) {\n return specifier;\n }\n const next = path.relative(outDir, path.resolve(originDir, specifier)).split(path.sep).join('/');\n return next.startsWith('.') ? next : `./${next}`;\n};\n\nexport const rewriteRelativeSpecifiers = (snippet: string, originDir: string, outDir: string): string => {\n const sf = ts.createSourceFile('snippet.tsx', snippet, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);\n const edits: Array<{ start: number; end: number; text: string }> = [];\n const rewrite = (literal: import('@typescript/typescript6').StringLiteral): void => {\n if (!literal.text.startsWith('.')) {\n return;\n }\n const absolute = path.resolve(originDir, literal.text);\n let next = path.relative(outDir, absolute).split(path.sep).join('/');\n if (!next.startsWith('.')) {\n next = `./${next}`;\n }\n const quote = snippet[literal.getStart(sf)];\n edits.push({ start: literal.getStart(sf), end: literal.getEnd(), text: `${quote}${next}${quote}` });\n };\n const visit = (node: Node): void => {\n if (\n (ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) &&\n node.moduleSpecifier &&\n ts.isStringLiteral(node.moduleSpecifier)\n ) {\n rewrite(node.moduleSpecifier);\n }\n if (\n ts.isCallExpression(node) &&\n node.expression.kind === ts.SyntaxKind.ImportKeyword &&\n node.arguments.length === 1 &&\n ts.isStringLiteral(node.arguments[0])\n ) {\n rewrite(node.arguments[0]);\n }\n ts.forEachChild(node, visit);\n };\n visit(sf);\n let result = snippet;\n for (const edit of edits.sort((a, b) => b.start - a.start)) {\n result = result.slice(0, edit.start) + edit.text + result.slice(edit.end);\n }\n return result;\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport * as fs from 'node:fs';\nimport { createRequire as nodeCreateRequire } from 'node:module';\nimport * as path from 'node:path';\n\nimport { parseFile, ts } from './ts-util.ts';\n\n/**\n * Per-family condition defaults, resolved from the module a barrel imports its makers from.\n *\n * The generator parses barrels rather than executing them, so it reads each maker's default from\n * the maker's own declaration: the `environments` literal it passes to `moduleMaker`, or the one\n * it falls back to as `options?.environments ?? [...]`. There is no second copy to drift.\n */\nexport type MakerDefaults = {\n /** Conditions for `<namespace>.<maker>`, or null when the module declares no default for it. */\n lookup: (namespace: string | null, maker: string) => readonly string[] | null;\n};\n\n/**\n * Resolves a module specifier to a source file: relative paths directly, bare package subpaths via\n * the package's own `exports` map, preferring the `source` condition (the in-workspace TypeScript)\n * and falling back to `import` (a published package's built JS, which the TS parser also reads).\n */\nconst resolveModuleFile = (fromDir: string, spec: string): string | null => {\n if (spec.startsWith('.')) {\n const base = path.resolve(fromDir, spec);\n const candidates = [`${base}.ts`, `${base}.tsx`, path.join(base, 'index.ts'), path.join(base, 'index.tsx')];\n return candidates.find((candidate) => fs.existsSync(candidate)) ?? null;\n }\n\n const match = /^(@[^/]+\\/[^/]+|[^@][^/]*)(\\/.*)?$/.exec(spec);\n if (!match) {\n return null;\n }\n const [, pkgName, subpath = '.'] = match;\n\n let pkgJsonPath: string;\n try {\n pkgJsonPath = nodeCreateRequire(path.join(fromDir, 'noop.js')).resolve(`${pkgName}/package.json`);\n } catch {\n return null;\n }\n const pkgDir = path.dirname(pkgJsonPath);\n const entry = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8'))?.exports?.[subpath === '.' ? '.' : `.${subpath}`];\n const target = typeof entry === 'string' ? entry : (entry?.source ?? entry?.import);\n if (typeof target !== 'string') {\n return null;\n }\n const resolved = path.join(pkgDir, target);\n return fs.existsSync(resolved) ? resolved : null;\n};\n\n/**\n * Every `environments` literal a maker module declares, keyed by the exported maker's name.\n *\n * Two shapes occur, and both are the maker stating its own default: `moduleMaker(name, tag, {\n * environments: [...] })` for the loader-based families, and `options?.environments ?? [...]`\n * inside the value-based helpers. Taking the right operand of the `??` reads the fallback rather\n * than the caller's override, which is exactly the default being sought.\n */\nconst readMakerDefaults = (filePath: string): Map<string, readonly string[]> | null => {\n const source = parseFile(filePath);\n if (!source) {\n return null;\n }\n\n const out = new Map<string, readonly string[]>();\n for (const stmt of source.statements) {\n if (!ts.isVariableStatement(stmt)) {\n continue;\n }\n for (const decl of stmt.declarationList.declarations) {\n if (!ts.isIdentifier(decl.name) || !decl.initializer) {\n continue;\n }\n const found = findEnvironments(decl.initializer);\n if (found) {\n out.set(decl.name.text, found);\n }\n }\n }\n return out.size > 0 ? out : null;\n};\n\n/** First `environments:` literal reachable in an expression, unwrapping a `??` fallback. */\nconst findEnvironments = (node: import('@typescript/typescript6').Node): readonly string[] | null => {\n let found: readonly string[] | null = null;\n const visit = (child: import('@typescript/typescript6').Node): void => {\n if (found) {\n return;\n }\n if (ts.isPropertyAssignment(child) && ts.isIdentifier(child.name) && child.name.text === 'environments') {\n let value: import('@typescript/typescript6').Node = child.initializer;\n if (ts.isBinaryExpression(value) && value.operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken) {\n value = value.right;\n }\n if (ts.isArrayLiteralExpression(value)) {\n found = value.elements.filter(ts.isStringLiteralLike).map((element) => element.text);\n return;\n }\n }\n ts.forEachChild(child, visit);\n };\n visit(node);\n return found;\n};\n\n/**\n * Builds the default lookup for one barrel, from the maker modules it imports. Only namespace\n * imports carry defaults: a maker family is addressed as `<namespace>.<maker>`, which is how the\n * repo imports them (`import * as AppCapability from '@dxos/app-toolkit/AppCapability'`).\n */\nexport const makerDefaults = (barrelPath: string): MakerDefaults => {\n const source = parseFile(barrelPath);\n const byNamespace = new Map<string, Map<string, readonly string[]>>();\n if (source) {\n const barrelDir = path.dirname(barrelPath);\n for (const { namespace, specifier } of namespaceImports(source)) {\n const file = resolveModuleFile(barrelDir, specifier);\n const defaults = file && readMakerDefaults(file);\n if (defaults) {\n byNamespace.set(namespace, defaults);\n }\n }\n }\n return {\n lookup: (namespace, maker) => (namespace ? (byNamespace.get(namespace)?.get(maker) ?? null) : null),\n };\n};\n\n/** Namespace imports (`import * as X from '...'`) with the specifier each binds. */\nconst namespaceImports = (\n source: import('@typescript/typescript6').SourceFile,\n): { namespace: string; specifier: string }[] => {\n const out: { namespace: string; specifier: string }[] = [];\n for (const stmt of source.statements) {\n if (\n !ts.isImportDeclaration(stmt) ||\n !stmt.importClause?.namedBindings ||\n !ts.isNamespaceImport(stmt.importClause.namedBindings) ||\n !ts.isStringLiteralLike(stmt.moduleSpecifier)\n ) {\n continue;\n }\n out.push({ namespace: stmt.importClause.namedBindings.name.text, specifier: stmt.moduleSpecifier.text });\n }\n return out;\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport path from 'node:path';\n\nimport { type MakerDefaults, makerDefaults } from './maker-defaults.ts';\nimport {\n type ExportConst,\n calleeText,\n nodeText,\n parseFile,\n resolveRelativeModule,\n statementTextWithLeadingComments,\n topLevelExportConsts,\n topLevelExportDeclarations,\n ts,\n} from './ts-util.ts';\n\nexport type BarrelMember = {\n name: string;\n /** `maker-call` members are module declarations; anything else is a helper/value export. */\n kind: 'maker-call' | 'non-call-initializer';\n /**\n * Conditions this module is split out for: the call site's own `environments` literal, else the\n * default its maker family declares. Null means neither applies, and the module is treated as\n * isomorphic — every generated variant carries it.\n */\n environments: readonly string[] | null;\n /** File the declaration statement actually lives in (may differ from the barrel via re-exports). */\n sourceFile: string;\n statementText: string;\n};\n\n/**\n * Parses a canonical capabilities barrel into exported-name -> member, resolving one level of\n * `export * from` / `export { X } from` indirection (both occur in real plugin barrels).\n */\nexport const parseBarrel = (\n filePath: string,\n defaults: MakerDefaults = makerDefaults(filePath),\n): Map<string, BarrelMember> => {\n const members = new Map<string, BarrelMember>();\n const sourceFile = parseFile(filePath);\n if (!sourceFile) {\n return members;\n }\n\n for (const entry of topLevelExportConsts(sourceFile)) {\n members.set(entry.name, describeMember(sourceFile, entry, filePath, defaults));\n }\n\n for (const exp of topLevelExportDeclarations(sourceFile)) {\n if (exp.kind === 'star') {\n if (!exp.moduleSpecifier) {\n continue;\n }\n const target = resolveRelativeModule(path.dirname(filePath), exp.moduleSpecifier);\n if (!target) {\n continue;\n }\n for (const [name, member] of parseBarrel(target)) {\n members.set(name, member);\n }\n } else if (!exp.isTypeOnly && exp.moduleSpecifier) {\n const target = resolveRelativeModule(path.dirname(filePath), exp.moduleSpecifier);\n if (!target) {\n continue;\n }\n const found = parseBarrel(target).get(exp.localName);\n if (found) {\n members.set(exp.exportedName, found);\n }\n }\n }\n\n return members;\n};\n\nconst describeMember = (\n sourceFile: import('@typescript/typescript6').SourceFile,\n entry: ExportConst,\n filePath: string,\n defaults: MakerDefaults,\n): BarrelMember => {\n const statementText = statementTextWithLeadingComments(sourceFile, entry.statement);\n if (!ts.isCallExpression(entry.initializer)) {\n return { name: entry.name, kind: 'non-call-initializer', environments: null, sourceFile: filePath, statementText };\n }\n return {\n name: entry.name,\n kind: 'maker-call',\n environments: resolveEnvironments(sourceFile, entry.initializer, defaults),\n sourceFile: filePath,\n statementText,\n };\n};\n\n/**\n * A module's conditions: its own `environments` literal if it declares one, else the default its\n * maker family declares. Only the call site can narrow or widen a family — that is the whole point\n * of the family default, so a genuine exception stays a one-line annotation at the exception.\n */\nconst resolveEnvironments = (\n sourceFile: import('@typescript/typescript6').SourceFile,\n call: import('@typescript/typescript6').CallExpression,\n defaults: MakerDefaults,\n): readonly string[] | null => {\n const declared = readEnvironments(sourceFile, call);\n if (declared) {\n return declared;\n }\n const callee = call.expression;\n return ts.isPropertyAccessExpression(callee) && ts.isIdentifier(callee.expression)\n ? defaults.lookup(callee.expression.text, callee.name.text)\n : null;\n};\n\n/**\n * Reads the `environments: ['...']` literal from whichever argument of the maker call is an\n * object literal carrying it — covers maker options bags, `lazyModule`/`inlineModule` specs, and\n * the value-based helpers' options. A computed (non-literal) value is a hard error: the generator\n * is the only consumer and would silently mis-classify the module.\n */\nconst readEnvironments = (\n sourceFile: import('@typescript/typescript6').SourceFile,\n call: import('@typescript/typescript6').CallExpression,\n): readonly string[] | null => {\n for (const arg of call.arguments) {\n if (!ts.isObjectLiteralExpression(arg)) {\n continue;\n }\n for (const prop of arg.properties) {\n if (!ts.isPropertyAssignment(prop) || !ts.isIdentifier(prop.name) || prop.name.text !== 'environments') {\n continue;\n }\n if (!ts.isArrayLiteralExpression(prop.initializer)) {\n throw new Error(\n `environments must be a literal array of string literals (${calleeText(sourceFile, call.expression)} at ${sourceFile.fileName})`,\n );\n }\n const values: string[] = [];\n for (const element of prop.initializer.elements) {\n if (!ts.isStringLiteralLike(element)) {\n throw new Error(\n `environments must be a literal array of string literals (${calleeText(sourceFile, call.expression)} at ${sourceFile.fileName}, saw ${nodeText(sourceFile, element)})`,\n );\n }\n values.push(element.text);\n }\n return values;\n }\n }\n return null;\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nimport { type BarrelMember, parseBarrel } from './barrel.ts';\nimport {\n collectFreeIdentifiers,\n parseFile,\n rebaseSpecifier,\n rewriteRelativeSpecifiers,\n topLevelImportDeclarations,\n topLevelLocalDeclarations,\n} from './ts-util.ts';\n\nexport type GenerateResult = {\n pluginDir: string;\n environments: string[];\n files: Array<{ path: string; included: number; stubbed: number; values: number }>;\n};\n\nconst findFirst = (dir: string, names: string[]): string | null =>\n names.map((name) => path.join(dir, name)).find((candidate) => fs.existsSync(candidate)) ?? null;\n\n/**\n * Generates the per-condition capability barrels for one plugin package:\n * `src/capabilities/gen/<env>.ts` for every condition named by an `environments` annotation in\n * the canonical barrel, plus the matching `#capabilities` condition map in package.json.\n */\nexport const generate = (pluginDir: string): GenerateResult => {\n const capabilitiesDir = path.join(pluginDir, 'src/capabilities');\n const indexPath = findFirst(capabilitiesDir, ['index.ts', 'index.tsx']);\n if (!indexPath) {\n throw new Error(`no capabilities barrel found at ${capabilitiesDir}/index.ts`);\n }\n\n const members = parseBarrel(indexPath);\n const moduleMembers = [...members.values()].filter((member) => member.kind === 'maker-call');\n const valueMembers = [...members.values()].filter((member) => member.kind === 'non-call-initializer');\n const environments = [...new Set(moduleMembers.flatMap((member) => member.environments ?? []))].sort();\n\n const genDir = path.join(capabilitiesDir, 'gen');\n const result: GenerateResult = { pluginDir, environments, files: [] };\n const canonicalSource = `./${path.relative(pluginDir, indexPath).split(path.sep).join('/')}`;\n fs.rmSync(genDir, { recursive: true, force: true });\n if (environments.length === 0) {\n // Still sync: dropping the last annotation has to retract the conditions too, or package.json\n // keeps pointing `#capabilities` at gen files that are no longer produced.\n syncPackageImports(pluginDir, environments, canonicalSource);\n return result;\n }\n fs.mkdirSync(genDir, { recursive: true });\n\n for (const env of environments) {\n const carries = (member: BarrelMember) => member.environments === null || member.environments.includes(env);\n const modules = moduleMembers.filter(carries);\n const included = [...valueMembers, ...modules];\n const stubbed = moduleMembers.filter((member) => !carries(member));\n\n const text = renderBarrel({ env, genDir, included, stubbed });\n const outPath = path.join(genDir, `${env}.ts`);\n fs.writeFileSync(outPath, text);\n result.files.push({\n path: outPath,\n included: modules.length,\n stubbed: stubbed.length,\n values: valueMembers.length,\n });\n }\n\n syncPackageImports(pluginDir, environments, canonicalSource);\n return result;\n};\n\ntype RenderOptions = {\n env: string;\n genDir: string;\n included: BarrelMember[];\n stubbed: BarrelMember[];\n};\n\nconst renderBarrel = ({ env, genDir, included, stubbed }: RenderOptions): string => {\n type Merged = { isTypeOnly: boolean; defaultName: string | null; namespaceName: string | null; named: Set<string> };\n const bySpecifier = new Map<string, Merged>();\n const importCache = new Map<string, ReturnType<typeof topLevelImportDeclarations>>();\n for (const member of included) {\n const free = collectFreeIdentifiers(member.statementText);\n if (!importCache.has(member.sourceFile)) {\n importCache.set(member.sourceFile, topLevelImportDeclarations(parseFile(member.sourceFile)!));\n }\n for (const decl of importCache.get(member.sourceFile)!) {\n if (![...decl.boundNames].some((name) => free.has(name))) {\n continue;\n }\n const spec = rebaseSpecifier(decl.specifier, path.dirname(member.sourceFile), genDir);\n const existing = bySpecifier.get(spec) ?? {\n isTypeOnly: decl.isTypeOnly,\n defaultName: null,\n namespaceName: null,\n named: new Set<string>(),\n };\n existing.isTypeOnly = existing.isTypeOnly && decl.isTypeOnly;\n existing.defaultName ??= decl.defaultName;\n existing.namespaceName ??= decl.namespaceName;\n for (const name of decl.named) {\n existing.named.add(name);\n }\n bySpecifier.set(spec, existing);\n }\n }\n\n const locals: Array<{ sourceFile: string; name: string; text: string }> = [];\n const localCache = new Map<string, ReturnType<typeof topLevelLocalDeclarations>>();\n for (const member of included) {\n if (!localCache.has(member.sourceFile)) {\n localCache.set(member.sourceFile, topLevelLocalDeclarations(parseFile(member.sourceFile)!));\n }\n const available = localCache.get(member.sourceFile)!;\n const taken = new Set(locals.filter((local) => local.sourceFile === member.sourceFile).map((l) => l.name));\n const pending = [...collectFreeIdentifiers(member.statementText)];\n while (pending.length > 0) {\n const name = pending.pop()!;\n if (taken.has(name)) {\n continue;\n }\n const decl = available.find((candidate) => candidate.name === name);\n if (!decl) {\n continue;\n }\n taken.add(name);\n locals.push({ sourceFile: member.sourceFile, name, text: decl.text });\n pending.push(...collectFreeIdentifiers(decl.text));\n }\n }\n\n for (const local of locals) {\n const free = collectFreeIdentifiers(local.text);\n for (const decl of importCache.get(local.sourceFile) ?? []) {\n if (![...decl.boundNames].some((name) => free.has(name))) {\n continue;\n }\n const spec = rebaseSpecifier(decl.specifier, path.dirname(local.sourceFile), genDir);\n const existing = bySpecifier.get(spec) ?? {\n isTypeOnly: decl.isTypeOnly,\n defaultName: null,\n namespaceName: null,\n named: new Set<string>(),\n };\n existing.isTypeOnly = existing.isTypeOnly && decl.isTypeOnly;\n existing.defaultName ??= decl.defaultName;\n existing.namespaceName ??= decl.namespaceName;\n for (const name of decl.named) {\n existing.named.add(name);\n }\n bySpecifier.set(spec, existing);\n }\n }\n\n const importTexts = new Set<string>();\n for (const [spec, merged] of bySpecifier) {\n const prefix = merged.isTypeOnly ? 'import type' : 'import';\n if (merged.namespaceName) {\n importTexts.add(`${prefix} * as ${merged.namespaceName} from '${spec}';`);\n }\n const clause = [merged.defaultName, merged.named.size > 0 ? `{ ${[...merged.named].sort().join(', ')} }` : null]\n .filter(Boolean)\n .join(', ');\n if (clause) {\n importTexts.add(`${prefix} ${clause} from '${spec}';`);\n }\n }\n\n const lines: string[] = [\n '//',\n '// Copyright 2026 DXOS.org',\n '//',\n '',\n `// GENERATED by dx-plugin — do not edit. Sliced from ../index.ts for the '${env}' condition.`,\n '',\n ];\n if (importTexts.size > 0) {\n lines.push(...sortImports([...importTexts]), '');\n }\n for (const local of locals) {\n lines.push(rewriteRelativeSpecifiers(local.text, path.dirname(local.sourceFile), genDir), '');\n }\n for (const member of included) {\n lines.push(rewriteRelativeSpecifiers(member.statementText, path.dirname(member.sourceFile), genDir), '');\n }\n for (const member of [...stubbed].sort((a, b) => a.name.localeCompare(b.name))) {\n lines.push(`export const ${member.name} = undefined;`);\n }\n return (\n lines\n .join('\\n')\n .replace(/\\n{3,}/g, '\\n\\n')\n .trimEnd() + '\\n'\n );\n};\n\n/** Sort import statements into the repo's groups: external, @dxos, `#` internal, relative. */\nconst sortImports = (imports: string[]): string[] => {\n const specifier = (text: string): string => /from\\s+['\"]([^'\"]+)['\"]/.exec(text)?.[1] ?? text;\n const group = (spec: string): number =>\n spec.startsWith('#') ? 2 : spec.startsWith('.') ? 3 : spec.startsWith('@dxos/') ? 1 : 0;\n const sorted = [...imports].sort((a, b) => {\n const specA = specifier(a);\n const specB = specifier(b);\n return group(specA) - group(specB) || specA.localeCompare(specB);\n });\n const out: string[] = [];\n let lastGroup: number | null = null;\n for (const text of sorted) {\n const currentGroup = group(specifier(text));\n if (lastGroup !== null && currentGroup !== lastGroup) {\n out.push('');\n }\n out.push(text);\n lastGroup = currentGroup;\n }\n return out;\n};\n\n/**\n * Rewrites the `#capabilities` entry of the plugin's package.json so each generated environment\n * resolves the generated barrel (source condition) and its built counterpart (dist condition).\n */\nconst syncPackageImports = (pluginDir: string, environments: string[], canonicalSource: string): void => {\n const pkgPath = path.join(pluginDir, 'package.json');\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));\n const existing = pkg.imports?.['#capabilities'];\n\n // Nothing to split and nothing already split: leave the manifest untouched. Writing an entry\n // here would invent `#capabilities` for a plugin that never declared one, and expand a\n // deliberate shorthand string into the conditional form for no reason.\n const hasConditions = typeof existing?.source === 'object';\n if (environments.length === 0 && !hasConditions) {\n return;\n }\n\n const types = existing?.types ?? './dist/types/src/capabilities/index.d.ts';\n if (environments.length === 0) {\n pkg.imports = {\n ...pkg.imports,\n '#capabilities': { source: canonicalSource, types, default: './dist/lib/capabilities.mjs' },\n };\n fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\\n');\n return;\n }\n\n // Tools match several conditions and take the first key that matches, so a condition goes\n // before any broader one its tools also match: workerd and tauri builds both match `browser`.\n const FIRST = ['workerd', 'node'];\n const LAST = ['browser'];\n const rank = (env: string) =>\n FIRST.includes(env) ? FIRST.indexOf(env) : LAST.includes(env) ? FIRST.length + 1 : FIRST.length;\n const envOrder = [...environments].sort((a, b) => rank(a) - rank(b) || a.localeCompare(b));\n\n const source: Record<string, string> = {};\n for (const env of envOrder) {\n source[env] = `./src/capabilities/gen/${env}.ts`;\n }\n const entry: Record<string, unknown> = { source, types };\n for (const env of envOrder) {\n entry[env] = `./dist/lib/capabilities.${env}.mjs`;\n }\n\n pkg.imports = { ...pkg.imports, '#capabilities': entry };\n fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\\n');\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport path from 'node:path';\n\nimport { generate } from './generate.ts';\n\n// TODO(wittjosiah): Roll into dx cli? Once we stop shipping non-core plugins bundled into the cli\n// it might be light weight enough to support this use case.\nconst USAGE = `dx-plugin — plugin-authoring toolchain shipped with @dxos/app-framework.\n\nUsage: dx-plugin <command>\n\nCommands:\n gen [--dir <path>] [--verbose]\n Generate the headless #capabilities barrels (src/capabilities/gen/) from\n the canonical barrel's environments annotations, and sync the package.json\n #capabilities condition map. --verbose reports each generated file.`;\n\nconst gen = (args: string[]): void => {\n const dirFlagIndex = args.indexOf('--dir');\n const pluginDir = path.resolve(dirFlagIndex === -1 ? process.cwd() : args[dirFlagIndex + 1]);\n // Silent by default since it runs as a prebuild step for every plugin and floods build output.\n const verbose = args.includes('--verbose');\n const result = generate(pluginDir);\n if (!verbose) {\n return;\n }\n if (result.environments.length === 0) {\n // eslint-disable-next-line no-console\n console.log('dx-plugin gen: no environments annotations found; nothing generated.');\n return;\n }\n for (const file of result.files) {\n const values = file.values > 0 ? `, ${file.values} values` : '';\n // eslint-disable-next-line no-console\n console.log(\n `dx-plugin gen: ${path.relative(pluginDir, file.path)} (${file.included} modules, ${file.stubbed} stubs${values})`,\n );\n }\n};\n\nconst main = (): void => {\n const [command, ...args] = process.argv.slice(2);\n switch (command) {\n case 'gen': {\n gen(args);\n break;\n }\n default: {\n // eslint-disable-next-line no-console\n console.error(USAGE);\n process.exitCode = command === undefined || command === '--help' ? 0 : 1;\n }\n }\n};\n\nmain();\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"plugin-cli.mjs","names":["nodeCreateRequire","path","fs","nodeCreateRequire"],"sources":["../../src/plugin-cli/ts-util.ts","../../src/plugin-cli/maker-defaults.ts","../../src/plugin-cli/barrel.ts","../../src/plugin-cli/generate.ts","../../src/plugin-cli/main.ts"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport fs from 'node:fs';\nimport { createRequire as nodeCreateRequire } from 'node:module';\nimport path from 'node:path';\n\n// The tool operates on the consumer's TypeScript source, so it borrows an existing compiler-API\n// install instead of adding a heavyweight runtime dependency to app-framework that every browser\n// consumer would download.\n//\n// `@typescript/typescript6` first: the `typescript` specifier now resolves to the 7.x native\n// preview, which ships only `version` — no `createSourceFile`, no `ScriptTarget`. Resolution\n// succeeding therefore proves nothing, so each candidate is probed for the API actually used here\n// and skipped when it is absent; the same package the protobuf compiler imports for this reason.\nconst TYPESCRIPT_CANDIDATES = ['@typescript/typescript6', 'typescript'] as const;\n\nconst resolveTypescript = (): typeof import('@typescript/typescript6') => {\n const bases = [path.join(process.cwd(), 'package.json'), import.meta.url];\n for (const base of bases) {\n for (const specifier of TYPESCRIPT_CANDIDATES) {\n try {\n const module = nodeCreateRequire(base)(specifier);\n if (typeof module?.createSourceFile === 'function' && module.ScriptTarget) {\n return module;\n }\n } catch {\n continue;\n }\n }\n }\n throw new Error(\n `dx-plugin needs a TypeScript compiler API: install one of ${TYPESCRIPT_CANDIDATES.join(' or ')} in the target package or workspace.`,\n );\n};\n\nexport const ts = resolveTypescript();\n\ntype SourceFile = import('@typescript/typescript6').SourceFile;\ntype Node = import('@typescript/typescript6').Node;\ntype Statement = import('@typescript/typescript6').Statement;\ntype Expression = import('@typescript/typescript6').Expression;\n\n/** Parse a file into a ts.SourceFile, or null if it doesn't exist. */\nexport const parseFile = (filePath: string): SourceFile | null => {\n if (!fs.existsSync(filePath)) {\n return null;\n }\n const text = fs.readFileSync(filePath, 'utf8');\n return ts.createSourceFile(filePath, text, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);\n};\n\n/** Full source text of a node, as written (not re-printed). */\nexport const nodeText = (sourceFile: SourceFile, node: Node): string =>\n sourceFile.text.slice(node.getStart(sourceFile), node.getEnd());\n\n/** Flattened text of a member-access chain, e.g. `AppCapability.schema`. */\nexport const calleeText = (sourceFile: SourceFile, expr: Expression): string => {\n if (ts.isIdentifier(expr)) {\n return expr.text;\n }\n if (ts.isPropertyAccessExpression(expr)) {\n return `${calleeText(sourceFile, expr.expression)}.${expr.name.text}`;\n }\n return nodeText(sourceFile, expr);\n};\n\n/** Statement text including the comments directly above it — sliced verbatim into generated barrels. */\nexport const statementTextWithLeadingComments = (sourceFile: SourceFile, statement: Statement): string => {\n const fullStart = statement.getFullStart();\n const start = statement.getStart(sourceFile);\n const leading = sourceFile.text.slice(fullStart, start).replace(/^\\s*\\n+/, '');\n const body = sourceFile.text.slice(start, statement.getEnd());\n return (leading + body).trimEnd();\n};\n\nexport type ExportConst = {\n name: string;\n statement: Statement;\n initializer: Expression;\n};\n\n/** All `export const NAME = ...` at top level. */\nexport const topLevelExportConsts = (sourceFile: SourceFile): ExportConst[] => {\n const out: ExportConst[] = [];\n for (const stmt of sourceFile.statements) {\n if (!ts.isVariableStatement(stmt)) {\n continue;\n }\n if (!stmt.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword)) {\n continue;\n }\n for (const decl of stmt.declarationList.declarations) {\n if (!ts.isIdentifier(decl.name) || !decl.initializer) {\n continue;\n }\n out.push({ name: decl.name.text, statement: stmt, initializer: decl.initializer });\n }\n }\n return out;\n};\n\nexport type LocalDeclaration = {\n name: string;\n text: string;\n};\n\n/**\n * Top-level declarations a file keeps to itself — `const` and `function` without `export`. A kept\n * module statement can reference one (a helper the barrel author factored out), and it has to\n * travel with the statement or the generated barrel will not compile.\n */\nexport const topLevelLocalDeclarations = (sourceFile: SourceFile): LocalDeclaration[] => {\n const out: LocalDeclaration[] = [];\n const exported = (stmt: Statement): boolean =>\n (ts.canHaveModifiers(stmt) ? ts.getModifiers(stmt) : undefined)?.some(\n (modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword,\n ) ?? false;\n\n for (const stmt of sourceFile.statements) {\n if (exported(stmt)) {\n continue;\n }\n if (ts.isVariableStatement(stmt)) {\n for (const decl of stmt.declarationList.declarations) {\n if (ts.isIdentifier(decl.name)) {\n out.push({ name: decl.name.text, text: statementTextWithLeadingComments(sourceFile, stmt) });\n }\n }\n } else if (\n (ts.isFunctionDeclaration(stmt) || ts.isTypeAliasDeclaration(stmt) || ts.isInterfaceDeclaration(stmt)) &&\n stmt.name\n ) {\n out.push({ name: stmt.name.text, text: statementTextWithLeadingComments(sourceFile, stmt) });\n }\n }\n return out;\n};\n\nexport type ExportDeclarationEntry =\n | { kind: 'star'; moduleSpecifier: string | null }\n | { kind: 'named'; isTypeOnly: boolean; localName: string; exportedName: string; moduleSpecifier: string | null };\n\n/** All `export * from '...'` / `export { A as B } from '...'` entries. */\nexport const topLevelExportDeclarations = (sourceFile: SourceFile): ExportDeclarationEntry[] => {\n const out: ExportDeclarationEntry[] = [];\n for (const stmt of sourceFile.statements) {\n if (!ts.isExportDeclaration(stmt)) {\n continue;\n }\n const moduleSpecifier =\n stmt.moduleSpecifier && ts.isStringLiteral(stmt.moduleSpecifier) ? stmt.moduleSpecifier.text : null;\n if (stmt.exportClause === undefined) {\n out.push({ kind: 'star', moduleSpecifier });\n } else if (ts.isNamedExports(stmt.exportClause)) {\n for (const el of stmt.exportClause.elements) {\n out.push({\n kind: 'named',\n isTypeOnly: stmt.isTypeOnly || el.isTypeOnly,\n localName: (el.propertyName ?? el.name).text,\n exportedName: el.name.text,\n moduleSpecifier,\n });\n }\n }\n }\n return out;\n};\n\n/** Resolve a relative import specifier to a file on disk. */\nexport const resolveRelativeModule = (fromDir: string, spec: string): string | null => {\n if (!spec.startsWith('.')) {\n return null;\n }\n const base = path.resolve(fromDir, spec);\n // The specifier may already carry its extension (`./foo/index.ts`) — resolve it directly rather\n // than appending another one on top, which would never exist on disk.\n if (/\\.tsx?$/.test(base)) {\n return fs.existsSync(base) ? base : null;\n }\n const candidates = [`${base}.ts`, `${base}.tsx`, path.join(base, 'index.ts'), path.join(base, 'index.tsx')];\n return candidates.find((candidate) => fs.existsSync(candidate)) ?? null;\n};\n\nexport type ImportDeclarationEntry = {\n text: string;\n boundNames: Set<string>;\n specifier: string;\n /** Whole-clause `import type`, distinct from a per-element `type` modifier. */\n isTypeOnly: boolean;\n defaultName: string | null;\n namespaceName: string | null;\n /** Named bindings as written, e.g. `Foo`, `Foo as Bar`, `type Foo`. */\n named: string[];\n};\n\n/** Every top-level import declaration, with the local identifiers it binds. */\nexport const topLevelImportDeclarations = (sourceFile: SourceFile): ImportDeclarationEntry[] => {\n const out: ImportDeclarationEntry[] = [];\n for (const stmt of sourceFile.statements) {\n if (!ts.isImportDeclaration(stmt) || !stmt.importClause) {\n continue;\n }\n const boundNames = new Set<string>();\n const clause = stmt.importClause;\n if (clause.name) {\n boundNames.add(clause.name.text);\n }\n if (clause.namedBindings) {\n if (ts.isNamespaceImport(clause.namedBindings)) {\n boundNames.add(clause.namedBindings.name.text);\n } else if (ts.isNamedImports(clause.namedBindings)) {\n for (const el of clause.namedBindings.elements) {\n boundNames.add(el.name.text);\n }\n }\n }\n const named: string[] = [];\n let namespaceName: string | null = null;\n if (clause.namedBindings) {\n if (ts.isNamespaceImport(clause.namedBindings)) {\n namespaceName = clause.namedBindings.name.text;\n } else if (ts.isNamedImports(clause.namedBindings)) {\n for (const el of clause.namedBindings.elements) {\n named.push(nodeText(sourceFile, el));\n }\n }\n }\n out.push({\n text: nodeText(sourceFile, stmt),\n boundNames,\n specifier: ts.isStringLiteralLike(stmt.moduleSpecifier) ? stmt.moduleSpecifier.text : '',\n isTypeOnly: clause.isTypeOnly,\n defaultName: clause.name?.text ?? null,\n namespaceName,\n named,\n });\n }\n return out;\n};\n\n/**\n * Free identifiers referenced in a standalone snippet. Skips member-access property names and\n * non-computed object keys; otherwise over-collects — harmless, since callers only test membership\n * against known import bindings.\n */\nexport const collectFreeIdentifiers = (snippet: string): Set<string> => {\n const sf = ts.createSourceFile('snippet.tsx', snippet, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);\n const names = new Set<string>();\n const isSkipped = (node: Node): boolean => {\n const parent = node.parent;\n if (!parent) {\n return false;\n }\n if (ts.isPropertyAccessExpression(parent) && parent.name === node) {\n return true;\n }\n if (\n (ts.isPropertyAssignment(parent) ||\n ts.isPropertySignature(parent) ||\n ts.isMethodDeclaration(parent) ||\n ts.isMethodSignature(parent)) &&\n parent.name === node\n ) {\n return true;\n }\n return false;\n };\n const visit = (node: Node): void => {\n if (ts.isIdentifier(node) && !isSkipped(node)) {\n names.add(node.text);\n }\n ts.forEachChild(node, visit);\n };\n visit(sf);\n return names;\n};\n\n/**\n * Rewrite every relative module specifier in a snippet (static `from '...'` and dynamic\n * `import('...')`) so text authored in `originDir` stays correct when emitted into `outDir`.\n */\n/** Re-bases one relative module specifier from `originDir` to `outDir`; absolute ones pass through. */\nexport const rebaseSpecifier = (specifier: string, originDir: string, outDir: string): string => {\n if (!specifier.startsWith('.')) {\n return specifier;\n }\n const next = path.relative(outDir, path.resolve(originDir, specifier)).split(path.sep).join('/');\n return next.startsWith('.') ? next : `./${next}`;\n};\n\nexport const rewriteRelativeSpecifiers = (snippet: string, originDir: string, outDir: string): string => {\n const sf = ts.createSourceFile('snippet.tsx', snippet, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);\n const edits: Array<{ start: number; end: number; text: string }> = [];\n const rewrite = (literal: import('@typescript/typescript6').StringLiteral): void => {\n if (!literal.text.startsWith('.')) {\n return;\n }\n const absolute = path.resolve(originDir, literal.text);\n let next = path.relative(outDir, absolute).split(path.sep).join('/');\n if (!next.startsWith('.')) {\n next = `./${next}`;\n }\n const quote = snippet[literal.getStart(sf)];\n edits.push({ start: literal.getStart(sf), end: literal.getEnd(), text: `${quote}${next}${quote}` });\n };\n const visit = (node: Node): void => {\n if (\n (ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) &&\n node.moduleSpecifier &&\n ts.isStringLiteral(node.moduleSpecifier)\n ) {\n rewrite(node.moduleSpecifier);\n }\n if (\n ts.isCallExpression(node) &&\n node.expression.kind === ts.SyntaxKind.ImportKeyword &&\n node.arguments.length === 1 &&\n ts.isStringLiteral(node.arguments[0])\n ) {\n rewrite(node.arguments[0]);\n }\n ts.forEachChild(node, visit);\n };\n visit(sf);\n let result = snippet;\n for (const edit of edits.sort((a, b) => b.start - a.start)) {\n result = result.slice(0, edit.start) + edit.text + result.slice(edit.end);\n }\n return result;\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport * as fs from 'node:fs';\nimport { createRequire as nodeCreateRequire } from 'node:module';\nimport * as path from 'node:path';\n\nimport { parseFile, ts } from './ts-util.ts';\n\n/**\n * Per-family condition defaults, resolved from the module a barrel imports its makers from.\n *\n * The generator parses barrels rather than executing them, so it reads each maker's default from\n * the maker's own declaration: the `environments` literal it passes to `moduleMaker`, or the one\n * it falls back to as `options?.environments ?? [...]`. There is no second copy to drift.\n */\nexport type MakerDefaults = {\n /** Conditions for `<namespace>.<maker>`, or null when the module declares no default for it. */\n lookup: (namespace: string | null, maker: string) => readonly string[] | null;\n};\n\n/**\n * Resolves a module specifier to a source file: relative paths directly, bare package subpaths via\n * the package's own `exports` map, preferring the `source` condition (the in-workspace TypeScript)\n * and falling back to `import` (a published package's built JS, which the TS parser also reads).\n */\nconst resolveModuleFile = (fromDir: string, spec: string): string | null => {\n if (spec.startsWith('.')) {\n const base = path.resolve(fromDir, spec);\n const candidates = [`${base}.ts`, `${base}.tsx`, path.join(base, 'index.ts'), path.join(base, 'index.tsx')];\n return candidates.find((candidate) => fs.existsSync(candidate)) ?? null;\n }\n\n const match = /^(@[^/]+\\/[^/]+|[^@][^/]*)(\\/.*)?$/.exec(spec);\n if (!match) {\n return null;\n }\n const [, pkgName, subpath = '.'] = match;\n\n let pkgJsonPath: string;\n try {\n pkgJsonPath = nodeCreateRequire(path.join(fromDir, 'noop.js')).resolve(`${pkgName}/package.json`);\n } catch {\n return null;\n }\n const pkgDir = path.dirname(pkgJsonPath);\n const entry = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8'))?.exports?.[subpath === '.' ? '.' : `.${subpath}`];\n const target = typeof entry === 'string' ? entry : (entry?.source ?? entry?.import);\n if (typeof target !== 'string') {\n return null;\n }\n const resolved = path.join(pkgDir, target);\n return fs.existsSync(resolved) ? resolved : null;\n};\n\n/**\n * Every `environments` literal a maker module declares, keyed by the exported maker's name.\n *\n * Two shapes occur, and both are the maker stating its own default: `moduleMaker(name, tag, {\n * environments: [...] })` for the loader-based families, and `options?.environments ?? [...]`\n * inside the value-based helpers. Taking the right operand of the `??` reads the fallback rather\n * than the caller's override, which is exactly the default being sought.\n */\nconst readMakerDefaults = (filePath: string): Map<string, readonly string[]> | null => {\n const source = parseFile(filePath);\n if (!source) {\n return null;\n }\n\n const out = new Map<string, readonly string[]>();\n for (const stmt of source.statements) {\n if (!ts.isVariableStatement(stmt)) {\n continue;\n }\n for (const decl of stmt.declarationList.declarations) {\n if (!ts.isIdentifier(decl.name) || !decl.initializer) {\n continue;\n }\n const found = findEnvironments(decl.initializer);\n if (found) {\n out.set(decl.name.text, found);\n }\n }\n }\n return out.size > 0 ? out : null;\n};\n\n/** First `environments:` literal reachable in an expression, unwrapping a `??` fallback. */\nconst findEnvironments = (node: import('@typescript/typescript6').Node): readonly string[] | null => {\n let found: readonly string[] | null = null;\n const visit = (child: import('@typescript/typescript6').Node): void => {\n if (found) {\n return;\n }\n if (ts.isPropertyAssignment(child) && ts.isIdentifier(child.name) && child.name.text === 'environments') {\n let value: import('@typescript/typescript6').Node = child.initializer;\n if (ts.isBinaryExpression(value) && value.operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken) {\n value = value.right;\n }\n if (ts.isArrayLiteralExpression(value)) {\n found = value.elements.filter(ts.isStringLiteralLike).map((element) => element.text);\n return;\n }\n }\n ts.forEachChild(child, visit);\n };\n visit(node);\n return found;\n};\n\n/**\n * Builds the default lookup for one barrel, from the maker modules it imports. Only namespace\n * imports carry defaults: a maker family is addressed as `<namespace>.<maker>`, which is how the\n * repo imports them (`import * as AppCapability from '@dxos/app-toolkit/AppCapability'`).\n */\nexport const makerDefaults = (barrelPath: string): MakerDefaults => {\n const source = parseFile(barrelPath);\n const byNamespace = new Map<string, Map<string, readonly string[]>>();\n if (source) {\n const barrelDir = path.dirname(barrelPath);\n for (const { namespace, specifier } of namespaceImports(source)) {\n const file = resolveModuleFile(barrelDir, specifier);\n const defaults = file && readMakerDefaults(file);\n if (defaults) {\n byNamespace.set(namespace, defaults);\n }\n }\n }\n return {\n lookup: (namespace, maker) => (namespace ? (byNamespace.get(namespace)?.get(maker) ?? null) : null),\n };\n};\n\n/** Namespace imports (`import * as X from '...'`) with the specifier each binds. */\nconst namespaceImports = (\n source: import('@typescript/typescript6').SourceFile,\n): { namespace: string; specifier: string }[] => {\n const out: { namespace: string; specifier: string }[] = [];\n for (const stmt of source.statements) {\n if (\n !ts.isImportDeclaration(stmt) ||\n !stmt.importClause?.namedBindings ||\n !ts.isNamespaceImport(stmt.importClause.namedBindings) ||\n !ts.isStringLiteralLike(stmt.moduleSpecifier)\n ) {\n continue;\n }\n out.push({ namespace: stmt.importClause.namedBindings.name.text, specifier: stmt.moduleSpecifier.text });\n }\n return out;\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport path from 'node:path';\n\nimport { type MakerDefaults, makerDefaults } from './maker-defaults.ts';\nimport {\n type ExportConst,\n calleeText,\n nodeText,\n parseFile,\n resolveRelativeModule,\n statementTextWithLeadingComments,\n topLevelExportConsts,\n topLevelExportDeclarations,\n ts,\n} from './ts-util.ts';\n\nexport type BarrelMember = {\n name: string;\n /** `maker-call` members are module declarations; anything else is a helper/value export. */\n kind: 'maker-call' | 'non-call-initializer';\n /**\n * Conditions this module is split out for: the call site's own `environments` literal, else the\n * default its maker family declares. Null means neither applies, and the module is treated as\n * isomorphic — every generated variant carries it.\n */\n environments: readonly string[] | null;\n /** File the declaration statement actually lives in (may differ from the barrel via re-exports). */\n sourceFile: string;\n statementText: string;\n};\n\n/**\n * Parses a canonical capabilities barrel into exported-name -> member, resolving one level of\n * `export * from` / `export { X } from` indirection (both occur in real plugin barrels).\n */\nexport const parseBarrel = (\n filePath: string,\n defaults: MakerDefaults = makerDefaults(filePath),\n): Map<string, BarrelMember> => {\n const members = new Map<string, BarrelMember>();\n const sourceFile = parseFile(filePath);\n if (!sourceFile) {\n return members;\n }\n\n for (const entry of topLevelExportConsts(sourceFile)) {\n members.set(entry.name, describeMember(sourceFile, entry, filePath, defaults));\n }\n\n for (const exp of topLevelExportDeclarations(sourceFile)) {\n if (exp.kind === 'star') {\n if (!exp.moduleSpecifier) {\n continue;\n }\n const target = resolveRelativeModule(path.dirname(filePath), exp.moduleSpecifier);\n if (!target) {\n continue;\n }\n for (const [name, member] of parseBarrel(target)) {\n members.set(name, member);\n }\n } else if (!exp.isTypeOnly && exp.moduleSpecifier) {\n const target = resolveRelativeModule(path.dirname(filePath), exp.moduleSpecifier);\n if (!target) {\n continue;\n }\n const found = parseBarrel(target).get(exp.localName);\n if (found) {\n members.set(exp.exportedName, found);\n }\n }\n }\n\n return members;\n};\n\nconst describeMember = (\n sourceFile: import('@typescript/typescript6').SourceFile,\n entry: ExportConst,\n filePath: string,\n defaults: MakerDefaults,\n): BarrelMember => {\n const statementText = statementTextWithLeadingComments(sourceFile, entry.statement);\n if (!ts.isCallExpression(entry.initializer)) {\n return { name: entry.name, kind: 'non-call-initializer', environments: null, sourceFile: filePath, statementText };\n }\n return {\n name: entry.name,\n kind: 'maker-call',\n environments: resolveEnvironments(sourceFile, entry.initializer, defaults),\n sourceFile: filePath,\n statementText,\n };\n};\n\n/**\n * A module's conditions: its own `environments` literal if it declares one, else the default its\n * maker family declares. Only the call site can narrow or widen a family — that is the whole point\n * of the family default, so a genuine exception stays a one-line annotation at the exception.\n */\nconst resolveEnvironments = (\n sourceFile: import('@typescript/typescript6').SourceFile,\n call: import('@typescript/typescript6').CallExpression,\n defaults: MakerDefaults,\n): readonly string[] | null => {\n const declared = readEnvironments(sourceFile, call);\n if (declared) {\n return declared;\n }\n const callee = call.expression;\n return ts.isPropertyAccessExpression(callee) && ts.isIdentifier(callee.expression)\n ? defaults.lookup(callee.expression.text, callee.name.text)\n : null;\n};\n\n/**\n * Reads the `environments: ['...']` literal from whichever argument of the maker call is an\n * object literal carrying it — covers maker options bags, `lazyModule`/`inlineModule` specs, and\n * the value-based helpers' options. A computed (non-literal) value is a hard error: the generator\n * is the only consumer and would silently mis-classify the module.\n */\nconst readEnvironments = (\n sourceFile: import('@typescript/typescript6').SourceFile,\n call: import('@typescript/typescript6').CallExpression,\n): readonly string[] | null => {\n for (const arg of call.arguments) {\n if (!ts.isObjectLiteralExpression(arg)) {\n continue;\n }\n for (const prop of arg.properties) {\n if (!ts.isPropertyAssignment(prop) || !ts.isIdentifier(prop.name) || prop.name.text !== 'environments') {\n continue;\n }\n if (!ts.isArrayLiteralExpression(prop.initializer)) {\n throw new Error(\n `environments must be a literal array of string literals (${calleeText(sourceFile, call.expression)} at ${sourceFile.fileName})`,\n );\n }\n const values: string[] = [];\n for (const element of prop.initializer.elements) {\n if (!ts.isStringLiteralLike(element)) {\n throw new Error(\n `environments must be a literal array of string literals (${calleeText(sourceFile, call.expression)} at ${sourceFile.fileName}, saw ${nodeText(sourceFile, element)})`,\n );\n }\n values.push(element.text);\n }\n return values;\n }\n }\n return null;\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nimport { type BarrelMember, parseBarrel } from './barrel.ts';\nimport {\n collectFreeIdentifiers,\n parseFile,\n rebaseSpecifier,\n rewriteRelativeSpecifiers,\n topLevelImportDeclarations,\n topLevelLocalDeclarations,\n} from './ts-util.ts';\n\nexport type GenerateResult = {\n pluginDir: string;\n environments: string[];\n files: Array<{ path: string; included: number; stubbed: number; values: number }>;\n};\n\nconst findFirst = (dir: string, names: string[]): string | null =>\n names.map((name) => path.join(dir, name)).find((candidate) => fs.existsSync(candidate)) ?? null;\n\n/**\n * Generates the per-condition capability barrels for one plugin package:\n * `src/capabilities/gen/<env>.ts` for every condition named by an `environments` annotation in\n * the canonical barrel, plus the matching `#capabilities` condition map in package.json.\n */\nexport const generate = (pluginDir: string): GenerateResult => {\n const capabilitiesDir = path.join(pluginDir, 'src/capabilities');\n const indexPath = findFirst(capabilitiesDir, ['index.ts', 'index.tsx']);\n if (!indexPath) {\n throw new Error(`no capabilities barrel found at ${capabilitiesDir}/index.ts`);\n }\n\n const members = parseBarrel(indexPath);\n const moduleMembers = [...members.values()].filter((member) => member.kind === 'maker-call');\n const valueMembers = [...members.values()].filter((member) => member.kind === 'non-call-initializer');\n const environments = [...new Set(moduleMembers.flatMap((member) => member.environments ?? []))].sort();\n\n const genDir = path.join(capabilitiesDir, 'gen');\n const result: GenerateResult = { pluginDir, environments, files: [] };\n const canonicalSource = `./${path.relative(pluginDir, indexPath).split(path.sep).join('/')}`;\n fs.rmSync(genDir, { recursive: true, force: true });\n if (environments.length === 0) {\n // Still sync: dropping the last annotation has to retract the conditions too, or package.json\n // keeps pointing `#capabilities` at gen files that are no longer produced.\n syncPackageImports(pluginDir, environments, canonicalSource);\n return result;\n }\n fs.mkdirSync(genDir, { recursive: true });\n\n for (const env of environments) {\n const carries = (member: BarrelMember) => member.environments === null || member.environments.includes(env);\n const modules = moduleMembers.filter(carries);\n const included = [...valueMembers, ...modules];\n const stubbed = moduleMembers.filter((member) => !carries(member));\n\n const text = renderBarrel({ env, genDir, included, stubbed });\n const outPath = path.join(genDir, `${env}.ts`);\n fs.writeFileSync(outPath, text);\n result.files.push({\n path: outPath,\n included: modules.length,\n stubbed: stubbed.length,\n values: valueMembers.length,\n });\n }\n\n syncPackageImports(pluginDir, environments, canonicalSource);\n return result;\n};\n\ntype RenderOptions = {\n env: string;\n genDir: string;\n included: BarrelMember[];\n stubbed: BarrelMember[];\n};\n\nconst renderBarrel = ({ env, genDir, included, stubbed }: RenderOptions): string => {\n type Merged = { isTypeOnly: boolean; defaultName: string | null; namespaceName: string | null; named: Set<string> };\n const bySpecifier = new Map<string, Merged>();\n const importCache = new Map<string, ReturnType<typeof topLevelImportDeclarations>>();\n for (const member of included) {\n const free = collectFreeIdentifiers(member.statementText);\n if (!importCache.has(member.sourceFile)) {\n importCache.set(member.sourceFile, topLevelImportDeclarations(parseFile(member.sourceFile)!));\n }\n for (const decl of importCache.get(member.sourceFile)!) {\n if (![...decl.boundNames].some((name) => free.has(name))) {\n continue;\n }\n const spec = rebaseSpecifier(decl.specifier, path.dirname(member.sourceFile), genDir);\n const existing = bySpecifier.get(spec) ?? {\n isTypeOnly: decl.isTypeOnly,\n defaultName: null,\n namespaceName: null,\n named: new Set<string>(),\n };\n existing.isTypeOnly = existing.isTypeOnly && decl.isTypeOnly;\n existing.defaultName ??= decl.defaultName;\n existing.namespaceName ??= decl.namespaceName;\n for (const name of decl.named) {\n existing.named.add(name);\n }\n bySpecifier.set(spec, existing);\n }\n }\n\n const locals: Array<{ sourceFile: string; name: string; text: string }> = [];\n const localCache = new Map<string, ReturnType<typeof topLevelLocalDeclarations>>();\n for (const member of included) {\n if (!localCache.has(member.sourceFile)) {\n localCache.set(member.sourceFile, topLevelLocalDeclarations(parseFile(member.sourceFile)!));\n }\n const available = localCache.get(member.sourceFile)!;\n const taken = new Set(locals.filter((local) => local.sourceFile === member.sourceFile).map((l) => l.name));\n const pending = [...collectFreeIdentifiers(member.statementText)];\n while (pending.length > 0) {\n const name = pending.pop()!;\n if (taken.has(name)) {\n continue;\n }\n const decl = available.find((candidate) => candidate.name === name);\n if (!decl) {\n continue;\n }\n taken.add(name);\n locals.push({ sourceFile: member.sourceFile, name, text: decl.text });\n pending.push(...collectFreeIdentifiers(decl.text));\n }\n }\n\n for (const local of locals) {\n const free = collectFreeIdentifiers(local.text);\n for (const decl of importCache.get(local.sourceFile) ?? []) {\n if (![...decl.boundNames].some((name) => free.has(name))) {\n continue;\n }\n const spec = rebaseSpecifier(decl.specifier, path.dirname(local.sourceFile), genDir);\n const existing = bySpecifier.get(spec) ?? {\n isTypeOnly: decl.isTypeOnly,\n defaultName: null,\n namespaceName: null,\n named: new Set<string>(),\n };\n existing.isTypeOnly = existing.isTypeOnly && decl.isTypeOnly;\n existing.defaultName ??= decl.defaultName;\n existing.namespaceName ??= decl.namespaceName;\n for (const name of decl.named) {\n existing.named.add(name);\n }\n bySpecifier.set(spec, existing);\n }\n }\n\n const importTexts = new Set<string>();\n for (const [spec, merged] of bySpecifier) {\n const prefix = merged.isTypeOnly ? 'import type' : 'import';\n if (merged.namespaceName) {\n importTexts.add(`${prefix} * as ${merged.namespaceName} from '${spec}';`);\n }\n const clause = [merged.defaultName, merged.named.size > 0 ? `{ ${[...merged.named].sort().join(', ')} }` : null]\n .filter(Boolean)\n .join(', ');\n if (clause) {\n importTexts.add(`${prefix} ${clause} from '${spec}';`);\n }\n }\n\n const lines: string[] = [\n '//',\n '// Copyright 2026 DXOS.org',\n '//',\n '',\n `// GENERATED by dx-plugin — do not edit. Sliced from ../index.ts for the '${env}' condition.`,\n '',\n ];\n if (importTexts.size > 0) {\n lines.push(...sortImports([...importTexts]), '');\n }\n for (const local of locals) {\n lines.push(rewriteRelativeSpecifiers(local.text, path.dirname(local.sourceFile), genDir), '');\n }\n for (const member of included) {\n lines.push(rewriteRelativeSpecifiers(member.statementText, path.dirname(member.sourceFile), genDir), '');\n }\n for (const member of [...stubbed].sort((a, b) => a.name.localeCompare(b.name))) {\n lines.push(`export const ${member.name} = undefined;`);\n }\n return (\n lines\n .join('\\n')\n .replace(/\\n{3,}/g, '\\n\\n')\n .trimEnd() + '\\n'\n );\n};\n\n/** Sort import statements into the repo's groups: external, @dxos, `#` internal, relative. */\nconst sortImports = (imports: string[]): string[] => {\n const specifier = (text: string): string => /from\\s+['\"]([^'\"]+)['\"]/.exec(text)?.[1] ?? text;\n const group = (spec: string): number =>\n spec.startsWith('#') ? 2 : spec.startsWith('.') ? 3 : spec.startsWith('@dxos/') ? 1 : 0;\n const sorted = [...imports].sort((a, b) => {\n const specA = specifier(a);\n const specB = specifier(b);\n return group(specA) - group(specB) || specA.localeCompare(specB);\n });\n const out: string[] = [];\n let lastGroup: number | null = null;\n for (const text of sorted) {\n const currentGroup = group(specifier(text));\n if (lastGroup !== null && currentGroup !== lastGroup) {\n out.push('');\n }\n out.push(text);\n lastGroup = currentGroup;\n }\n return out;\n};\n\n/**\n * Rewrites the `#capabilities` entry of the plugin's package.json so each generated environment\n * resolves the generated barrel (source condition) and its built counterpart (dist condition).\n */\nconst syncPackageImports = (pluginDir: string, environments: string[], canonicalSource: string): void => {\n const pkgPath = path.join(pluginDir, 'package.json');\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));\n const existing = pkg.imports?.['#capabilities'];\n\n // Nothing to split and nothing already split: leave the manifest untouched. Writing an entry\n // here would invent `#capabilities` for a plugin that never declared one, and expand a\n // deliberate shorthand string into the conditional form for no reason.\n const hasConditions = typeof existing?.source === 'object';\n if (environments.length === 0 && !hasConditions) {\n return;\n }\n\n const types = existing?.types ?? './dist/types/src/capabilities/index.d.ts';\n if (environments.length === 0) {\n pkg.imports = {\n ...pkg.imports,\n '#capabilities': { source: canonicalSource, types, default: './dist/lib/capabilities.mjs' },\n };\n fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\\n');\n return;\n }\n\n // Tools match several conditions and take the first key that matches, so a condition goes\n // before any broader one its tools also match: workerd and tauri builds both match `browser`.\n const FIRST = ['workerd', 'node'];\n const LAST = ['browser'];\n const rank = (env: string) =>\n FIRST.includes(env) ? FIRST.indexOf(env) : LAST.includes(env) ? FIRST.length + 1 : FIRST.length;\n const envOrder = [...environments].sort((a, b) => rank(a) - rank(b) || a.localeCompare(b));\n\n const source: Record<string, string> = {};\n for (const env of envOrder) {\n source[env] = `./src/capabilities/gen/${env}.ts`;\n }\n const entry: Record<string, unknown> = { source, types };\n for (const env of envOrder) {\n entry[env] = `./dist/lib/capabilities.${env}.mjs`;\n }\n\n pkg.imports = { ...pkg.imports, '#capabilities': entry };\n fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\\n');\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport path from 'node:path';\n\nimport { generate } from './generate.ts';\n\n// TODO(wittjosiah): Roll into dx cli? Once we stop shipping non-core plugins bundled into the cli\n// it might be light weight enough to support this use case.\nconst USAGE = `dx-plugin — plugin-authoring toolchain shipped with @dxos/app-framework.\n\nUsage: dx-plugin <command>\n\nCommands:\n gen [--dir <path>] [--verbose]\n Generate the headless #capabilities barrels (src/capabilities/gen/) from\n the canonical barrel's environments annotations, and sync the package.json\n #capabilities condition map. --verbose reports each generated file.`;\n\nconst gen = (args: string[]): void => {\n const dirFlagIndex = args.indexOf('--dir');\n const pluginDir = path.resolve(dirFlagIndex === -1 ? process.cwd() : args[dirFlagIndex + 1]);\n // Silent by default since it runs as a prebuild step for every plugin and floods build output.\n const verbose = args.includes('--verbose');\n const result = generate(pluginDir);\n if (!verbose) {\n return;\n }\n if (result.environments.length === 0) {\n // eslint-disable-next-line no-console\n console.log('dx-plugin gen: no environments annotations found; nothing generated.');\n return;\n }\n for (const file of result.files) {\n const values = file.values > 0 ? `, ${file.values} values` : '';\n // eslint-disable-next-line no-console\n console.log(\n `dx-plugin gen: ${path.relative(pluginDir, file.path)} (${file.included} modules, ${file.stubbed} stubs${values})`,\n );\n }\n};\n\nconst main = (): void => {\n const [command, ...args] = process.argv.slice(2);\n switch (command) {\n case 'gen': {\n gen(args);\n break;\n }\n default: {\n // eslint-disable-next-line no-console\n console.error(USAGE);\n process.exitCode = command === undefined || command === '--help' ? 0 : 1;\n }\n }\n};\n\nmain();\n"],"mappings":"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"}
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { make, meta, layerIdb as storageLayer };
|
|
1
|
+
export { n as make, i as meta, r as storageLayer } from "../chunk-ProcessManagerPlugin.mjs";
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { EmptyHistoryError, make };
|
|
1
|
+
export { r as EmptyHistoryError, n as make } from "../../chunk-history-tracker.mjs";
|
|
@@ -1,47 +1 @@
|
|
|
1
|
-
|
|
2
|
-
//#region src/plugin-process-manager/history/undo-mapping.ts
|
|
3
|
-
var undo_mapping_exports = /* @__PURE__ */ __exportAll({
|
|
4
|
-
make: () => make,
|
|
5
|
-
resolveMessage: () => resolveMessage
|
|
6
|
-
});
|
|
7
|
-
/**
|
|
8
|
-
* Creates a type-safe undo mapping.
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```ts
|
|
12
|
-
* // Static message
|
|
13
|
-
* const mapping = UndoMapping.make({
|
|
14
|
-
* operation: DeleteThread,
|
|
15
|
-
* inverse: RestoreThread,
|
|
16
|
-
* deriveContext: (input, output) => ({
|
|
17
|
-
* thread: output.thread,
|
|
18
|
-
* anchor: output.anchor,
|
|
19
|
-
* }),
|
|
20
|
-
* message: ['thread deleted label', { ns: '@dxos/plugin-thread' }],
|
|
21
|
-
* });
|
|
22
|
-
*
|
|
23
|
-
* // Dynamic message based on input/output
|
|
24
|
-
* const mapping = UndoMapping.make({
|
|
25
|
-
* operation: RemoveObjects,
|
|
26
|
-
* inverse: RestoreObjects,
|
|
27
|
-
* deriveContext: (_input, output) => output,
|
|
28
|
-
* message: (input, _output) =>
|
|
29
|
-
* input.objects.length === 1
|
|
30
|
-
* ? ['object deleted label', { ns: getTypename(input.objects[0]) }]
|
|
31
|
-
* : ['objects deleted label', { ns: '@dxos/plugin-space' }],
|
|
32
|
-
* });
|
|
33
|
-
* ```
|
|
34
|
-
*/
|
|
35
|
-
var make = (props) => props;
|
|
36
|
-
/**
|
|
37
|
-
* Resolves a message provider to a Label.
|
|
38
|
-
*/
|
|
39
|
-
var resolveMessage = (message, input, output) => {
|
|
40
|
-
if (message === void 0) return;
|
|
41
|
-
if (typeof message === "function") return message(input, output);
|
|
42
|
-
return message;
|
|
43
|
-
};
|
|
44
|
-
//#endregion
|
|
45
|
-
export { make, resolveMessage, undo_mapping_exports as t };
|
|
46
|
-
|
|
47
|
-
//# sourceMappingURL=undo-mapping.mjs.map
|
|
1
|
+
export { t as make, n as resolveMessage } from "../../chunk-undo-mapping.mjs";
|
|
@@ -1,22 +1 @@
|
|
|
1
|
-
|
|
2
|
-
//#region src/plugin-process-manager/history/undo-registry.ts
|
|
3
|
-
var undo_registry_exports = /* @__PURE__ */ __exportAll({ make: () => make });
|
|
4
|
-
/**
|
|
5
|
-
* Creates an UndoRegistry that looks up inverse operations.
|
|
6
|
-
*/
|
|
7
|
-
var make = (getMappings) => {
|
|
8
|
-
const lookup = (operation) => {
|
|
9
|
-
const mapping = getMappings().find((m) => m.operation.meta.key === operation.meta.key);
|
|
10
|
-
if (!mapping) return;
|
|
11
|
-
return {
|
|
12
|
-
inverse: mapping.inverse,
|
|
13
|
-
deriveContext: mapping.deriveContext,
|
|
14
|
-
message: mapping.message
|
|
15
|
-
};
|
|
16
|
-
};
|
|
17
|
-
return { lookup };
|
|
18
|
-
};
|
|
19
|
-
//#endregion
|
|
20
|
-
export { make, undo_registry_exports as t };
|
|
21
|
-
|
|
22
|
-
//# sourceMappingURL=undo-registry.mjs.map
|
|
1
|
+
export { t as make } from "../../chunk-undo-registry.mjs";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { d as SurfaceManagerProvider, n as SurfaceComponent, t as SurfaceManager } from "../chunk-SurfaceManager.mjs";
|
|
2
2
|
import { t as PluginManagerContext } from "../chunk-context.mjs";
|
|
3
|
-
import { ReactContext } from "../
|
|
3
|
+
import { p as ReactContext } from "../chunk-capabilities.mjs";
|
|
4
4
|
import { PluginManagerProvider } from "../PluginManagerProvider.mjs";
|
|
5
5
|
import { t as topologicalSort } from "../chunk-helpers.mjs";
|
|
6
6
|
import { Fragment, useMemo } from "react";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.mjs","names":[],"sources":["../../../src/testing/react.tsx"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport { RegistryContext } from '@effect/atom-react/RegistryContext';\nimport { type RenderOptions, type RenderResult, render as rtlRender } from '@testing-library/react';\nimport React, { type FC, Fragment, type PropsWithChildren, type ReactNode, useMemo } from 'react';\n\nimport { ContextProtocolProvider } from '@dxos/web-context-react';\n\nimport { Capabilities } from '../common/index.ts';\nimport * as Role from '../common/Role.ts';\nimport { PluginManagerContext } from '../context.ts';\nimport { topologicalSort } from '../helpers.ts';\nimport { PluginManagerProvider } from '../ui/components/PluginManager/PluginManagerProvider.ts';\nimport { SurfaceComponent } from '../ui/components/Surface/SurfaceComponent.tsx';\nimport { SurfaceManager } from '../ui/components/Surface/SurfaceManager.ts';\nimport { SurfaceManagerProvider } from '../ui/components/Surface/SurfaceManagerContext.ts';\nimport { type TestHarness } from './harness.ts';\n\nexport type HarnessRenderOptions = Omit<RenderOptions, 'wrapper'> & {\n /** Additional providers to wrap around the harness tree (applied innermost first). */\n reactContexts?: FC<PropsWithChildren>[];\n};\n\n/**\n * Renders `ui` wrapped in the same provider tree as `useApp` plus every contributed\n * `Capabilities.ReactContext`.\n */\nexport const render = (harness: TestHarness, ui: ReactNode, options?: HarnessRenderOptions): RenderResult => {\n const { reactContexts = [], ...rest } = options ?? {};\n const Wrapper = ({ children }: PropsWithChildren) => (\n <HarnessProviders harness={harness} extra={reactContexts}>\n {children}\n </HarnessProviders>\n );\n return rtlRender(<>{ui}</>, { ...rest, wrapper: Wrapper });\n};\n\nexport type RenderSurfaceProps<TToken extends Role.Role<any>> = {\n type: TToken;\n data?: TToken extends Role.Role<infer D> ? D : never;\n limit?: number;\n fallback?: FC<{ error: Error; data?: any }>;\n placeholder?: ReactNode;\n};\n\n/**\n * Renders a `Surface` with the given role token/data inside the harness provider tree.\n */\nexport const renderSurface = <TToken extends Role.Role<any>>(\n harness: TestHarness,\n props: RenderSurfaceProps<TToken>,\n options?: HarnessRenderOptions,\n): RenderResult => {\n const { type, data, limit, fallback, placeholder } = props;\n return render(\n harness,\n <SurfaceComponent type={type} data={data as any} limit={limit} fallback={fallback} placeholder={placeholder} />,\n options,\n );\n};\n\ntype HarnessProvidersProps = PropsWithChildren<{\n harness: TestHarness;\n extra: FC<PropsWithChildren>[];\n}>;\n\nconst HarnessProviders = ({ harness, extra, children }: HarnessProvidersProps) => {\n const contributed = harness.getAll(Capabilities.ReactContext);\n const ContributedContext = composeContexts(contributed);\n const ExtraContext = composeExtra(extra);\n // Mirror useApp's provider stack (see SurfaceManager) so the unit-test render path matches the app.\n const surfaces = useMemo(() => new SurfaceManager(harness.manager.capabilities, harness.manager), [harness]);\n return (\n <PluginManagerProvider value={harness.manager}>\n <ContextProtocolProvider value={harness.manager} context={PluginManagerContext}>\n <RegistryContext.Provider value={harness.registry}>\n <SurfaceManagerProvider value={surfaces}>\n <ContributedContext>\n <ExtraContext>{children}</ExtraContext>\n </ContributedContext>\n </SurfaceManagerProvider>\n </RegistryContext.Provider>\n </ContextProtocolProvider>\n </PluginManagerProvider>\n );\n};\n\nconst composeContexts = (contexts: Capabilities.ReactContext[]): FC<PropsWithChildren> => {\n if (contexts.length === 0) {\n return Passthrough;\n }\n return topologicalSort(contexts)\n .map(({ context }) => context)\n .reduce((Acc, Next) => ({ children }: PropsWithChildren) => (\n <Acc>\n <Next>{children}</Next>\n </Acc>\n ));\n};\n\n// Composes in innermost-first order: the first context in the array wraps\n// `children` directly; subsequent contexts wrap the accumulator.\nconst composeExtra = (contexts: FC<PropsWithChildren>[]): FC<PropsWithChildren> => {\n if (contexts.length === 0) {\n return Passthrough;\n }\n return contexts.reduce<FC<PropsWithChildren>>(\n (Acc, Next) =>\n ({ children }: PropsWithChildren) => (\n <Next>\n <Acc>{children}</Acc>\n </Next>\n ),\n Passthrough,\n );\n};\n\nconst Passthrough: FC<PropsWithChildren> = ({ children }) => <Fragment>{children}</Fragment>;\n"],"mappings":";;;;;;;;;;;;;;;AA6BA,IAAa,UAAU,SAAsB,IAAe,YAAiD;CAC3G,MAAM,EAAE,gBAAgB,CAAC,GAAG,GAAG,SAAS,WAAW,CAAC;CACpD,MAAM,WAAW,EAAE,eACjB,oBAAC,kBAAD;EAA2B;EAAS,OAAO;EACxC;CACe,CAAA;CAEpB,
|
|
1
|
+
{"version":3,"file":"react.mjs","names":["rtlRender","_Fragment","Capabilities.ReactContext"],"sources":["../../../src/testing/react.tsx"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport { RegistryContext } from '@effect/atom-react/RegistryContext';\nimport { type RenderOptions, type RenderResult, render as rtlRender } from '@testing-library/react';\nimport React, { type FC, Fragment, type PropsWithChildren, type ReactNode, useMemo } from 'react';\n\nimport { ContextProtocolProvider } from '@dxos/web-context-react';\n\nimport { Capabilities } from '../common/index.ts';\nimport * as Role from '../common/Role.ts';\nimport { PluginManagerContext } from '../context.ts';\nimport { topologicalSort } from '../helpers.ts';\nimport { PluginManagerProvider } from '../ui/components/PluginManager/PluginManagerProvider.ts';\nimport { SurfaceComponent } from '../ui/components/Surface/SurfaceComponent.tsx';\nimport { SurfaceManager } from '../ui/components/Surface/SurfaceManager.ts';\nimport { SurfaceManagerProvider } from '../ui/components/Surface/SurfaceManagerContext.ts';\nimport { type TestHarness } from './harness.ts';\n\nexport type HarnessRenderOptions = Omit<RenderOptions, 'wrapper'> & {\n /** Additional providers to wrap around the harness tree (applied innermost first). */\n reactContexts?: FC<PropsWithChildren>[];\n};\n\n/**\n * Renders `ui` wrapped in the same provider tree as `useApp` plus every contributed\n * `Capabilities.ReactContext`.\n */\nexport const render = (harness: TestHarness, ui: ReactNode, options?: HarnessRenderOptions): RenderResult => {\n const { reactContexts = [], ...rest } = options ?? {};\n const Wrapper = ({ children }: PropsWithChildren) => (\n <HarnessProviders harness={harness} extra={reactContexts}>\n {children}\n </HarnessProviders>\n );\n return rtlRender(<>{ui}</>, { ...rest, wrapper: Wrapper });\n};\n\nexport type RenderSurfaceProps<TToken extends Role.Role<any>> = {\n type: TToken;\n data?: TToken extends Role.Role<infer D> ? D : never;\n limit?: number;\n fallback?: FC<{ error: Error; data?: any }>;\n placeholder?: ReactNode;\n};\n\n/**\n * Renders a `Surface` with the given role token/data inside the harness provider tree.\n */\nexport const renderSurface = <TToken extends Role.Role<any>>(\n harness: TestHarness,\n props: RenderSurfaceProps<TToken>,\n options?: HarnessRenderOptions,\n): RenderResult => {\n const { type, data, limit, fallback, placeholder } = props;\n return render(\n harness,\n <SurfaceComponent type={type} data={data as any} limit={limit} fallback={fallback} placeholder={placeholder} />,\n options,\n );\n};\n\ntype HarnessProvidersProps = PropsWithChildren<{\n harness: TestHarness;\n extra: FC<PropsWithChildren>[];\n}>;\n\nconst HarnessProviders = ({ harness, extra, children }: HarnessProvidersProps) => {\n const contributed = harness.getAll(Capabilities.ReactContext);\n const ContributedContext = composeContexts(contributed);\n const ExtraContext = composeExtra(extra);\n // Mirror useApp's provider stack (see SurfaceManager) so the unit-test render path matches the app.\n const surfaces = useMemo(() => new SurfaceManager(harness.manager.capabilities, harness.manager), [harness]);\n return (\n <PluginManagerProvider value={harness.manager}>\n <ContextProtocolProvider value={harness.manager} context={PluginManagerContext}>\n <RegistryContext.Provider value={harness.registry}>\n <SurfaceManagerProvider value={surfaces}>\n <ContributedContext>\n <ExtraContext>{children}</ExtraContext>\n </ContributedContext>\n </SurfaceManagerProvider>\n </RegistryContext.Provider>\n </ContextProtocolProvider>\n </PluginManagerProvider>\n );\n};\n\nconst composeContexts = (contexts: Capabilities.ReactContext[]): FC<PropsWithChildren> => {\n if (contexts.length === 0) {\n return Passthrough;\n }\n return topologicalSort(contexts)\n .map(({ context }) => context)\n .reduce((Acc, Next) => ({ children }: PropsWithChildren) => (\n <Acc>\n <Next>{children}</Next>\n </Acc>\n ));\n};\n\n// Composes in innermost-first order: the first context in the array wraps\n// `children` directly; subsequent contexts wrap the accumulator.\nconst composeExtra = (contexts: FC<PropsWithChildren>[]): FC<PropsWithChildren> => {\n if (contexts.length === 0) {\n return Passthrough;\n }\n return contexts.reduce<FC<PropsWithChildren>>(\n (Acc, Next) =>\n ({ children }: PropsWithChildren) => (\n <Next>\n <Acc>{children}</Acc>\n </Next>\n ),\n Passthrough,\n );\n};\n\nconst Passthrough: FC<PropsWithChildren> = ({ children }) => <Fragment>{children}</Fragment>;\n"],"mappings":";;;;;;;;;;;;;;;AA6BA,IAAa,UAAU,SAAsB,IAAe,YAAiD;CAC3G,MAAM,EAAE,gBAAgB,CAAC,GAAG,GAAG,SAAS,WAAW,CAAC;CACpD,MAAM,WAAW,EAAE,eACjB,oBAAC,kBAAD;EAA2B;EAAS,OAAO;EACxC;CACe,CAAA;CAEpB,OAAOA,SAAU,oBAAAC,YAAA,EAAA,UAAG,GAAK,CAAA,GAAG;EAAE,GAAG;EAAM,SAAS;CAAQ,CAAC;AAC3D;;;;AAaA,IAAa,iBACX,SACA,OACA,YACiB;CACjB,MAAM,EAAE,MAAM,MAAM,OAAO,UAAU,gBAAgB;CACrD,OAAO,OACL,SACA,oBAAC,kBAAD;EAAwB;EAAY;EAAoB;EAAiB;EAAuB;CAAc,CAAA,GAC9G,OACF;AACF;AAOA,IAAM,oBAAoB,EAAE,SAAS,OAAO,eAAsC;CAEhF,MAAM,qBAAqB,gBADP,QAAQ,OAAOC,YACQ,CAAW;CACtD,MAAM,eAAe,aAAa,KAAK;CAEvC,MAAM,WAAW,cAAc,IAAI,eAAe,QAAQ,QAAQ,cAAc,QAAQ,OAAO,GAAG,CAAC,OAAO,CAAC;CAC3G,OACE,oBAAC,uBAAD;EAAuB,OAAO,QAAQ;EACpC,UAAA,oBAAC,yBAAD;GAAyB,OAAO,QAAQ;GAAS,SAAS;GACxD,UAAA,oBAAC,gBAAgB,UAAjB;IAA0B,OAAO,QAAQ;IACvC,UAAA,oBAAC,wBAAD;KAAwB,OAAO;KAC7B,UAAA,oBAAC,oBAAD,EAAA,UACE,oBAAC,cAAD,EAAe,SAAuB,CAAA,EACpB,CAAA;IACE,CAAA;GACA,CAAA;EACH,CAAA;CACJ,CAAA;AAE3B;AAEA,IAAM,mBAAmB,aAAiE;CACxF,IAAI,SAAS,WAAW,GACtB,OAAO;CAET,OAAO,gBAAgB,QAAQ,CAAA,CAC5B,KAAK,EAAE,cAAc,OAAO,CAAA,CAC5B,QAAQ,KAAK,UAAU,EAAE,eACxB,oBAAC,KAAD,EAAA,UACE,oBAAC,MAAD,EAAO,SAAe,CAAA,EACnB,CAAA,CACN;AACL;AAIA,IAAM,gBAAgB,aAA6D;CACjF,IAAI,SAAS,WAAW,GACtB,OAAO;CAET,OAAO,SAAS,QACb,KAAK,UACH,EAAE,eACD,oBAAC,MAAD,EAAA,UACE,oBAAC,KAAD,EAAM,SAAc,CAAA,EAChB,CAAA,GAEV,WACF;AACF;AAEA,IAAM,eAAsC,EAAE,eAAe,oBAAC,UAAD,EAAW,SAAmB,CAAA"}
|
package/dist/lib/testing.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { eventKey, pluginStart } from "./
|
|
1
|
+
import { a as eventKey, d as pluginStart } from "./chunk-activation-event.mjs";
|
|
2
2
|
import { u as contribute } from "./chunk-capability.mjs";
|
|
3
|
-
import { expandContributions } from "./
|
|
4
|
-
import { Service,
|
|
3
|
+
import { n as expandContributions } from "./chunk-capability-manager.mjs";
|
|
4
|
+
import { c as Service, d as define, u as addModule, v as make, y as makeMeta } from "./chunk-plugin.mjs";
|
|
5
5
|
import { r as make$1 } from "./chunk-plugin-manager.mjs";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { f as ProcessManagerRuntime, l as OperationInvoker, m as ReactRoot, t as AtomRegistry, u as PluginManager } from "./chunk-capabilities.mjs";
|
|
7
|
+
import { a as Startup, n as Idle, t as CommandsRequested } from "./chunk-activation-events.mjs";
|
|
8
8
|
import { g as setDebug } from "./chunk-Surface.mjs";
|
|
9
9
|
import { T as useApp } from "./chunk-hooks.mjs";
|
|
10
10
|
import { useEffect, useMemo, useRef, useState } from "react";
|
package/dist/lib/testing.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.mjs","names":[],"sources":["../../src/testing/demand-gated.ts","../../src/testing/harness.ts","../../src/testing/operationCapture.ts","../../src/testing/service.ts","../../src/testing/withPluginManager.tsx","../../src/testing/withSurfaceDebug.tsx"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport { log } from '@dxos/log';\n\nimport { ActivationEvents } from '../common/index.ts';\nimport { ActivationEvent, type PluginManager } from '../core/index.ts';\n\n/**\n * Fires every activation event that a running app fires in response to demand: the\n * {@link ActivationEvents.Idle} wave, {@link ActivationEvents.CommandsRequested}, then each core\n * and enabled plugin's start event.\n *\n * Testing only, which is why it lives here rather than in the public `ActivationEvents` module.\n * A plugin's start fires when one of its surfaces renders, and that signal does not exist here: a\n * headless harness mounts no surfaces, and a story mounts exactly one in isolation, so both would\n * otherwise sit at whatever the startup pass activated and assert against modules that never load.\n *\n * The idle wave is included as an ordering barrier, not because the manager omits it — the\n * scheduler fires it from a forked daemon, so a caller that asserts as soon as `start()` returns\n * could otherwise race it. Firing here is idempotent against the wave guard either way.\n *\n * Fires unconditionally rather than tracking real demand, because narrowing it to the surfaces a\n * story mounts would starve any story whose subject depends on a sibling plugin's start-gated\n * contributions. The cost is that storybook cannot catch demand-gating regressions; only the\n * runtime modules-at-ready budget covers those.\n *\n * Sequential so the work trickles instead of saturating the main thread; per-plugin failures are\n * logged and skipped so one broken feature cannot stall the rest.\n */\nexport const activateDemandGatedModules = (\n manager: Pick<PluginManager.PluginManager, 'getCore' | 'getEnabled' | 'activate'>,\n): Effect.Effect<void> =>\n Effect.forEach(\n [\n ActivationEvents.Idle,\n // Demanded by a host building a command tree — a CLI binary or a terminal panel — and\n // nothing here is either.\n ActivationEvents.CommandsRequested,\n ...new Set([...manager.getCore(), ...manager.getEnabled()].map(ActivationEvent.pluginStart)),\n ],\n (event) =>\n manager\n .activate(event)\n .pipe(\n Effect.catch((error) =>\n Effect.sync(() => log.warn('activation event failed', { event: event.id, error: String(error) })),\n ),\n ),\n { discard: true },\n );\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Duration from 'effect/Duration';\nimport * as Effect from 'effect/Effect';\nimport * as PubSub from 'effect/PubSub';\nimport type * as Registry from 'effect/reactivity/AtomRegistry';\n\nimport type * as Operation from '@dxos/compute/Operation';\nimport * as EffectEx from '@dxos/effect/EffectEx';\nimport { invariant } from '@dxos/invariant';\n\nimport { ActivationEvents, Capabilities } from '../common/index.ts';\nimport { ActivationEvent, type Capability, type CapabilityManager, type Plugin, PluginManager } from '../core/index.ts';\nimport { activateDemandGatedModules } from './demand-gated.ts';\n\nexport type TestAppOptions = {\n /**\n * Plugins to register. Plugins whose `meta.profile.tags` includes `'system'` are treated as core\n * (force-enabled). For test convenience, plugins without a `'system'` tag are enabled by\n * default unless `enabled` is provided.\n */\n plugins: Plugin.Plugin[];\n /** Plugin ids that are enabled by default in addition to core. Defaults to all non-system plugin ids. */\n enabled?: string[];\n /** Additional activation events fired before Startup. */\n setupEvents?: ActivationEvent.ActivationEvent[];\n /**\n * Whether to automatically fire Startup during setup.\n * Defaults to true.\n */\n autoStart?: boolean;\n /**\n * Whether to register the PluginManager + AtomRegistry framework capabilities.\n * Defaults to true.\n */\n registerFrameworkCapabilities?: boolean;\n /**\n * Completes when the host is idle, gating the Idle wave. Off-browser the real wait resolves\n * immediately; pass `Effect.never` to keep idle-gated modules inactive, as on a browser cold boot.\n */\n whenIdle?: Effect.Effect<void>;\n /**\n * Resolves an id `manager.add` is given that names none of `plugins` — a URL, as a remote plugin\n * is added. Without it such an id fails, as an unknown plugin does.\n */\n pluginLoader?: PluginManager.ManagerOptions['pluginLoader'];\n};\n\n/**\n * A running plugin manager plus helpers for driving it in tests.\n */\nexport interface TestHarness {\n readonly manager: PluginManager.PluginManager;\n readonly capabilities: CapabilityManager.CapabilityManager;\n readonly registry: Registry.AtomRegistry;\n\n /** Activate the given event. Equivalent to `manager.activate(event)`. */\n fire(event: ActivationEvent.ActivationEvent | string): Promise<boolean>;\n /** Re-activate all modules that were activated by the given event. */\n reset(event: ActivationEvent.ActivationEvent | string): Promise<boolean>;\n\n /** Returns the first contributed capability for the given interface. Throws if none are present. */\n get<T>(iface: Capability.InterfaceDef<T>): T;\n /** Returns all contributed capabilities for the given interface. */\n getAll<T>(iface: Capability.InterfaceDef<T>): T[];\n /** Waits until at least one capability is contributed for the given interface. */\n waitForCapability<T>(iface: Capability.InterfaceDef<T>, opts?: { timeout?: number }): Promise<T>;\n /** Waits until the given activation event has completed. */\n waitForEvent(event: ActivationEvent.ActivationEvent | string, opts?: { timeout?: number }): Promise<void>;\n\n /** Invokes an operation through the `Capabilities.OperationInvoker` capability. */\n invoke<I, O>(op: Operation.Definition<I, O>, ...args: void extends I ? [input?: I] : [input: I]): Promise<O>;\n\n /**\n * Waits for `Capabilities.ProcessManagerRuntime` and runs the given effect on it.\n * Convenience around `waitForCapability(ProcessManagerRuntime).runPromise(effect)`.\n */\n runPromise<A, E>(\n effect: Effect.Effect<A, E, Capabilities.ProcessManagerRuntimeServices>,\n options?: { readonly timeout?: number; readonly signal?: AbortSignal },\n ): Promise<A>;\n\n enable(id: string): Promise<boolean>;\n disable(id: string): Promise<boolean>;\n\n /** Shuts down the underlying plugin manager. */\n dispose(): Promise<void>;\n\n /** Async-disposable support so tests can use `await using harness = ...`. */\n [Symbol.asyncDispose](): Promise<void>;\n}\n\nconst DEFAULT_TIMEOUT_MS = 5_000;\n\n/**\n * Creates a TestHarness with the same bootstrap sequence that `useApp` performs,\n * minus the React provider tree.\n *\n * For Node-only tests, this is enough to fire activation events, read\n * capabilities, and invoke operations.\n *\n * For React tests, pass the returned harness to `render` or `renderSurface`\n * from `@dxos/app-framework/testing-react`.\n *\n * TODO(wittjosiah): Consider running activation tests under a browser runner.\n * A plugin's `#capabilities` resolves to its `capabilities/node.ts` under the `node` export\n * condition, so a Node-run activation test asserts the NODE barrel's wiring, not the one the\n * app ships. The two are hand-maintained siblings and drifted silently — 35 modules were gated\n * in `index.ts` and ungated in `node.ts` (found 2026-08-04; a `CreateObject` module read as\n * startup-eager in tests while the browser build gated it correctly). They were realigned, but\n * nothing keeps them that way, and a lint rule is the wrong instrument: the barrels legitimately\n * diverge (node omits React surfaces entirely), so \"same gates\" is not a property that holds in\n * general. Running these tests in a browser runner exercises the shipped barrel directly and\n * makes the question moot.\n */\nexport const createTestApp = async (opts: TestAppOptions): Promise<TestHarness> => {\n const {\n plugins,\n enabled = plugins\n .filter(({ meta }) => !meta.profile.tags?.includes('system'))\n .map((plugin) => plugin.meta.profile.key),\n setupEvents = [],\n autoStart = true,\n registerFrameworkCapabilities = true,\n whenIdle,\n pluginLoader: fallbackLoader,\n } = opts;\n\n const pluginLoader = (id: string) => {\n const plugin = plugins.find((plugin) => plugin.meta.profile.key === id);\n if (!plugin && fallbackLoader) {\n return fallbackLoader(id);\n }\n return Effect.sync(() => {\n invariant(plugin, `Plugin not found: ${id}`);\n return { plugin };\n });\n };\n\n const manager = PluginManager.make({ pluginLoader, plugins, enabled, whenIdle });\n\n if (registerFrameworkCapabilities) {\n manager.capabilities.contribute({\n interface: Capabilities.PluginManager,\n implementation: manager,\n module: 'org.dxos.app-framework.plugin-manager',\n });\n manager.capabilities.contribute({\n interface: Capabilities.AtomRegistry,\n implementation: manager.registry,\n module: 'org.dxos.app-framework.atom-registry',\n });\n }\n\n if (autoStart) {\n try {\n await EffectEx.runAndForwardErrors(\n Effect.all([\n ...setupEvents.map((event) => manager.activate(event)),\n manager.activate(ActivationEvents.Startup),\n ]),\n );\n // In the app plugins start on demand (surface render), which a headless harness never\n // triggers — fire every start event before the test body runs so start-gated modules\n // are present.\n await EffectEx.runAndForwardErrors(activateDemandGatedModules(manager));\n } catch (err) {\n await EffectEx.runAndForwardErrors(manager.shutdown()).catch(() => undefined);\n throw err;\n }\n }\n\n return new TestHarnessImpl(manager);\n};\n\nclass TestHarnessImpl implements TestHarness {\n constructor(readonly manager: PluginManager.PluginManager) {}\n\n get capabilities(): CapabilityManager.CapabilityManager {\n return this.manager.capabilities;\n }\n\n get registry(): Registry.AtomRegistry {\n return this.manager.registry;\n }\n\n fire(event: ActivationEvent.ActivationEvent | string): Promise<boolean> {\n return EffectEx.runAndForwardErrors(this.manager.activate(event));\n }\n\n reset(event: ActivationEvent.ActivationEvent | string): Promise<boolean> {\n return EffectEx.runAndForwardErrors(this.manager.reset(event));\n }\n\n get<T>(iface: Capability.InterfaceDef<T>): T {\n return this.manager.capabilities.get(iface);\n }\n\n getAll<T>(iface: Capability.InterfaceDef<T>): T[] {\n return this.manager.capabilities.getAll(iface);\n }\n\n waitForCapability<T>(iface: Capability.InterfaceDef<T>, opts?: { timeout?: number }): Promise<T> {\n const timeout = opts?.timeout ?? DEFAULT_TIMEOUT_MS;\n return EffectEx.runAndForwardErrors(\n this.manager.capabilities.waitFor(iface).pipe(\n Effect.timeoutOrElse({\n duration: Duration.millis(timeout),\n orElse: () => Effect.fail(timeoutError(iface.identifier)),\n }),\n ),\n );\n }\n\n waitForEvent(event: ActivationEvent.ActivationEvent | string, opts?: { timeout?: number }): Promise<void> {\n const key = typeof event === 'string' ? event : ActivationEvent.eventKey(event);\n const timeout = opts?.timeout ?? DEFAULT_TIMEOUT_MS;\n\n const program = Effect.gen({ self: this }, function* () {\n const queue = yield* PubSub.subscribe(this.manager.activation);\n // Re-check after subscribing to avoid a race where the event fires\n // between the caller invoking this and the subscription being installed.\n if (this.manager.getEventsFired().includes(key)) {\n return;\n }\n while (true) {\n const message = yield* PubSub.take(queue);\n if (message.event === key && message.state === 'activated') {\n return;\n }\n }\n }).pipe(\n Effect.scoped,\n Effect.timeoutOrElse({\n duration: Duration.millis(timeout),\n orElse: () => Effect.fail(timeoutError(key)),\n }),\n );\n\n return EffectEx.runAndForwardErrors(program);\n }\n\n async invoke<I, O>(op: Operation.Definition<I, O>, ...args: [input?: I]): Promise<O> {\n const invoker = await this.waitForCapability(Capabilities.OperationInvoker);\n const result = await invoker.invokePromise(op as any, ...(args as [any]));\n if (result.error) {\n throw result.error;\n }\n return result.data as O;\n }\n\n async runPromise<A, E>(\n effect: Effect.Effect<A, E, Capabilities.ProcessManagerRuntimeServices>,\n options?: { readonly timeout?: number; readonly signal?: AbortSignal },\n ): Promise<A> {\n const runtime = await this.waitForCapability(Capabilities.ProcessManagerRuntime, { timeout: options?.timeout });\n return runtime.runPromise(effect, options?.signal ? { signal: options.signal } : undefined);\n }\n\n enable(id: string): Promise<boolean> {\n return EffectEx.runAndForwardErrors(this.manager.enable(id));\n }\n\n disable(id: string): Promise<boolean> {\n return EffectEx.runAndForwardErrors(this.manager.disable(id));\n }\n\n async dispose(): Promise<void> {\n await EffectEx.runAndForwardErrors(this.manager.shutdown());\n }\n\n [Symbol.asyncDispose](): Promise<void> {\n return this.dispose();\n }\n}\n\nconst timeoutError = (id: string) => new Error(`Timed out waiting for ${id}`);\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport type * as Operation from '@dxos/compute/Operation';\n\nimport { Capabilities } from '../common/index.ts';\nimport { Capability } from '../core/index.ts';\n\nexport type CapturedCall<I = unknown> = {\n /** The DXN key string of the invoked operation. */\n operationKey: string;\n /** The input passed to the operation. */\n input: I;\n};\n\ntype CapabilityManagerLike = {\n get: (cap: Capability.InterfaceDef<Capabilities.OperationInvoker>) => Capabilities.OperationInvoker;\n getAll: (cap: Capability.InterfaceDef<Capabilities.OperationInvoker>) => Capabilities.OperationInvoker[];\n};\n\nexport type OperationCapture = {\n /**\n * Wraps the real OperationInvoker from the given manager. Pass to\n * `withPluginManager({ capabilities: (m) => capture.wrap(m) })`.\n */\n wrap(manager: CapabilityManagerLike): Capability.AnyContribution[];\n /** Returns all recorded calls (mocked or real) for the given operation. */\n getCalls<I, O>(op: Operation.Definition<I, O>): CapturedCall<I>[];\n /** Clears all recorded calls (useful between play function steps). */\n reset(): void;\n};\n\n/**\n * Creates a capture that wraps the real `Capabilities.OperationInvoker`:\n *\n * - **Mocked operations** (declared in `mockedOperations`) are intercepted: the call is recorded\n * and returns `{ data: undefined }` without executing. Use this for side-effecting operations\n * you don't want to run in tests, such as `LayoutOperation.Open` (navigation).\n *\n * - **All other operations** are forwarded to the real invoker and still execute normally. The\n * call is still recorded so you can assert it was triggered even though it ran for real.\n *\n * Pass a `spyFn` wrapper (e.g. `fn` from `storybook/test`) to get Storybook Actions panel\n * integration and vi-style matchers on the recording.\n *\n * @example\n * ```ts\n * import { fn } from 'storybook/test';\n *\n * const capture = makeOperationCapture(\n * // These ops are mocked: captured but not executed.\n * [AssistantOperation.RunPromptInNewChat, LayoutOperation.Open],\n * fn,\n * );\n *\n * // Wire into withPluginManager:\n * capabilities: (manager) => capture.wrap(manager)\n *\n * // Assert in a play function:\n * const calls = capture.getCalls(AssistantOperation.RunPromptInNewChat);\n * expect(calls).toHaveLength(1);\n * expect(calls[0].input.prompt).toBe('Draft a new document');\n * ```\n *\n * @idiom org.dxos.app-framework.testing.operationCapture\n * applies: Storybook play-function tests for components that call plugin operations\n * instead-of: Loading every plugin whose operations the component triggers\n * uses: {@link makeOperationCapture}, {@link withPluginManager}\n */\nexport const makeOperationCapture = (\n mockedOperations: readonly Operation.Definition.Any[],\n spyFn?: (impl: (...args: any[]) => any) => any,\n): OperationCapture => {\n const calls: CapturedCall[] = [];\n\n const mockedKeys = new Set(mockedOperations.map((op) => String(op.meta.key)));\n\n const record = (op: Operation.Definition<any, any>, input?: unknown) => {\n calls.push({ operationKey: String(op.meta.key), input: input ?? {} });\n };\n\n const recordFn = spyFn ? spyFn(record) : record;\n\n return {\n wrap(manager) {\n // Use getAll to find the real invoker that was registered before our wrapper. manager.get\n // returns the last contribution (ours, once added), but getAll returns them all in order.\n // On first invocation (when activation is complete) we find the non-wrapper contribution.\n let real: Capabilities.OperationInvoker | undefined;\n const delegate = () => {\n if (!real) {\n const all = manager.getAll(Capabilities.OperationInvoker);\n real = all.find((inv) => inv !== wrapped);\n }\n return real;\n };\n\n const wrapped: Capabilities.OperationInvoker = {\n get invocations() {\n return delegate()!.invocations;\n },\n get pendingFollowups() {\n return delegate()!.pendingFollowups;\n },\n get awaitFollowups() {\n return delegate()!.awaitFollowups;\n },\n invoke: (op: Operation.Definition<any, any>, input?: unknown, ...rest: any[]) => {\n recordFn(op, input);\n if (mockedKeys.has(String(op.meta.key))) {\n return Effect.succeed(undefined as any);\n }\n return (delegate()!.invoke as any)(op, input, ...rest);\n },\n invokePromise: async (op: Operation.Definition<any, any>, input?: unknown, ...rest: any[]) => {\n recordFn(op, input);\n if (mockedKeys.has(String(op.meta.key))) {\n return { data: undefined };\n }\n return (delegate()!.invokePromise as any)(op, input, ...rest);\n },\n schedule: (op: Operation.Definition<any, any>, input?: unknown, ...rest: any[]) => {\n recordFn(op, input);\n if (mockedKeys.has(String(op.meta.key))) {\n return Effect.succeed(undefined);\n }\n return (delegate()!.schedule as any)(op, input, ...rest);\n },\n };\n\n return [Capability.contribute(Capabilities.OperationInvoker, wrapped)];\n },\n getCalls<I, O>(op: Operation.Definition<I, O>): CapturedCall<I>[] {\n const key = String(op.meta.key);\n return calls.filter((c) => c.operationKey === key) as CapturedCall<I>[];\n },\n reset() {\n calls.length = 0;\n },\n };\n};\n","//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\nimport * as Layer from 'effect/Layer';\n\nimport { invariant } from '@dxos/invariant';\n\nimport { ActivationEvents, Capabilities } from '../common/index.ts';\nimport { Plugin, PluginManager } from '../core/index.ts';\n\n/**\n * Creates a Plugin.Service layer from a list of plugins.\n * This is primarily used for testing.\n */\nexport const fromPlugins = (plugins: Plugin.Plugin[]) =>\n Layer.effect(\n Plugin.Service,\n Effect.gen(function* () {\n // TODO(wittjosiah): Try to dedupe logic between here, createCliApp and useApp.\n\n const pluginLoader = (id: string) =>\n Effect.sync(() => {\n const plugin = plugins.find((plugin) => plugin.meta.profile.key === id);\n invariant(plugin, `Plugin not found: ${id}`);\n return { plugin };\n });\n\n const manager = PluginManager.make({\n pluginLoader,\n plugins,\n enabled: plugins.map((plugin) => plugin.meta.profile.key),\n });\n\n manager.capabilities.contribute({\n interface: Capabilities.PluginManager,\n implementation: manager,\n module: 'org.dxos.app-framework.plugin-manager',\n });\n\n manager.capabilities.contribute({\n interface: Capabilities.AtomRegistry,\n implementation: manager.registry,\n module: 'org.dxos.app-framework.atom-registry',\n });\n\n yield* manager.activate(ActivationEvents.Startup);\n\n return manager;\n }),\n );\n","//\n// Copyright 2025 DXOS.org\n//\n\nimport { type Decorator, type StoryContext } from '@storybook/react-vite';\nimport * as Effect from 'effect/Effect';\nimport React, { type PropsWithChildren, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { raise } from '@dxos/debug';\nimport * as EffectEx from '@dxos/effect/EffectEx';\nimport { DXN } from '@dxos/keys';\nimport { ErrorFallback } from '@dxos/react-error-boundary';\nimport { useAsyncEffect } from '@dxos/react-hooks';\nimport { type MaybeProvider, getProviderValue } from '@dxos/util';\n\nimport { ActivationEvents, Capabilities } from '../common/index.ts';\nimport { type ActivationEvent, Capability, CapabilityManager, Plugin, PluginManager } from '../core/index.ts';\nimport { type UseAppOptions, useApp } from '../ui/index.ts';\nimport { activateDemandGatedModules } from './demand-gated.ts';\n\n/**\n * The fallback a crashed story renders, overridable per story via `withPluginManager({ fallback })`.\n * A global because importing `./testing` from the storybook preview drags the plugin core into every\n * project's dependency pre-bundle.\n */\ndeclare global {\n // eslint-disable-next-line no-var\n var __STORY_ERROR_FALLBACK__: NonNullable<UseAppOptions['fallback']> | undefined;\n}\n\n/**\n * Builds a plugin manager for test hosts. Stories go through {@link withPluginManager}; headless\n * hook tests use this directly to supply the `PluginManagerProvider` value their wrapper needs.\n */\nexport const setupPluginManager = ({\n capabilities,\n plugins = [],\n ...options\n}: UseAppOptions & Pick<WithPluginManagerOptions, 'capabilities'> = {}) => {\n // Auto-enable every non-system plugin so stories don't have to spell out\n // enablement. System-tagged plugins are force-enabled by the manager.\n const enabled = plugins\n .filter(({ meta }) => !meta.profile.tags?.includes('system'))\n .map(({ meta }) => meta.profile.key);\n const pluginManager = PluginManager.make({\n pluginLoader: () => raise(new Error('Not implemented')),\n plugins: [StoryPlugin, ...plugins],\n enabled,\n ...options,\n });\n\n // The framework capabilities a real host contributes, mirroring `createTestApp`. Without these\n // no MODULE provides `AtomRegistry`, so any module requiring it fails the dependency pass's\n // missing-provider check with nothing to wait for — reached as soon as a requiring module sits\n // on the startup pass (attention, graph, the process manager).\n pluginManager.capabilities.contribute({\n interface: Capabilities.PluginManager,\n implementation: pluginManager,\n module: 'org.dxos.app-framework.plugin-manager',\n });\n pluginManager.capabilities.contribute({\n interface: Capabilities.AtomRegistry,\n implementation: pluginManager.registry,\n module: 'org.dxos.app-framework.atom-registry',\n });\n\n if (capabilities) {\n // Fixtures hand us `Contribution`s (from `Capability.contribute`); expand them to the raw\n // interface/implementation entries the manager ingests — the same path module activation uses.\n CapabilityManager.expandContributions(getProviderValue(capabilities, pluginManager.capabilities)).forEach(\n (capability) => {\n pluginManager.capabilities.contribute({\n interface: capability.interface,\n implementation: capability.implementation,\n module: 'story',\n });\n },\n );\n }\n\n return pluginManager;\n};\n\ntype ManagedPluginManagerState = {\n fallback?: UseAppOptions['fallback'];\n fireEvents?: (ActivationEvent.ActivationEvent | string)[];\n pluginManager: PluginManager.PluginManager;\n setupEvents?: ActivationEvent.ActivationEvent[];\n storyId: string;\n};\n\nexport type WithPluginManagerOptions = UseAppOptions & {\n /** @deprecated */\n capabilities?: MaybeProvider<Capability.AnyContribution[], CapabilityManager.CapabilityManager>;\n /** @deprecated */\n fireEvents?: (ActivationEvent.ActivationEvent | string)[];\n};\n\nexport type WithPluginManagerInitializer<Args = void> =\n | WithPluginManagerOptions\n | ((context: StoryContext<Args>) => WithPluginManagerOptions);\n\nexport type PluginManagerHostProps = PropsWithChildren<{\n /** Keys the manager: a new id builds a new one, and the old one shuts down. */\n id: string;\n /** Read with `id`; a new value also rebuilds the manager, so memoize it. */\n options: WithPluginManagerOptions;\n}>;\n\n/**\n * Hosts `children` as the root of a plugin app built from `options`. The decorator form is\n * {@link withPluginManager}; this form lets one story host several apps, e.g. one per client.\n */\nexport const PluginManagerHost = ({ id, options, children }: PluginManagerHostProps) => {\n const [managerState, setManagerState] = useState<ManagedPluginManagerState>();\n // The root is contributed once per manager, so it reads the latest children rather than capturing them.\n const childrenRef = useRef(children);\n childrenRef.current = children;\n\n useEffect(() => {\n const pluginManager = setupPluginManager(options);\n const [capability] = CapabilityManager.expandContributions([\n Capability.contribute(Capabilities.ReactRoot, {\n id,\n root: () => <>{childrenRef.current}</>,\n }),\n ]);\n\n pluginManager.capabilities.contribute({\n interface: capability.interface,\n implementation: capability.implementation,\n module: 'org.dxos.app-framework.with-plugin-manager',\n });\n\n setManagerState({\n pluginManager,\n setupEvents: options.setupEvents,\n fireEvents: options.fireEvents,\n fallback: options.fallback,\n storyId: id,\n });\n\n return () => {\n pluginManager.capabilities.remove(capability.interface, capability.implementation);\n // A story switch tears down while the start-event trickle is still activating, which\n // interrupts the shutdown fiber — expected; real failures still surface.\n EffectEx.runDetached(pluginManager.shutdown());\n };\n }, [id, options]);\n\n // Avoid mounting useApp with a stale manager from the previous story.\n if (!managerState || managerState.storyId !== id) {\n return <></>;\n }\n\n return <WithPluginManagerApp {...managerState} />;\n};\n\n/**\n * Wraps a story with a plugin manager.\n * NOTE: This builds up and tears down the plugin manager on every render.\n */\nexport const withPluginManager = <Args,>(init: WithPluginManagerInitializer<Args> = {}): Decorator => {\n return (Story, context) => {\n const storyId = context.id;\n // Storybook replaces the full context object often, so the manager is keyed by story id.\n const options = useMemo(() => (typeof init === 'function' ? init(context as any) : init), [storyId, init]);\n\n return (\n <PluginManagerHost id={storyId} options={options}>\n <Story />\n </PluginManagerHost>\n );\n };\n};\n\nconst WithPluginManagerApp = ({\n fallback,\n fireEvents,\n pluginManager,\n setupEvents,\n storyId,\n}: ManagedPluginManagerState) => {\n // Gates the first render: rendering before the start events land lets a component read a\n // capability that has not been contributed yet, which strict `useCapability` throws on.\n const [activated, setActivated] = useState(false);\n\n // Fire deprecated events only after the effect-owned manager for this story exists.\n useAsyncEffect(\n async (controller) => {\n await Promise.all(fireEvents?.map((event) => pluginManager.activate(event)) ?? []);\n // In the app plugins start on demand (surface render), but stories render one surface in\n // isolation — fire every start event so start-gated modules are present regardless of\n // which plugin's surface the story exercises. A story switch shuts the manager down\n // mid-trickle, interrupting the activation fiber — expected; real failures still surface.\n EffectEx.runDetached(\n activateDemandGatedModules(pluginManager).pipe(\n // Interruption skips this, so a torn-down story never flips the gate.\n Effect.andThen(\n Effect.sync(() => {\n if (!controller.signal.aborted) {\n setActivated(true);\n }\n }),\n ),\n ),\n );\n },\n [fireEvents, pluginManager, storyId],\n );\n\n const App = useApp({\n pluginManager,\n setupEvents,\n fallback: fallback ?? globalThis.__STORY_ERROR_FALLBACK__ ?? ErrorFallback,\n });\n return activated ? <App /> : <></>;\n};\n\nconst storyMeta = Plugin.makeMeta({\n key: DXN.make('org.dxos.appFramework.story'),\n name: 'Story',\n tags: ['system'],\n});\n\n// No-op plugin to ensure there exists at least one plugin for the startup event.\n// This is necessary because `createApp` expects the startup event to complete before the app is ready.\nconst StoryPlugin = Plugin.define(storyMeta).pipe(\n Plugin.addModule({\n id: 'Story',\n activatesOn: ActivationEvents.Startup,\n activate: () => Effect.succeed([]),\n }),\n Plugin.make,\n)();\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport { type Decorator } from '@storybook/react-vite';\nimport React from 'react';\n\nimport { Surface } from '../ui/index.ts';\n\n/**\n * Storybook decorator that enables the surface debug overlays (`<dx-surface>` wrappers + boundary\n * badges) for the wrapped story. The flag is a `window` singleton, so it is (re)applied on every\n * render — enabling it on decorated stories and clearing it otherwise, so the setting never leaks\n * between stories. Prefer this over the `.storybook/preview` flag when the story must also render\n * under the aggregate root Storybook, which does not load a per-package preview.\n */\nexport const withSurfaceDebug =\n (enabled = true): Decorator =>\n (Story) => {\n Surface.setDebug(enabled);\n return <Story />;\n };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,IAAa,8BACX,YAEA,OAAO,QACL;CACE;CAGA;CACA,GAAG,IAAI,IAAI,CAAC,GAAG,QAAQ,QAAQ,GAAG,GAAG,QAAQ,WAAW,CAAC,CAAC,CAAC,IAAI,WAA2B,CAAC;AAC7F,IACC,UACC,QACG,SAAS,KAAK,CAAA,CACd,KACC,OAAO,OAAO,UACZ,OAAO,WAAW,IAAI,KAAK,2BAA2B;CAAE,OAAO,MAAM;CAAI,OAAO,OAAO,KAAK;AAAE,GAAA;CAAA,YAAA;CAAA,GAAA;CAAA,GAAA;CAAA,GAAA,KAAA;AAAA,CAAC,CAAC,CAClG,CACF,GACJ,EAAE,SAAS,KAAK,CAClB;;;;ACyCF,IAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;AAuB3B,IAAa,gBAAgB,OAAO,SAA+C;CACjF,MAAM,EACJ,SACA,UAAU,QACP,QAAQ,EAAE,WAAW,CAAC,KAAK,QAAQ,MAAM,SAAS,QAAQ,CAAC,CAAA,CAC3D,KAAK,WAAW,OAAO,KAAK,QAAQ,GAAG,GAC1C,cAAc,CAAC,GACf,YAAY,MACZ,gCAAgC,MAChC,UACA,cAAc,mBACZ;CAEJ,MAAM,gBAAgB,OAAe;EACnC,MAAM,SAAS,QAAQ,MAAM,WAAW,OAAO,KAAK,QAAQ,QAAQ,EAAE;EACtE,IAAI,CAAC,UAAU,gBACb,OAAO,eAAe,EAAE;EAE1B,OAAO,OAAO,WAAW;GACvB,UAAU,QAAQ,qBAAqB,MAAG;IAAA,YAAA;IAAA,GAAA;IAAA,GAAA;IAAA,GAAA,KAAA;IAAA,GAAA,CAAA,UAAA,2BAAA;GAAA,CAAC;GAC3C,OAAO,EAAE,OAAO;EAClB,CAAC;CACH;CAEA,MAAM,UAAU,OAAmB;EAAE;EAAc;EAAS;EAAS;CAAS,CAAC;CAE/E,IAAI,+BAA+B;EACjC,QAAQ,aAAa,WAAW;GAC9B,WAAW;GACX,gBAAgB;GAChB,QAAQ;EACV,CAAC;EACD,QAAQ,aAAa,WAAW;GAC9B,WAAW;GACX,gBAAgB,QAAQ;GACxB,QAAQ;EACV,CAAC;CACH;CAEA,IAAI,WACF,IAAI;EACF,MAAM,SAAS,oBACb,OAAO,IAAI,CACT,GAAG,YAAY,KAAK,UAAU,QAAQ,SAAS,KAAK,CAAC,GACrD,QAAQ,SAAS,OAAwB,CAC3C,CAAC,CACH;EAIA,MAAM,SAAS,oBAAoB,2BAA2B,OAAO,CAAC;CACxE,SAAS,KAAK;EACZ,MAAM,SAAS,oBAAoB,QAAQ,SAAS,CAAC,CAAC,CAAC,YAAY,KAAA,CAAS;EAC5E,MAAM;CACR;CAGF,OAAO,IAAI,gBAAgB,OAAO;AACpC;AAEA,IAAM,kBAAN,MAA6C;CACtB;CAArB,YAAY,SAA+C;EAAtC,KAAA,UAAA;CAAuC;CAE5D,IAAI,eAAoD;EACtD,OAAO,KAAK,QAAQ;CACtB;CAEA,IAAI,WAAkC;EACpC,OAAO,KAAK,QAAQ;CACtB;CAEA,KAAK,OAAmE;EACtE,OAAO,SAAS,oBAAoB,KAAK,QAAQ,SAAS,KAAK,CAAC;CAClE;CAEA,MAAM,OAAmE;EACvE,OAAO,SAAS,oBAAoB,KAAK,QAAQ,MAAM,KAAK,CAAC;CAC/D;CAEA,IAAO,OAAsC;EAC3C,OAAO,KAAK,QAAQ,aAAa,IAAI,KAAK;CAC5C;CAEA,OAAU,OAAwC;EAChD,OAAO,KAAK,QAAQ,aAAa,OAAO,KAAK;CAC/C;CAEA,kBAAqB,OAAmC,MAAyC;EAC/F,MAAM,UAAU,MAAM,WAAW;EACjC,OAAO,SAAS,oBACd,KAAK,QAAQ,aAAa,QAAQ,KAAK,CAAC,CAAC,KACvC,OAAO,cAAc;GACnB,UAAU,SAAS,OAAO,OAAO;GACjC,cAAc,OAAO,KAAK,aAAa,MAAM,UAAU,CAAC;EAC1D,CAAC,CACH,CACF;CACF;CAEA,aAAa,OAAiD,MAA4C;EACxG,MAAM,MAAM,OAAO,UAAU,WAAW,QAAQ,SAAyB,KAAK;EAC9E,MAAM,UAAU,MAAM,WAAW;EAEjC,MAAM,UAAU,OAAO,IAAI,EAAE,MAAM,KAAK,GAAG,aAAa;GACtD,MAAM,QAAQ,OAAO,OAAO,UAAU,KAAK,QAAQ,UAAU;GAG7D,IAAI,KAAK,QAAQ,eAAe,CAAC,CAAC,SAAS,GAAG,GAC5C;GAEF,OAAO,MAAM;IACX,MAAM,UAAU,OAAO,OAAO,KAAK,KAAK;IACxC,IAAI,QAAQ,UAAU,OAAO,QAAQ,UAAU,aAC7C;GAEJ;EACF,CAAC,CAAC,CAAC,KACD,OAAO,QACP,OAAO,cAAc;GACnB,UAAU,SAAS,OAAO,OAAO;GACjC,cAAc,OAAO,KAAK,aAAa,GAAG,CAAC;EAC7C,CAAC,CACH;EAEA,OAAO,SAAS,oBAAoB,OAAO;CAC7C;CAEA,MAAM,OAAa,IAAgC,GAAG,MAA+B;EAEnF,MAAM,SAAS,OAAM,MADC,KAAK,kBAAkB,gBAA6B,EAAA,CAC7C,cAAc,IAAW,GAAI,IAAc;EACxE,IAAI,OAAO,OACT,MAAM,OAAO;EAEf,OAAO,OAAO;CAChB;CAEA,MAAM,WACJ,QACA,SACY;EAEZ,QAAO,MADe,KAAK,kBAAkB,uBAAoC,EAAE,SAAS,SAAS,QAAQ,CAAC,EAAA,CAC/F,WAAW,QAAQ,SAAS,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,KAAA,CAAS;CAC5F;CAEA,OAAO,IAA8B;EACnC,OAAO,SAAS,oBAAoB,KAAK,QAAQ,OAAO,EAAE,CAAC;CAC7D;CAEA,QAAQ,IAA8B;EACpC,OAAO,SAAS,oBAAoB,KAAK,QAAQ,QAAQ,EAAE,CAAC;CAC9D;CAEA,MAAM,UAAyB;EAC7B,MAAM,SAAS,oBAAoB,KAAK,QAAQ,SAAS,CAAC;CAC5D;CAEA,CAAC,OAAO,gBAA+B;EACrC,OAAO,KAAK,QAAQ;CACtB;AACF;AAEA,IAAM,gBAAgB,uBAAe,IAAI,MAAM,yBAAyB,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC9M5E,IAAa,wBACX,kBACA,UACqB;CACrB,MAAM,QAAwB,CAAC;CAE/B,MAAM,aAAa,IAAI,IAAI,iBAAiB,KAAK,OAAO,OAAO,GAAG,KAAK,GAAG,CAAC,CAAC;CAE5E,MAAM,UAAU,IAAoC,UAAoB;EACtE,MAAM,KAAK;GAAE,cAAc,OAAO,GAAG,KAAK,GAAG;GAAG,OAAO,SAAS,CAAC;EAAE,CAAC;CACtE;CAEA,MAAM,WAAW,QAAQ,MAAM,MAAM,IAAI;CAEzC,OAAO;EACL,KAAK,SAAS;GAIZ,IAAI;GACJ,MAAM,iBAAiB;IACrB,IAAI,CAAC,MAEH,OADY,QAAQ,OAAO,gBACpB,CAAA,CAAI,MAAM,QAAQ,QAAQ,OAAO;IAE1C,OAAO;GACT;GAEA,MAAM,UAAyC;IAC7C,IAAI,cAAc;KAChB,OAAO,SAAS,CAAC,CAAE;IACrB;IACA,IAAI,mBAAmB;KACrB,OAAO,SAAS,CAAC,CAAE;IACrB;IACA,IAAI,iBAAiB;KACnB,OAAO,SAAS,CAAC,CAAE;IACrB;IACA,SAAS,IAAoC,OAAiB,GAAG,SAAgB;KAC/E,SAAS,IAAI,KAAK;KAClB,IAAI,WAAW,IAAI,OAAO,GAAG,KAAK,GAAG,CAAC,GACpC,OAAO,OAAO,QAAQ,KAAA,CAAgB;KAExC,OAAQ,SAAS,CAAC,CAAE,OAAe,IAAI,OAAO,GAAG,IAAI;IACvD;IACA,eAAe,OAAO,IAAoC,OAAiB,GAAG,SAAgB;KAC5F,SAAS,IAAI,KAAK;KAClB,IAAI,WAAW,IAAI,OAAO,GAAG,KAAK,GAAG,CAAC,GACpC,OAAO,EAAE,MAAM,KAAA,EAAU;KAE3B,OAAQ,SAAS,CAAC,CAAE,cAAsB,IAAI,OAAO,GAAG,IAAI;IAC9D;IACA,WAAW,IAAoC,OAAiB,GAAG,SAAgB;KACjF,SAAS,IAAI,KAAK;KAClB,IAAI,WAAW,IAAI,OAAO,GAAG,KAAK,GAAG,CAAC,GACpC,OAAO,OAAO,QAAQ,KAAA,CAAS;KAEjC,OAAQ,SAAS,CAAC,CAAE,SAAiB,IAAI,OAAO,GAAG,IAAI;IACzD;GACF;GAEA,OAAO,CAAC,WAAsB,kBAA+B,OAAO,CAAC;EACvE;EACA,SAAe,IAAmD;GAChE,MAAM,MAAM,OAAO,GAAG,KAAK,GAAG;GAC9B,OAAO,MAAM,QAAQ,MAAM,EAAE,iBAAiB,GAAG;EACnD;EACA,QAAQ;GACN,MAAM,SAAS;EACjB;CACF;AACF;;;;;;;;AC/HA,IAAa,eAAe,YAC1B,MAAM,OACJ,SACA,OAAO,IAAI,aAAa;CAGtB,MAAM,gBAAgB,OACpB,OAAO,WAAW;EAChB,MAAM,SAAS,QAAQ,MAAM,WAAW,OAAO,KAAK,QAAQ,QAAQ,EAAE;EACtE,UAAU,QAAQ,qBAAqB,MAAG;GAAA,YAAA;GAAA,GAAA;GAAA,GAAA;GAAA,GAAA;GAAA,GAAA,CAAA,UAAA,2BAAA;EAAA,CAAC;EAC3C,OAAO,EAAE,OAAO;CAClB,CAAC;CAEH,MAAM,UAAU,OAAmB;EACjC;EACA;EACA,SAAS,QAAQ,KAAK,WAAW,OAAO,KAAK,QAAQ,GAAG;CAC1D,CAAC;CAED,QAAQ,aAAa,WAAW;EAC9B,WAAW;EACX,gBAAgB;EAChB,QAAQ;CACV,CAAC;CAED,QAAQ,aAAa,WAAW;EAC9B,WAAW;EACX,gBAAgB,QAAQ;EACxB,QAAQ;CACV,CAAC;CAED,OAAO,QAAQ,SAAS,OAAwB;CAEhD,OAAO;AACT,CAAC,CACH;;;;;;;ACjBF,IAAa,sBAAsB,EACjC,cACA,UAAU,CAAC,GACX,GAAG,YAC+D,CAAC,MAAM;CAGzE,MAAM,UAAU,QACb,QAAQ,EAAE,WAAW,CAAC,KAAK,QAAQ,MAAM,SAAS,QAAQ,CAAC,CAAA,CAC3D,KAAK,EAAE,WAAW,KAAK,QAAQ,GAAG;CACrC,MAAM,gBAAgB,OAAmB;EACvC,oBAAoB,sBAAM,IAAI,MAAM,iBAAiB,CAAC;EACtD,SAAS,CAAC,aAAa,GAAG,OAAO;EACjC;EACA,GAAG;CACL,CAAC;CAMD,cAAc,aAAa,WAAW;EACpC,WAAW;EACX,gBAAgB;EAChB,QAAQ;CACV,CAAC;CACD,cAAc,aAAa,WAAW;EACpC,WAAW;EACX,gBAAgB,cAAc;EAC9B,QAAQ;CACV,CAAC;CAED,IAAI,cAGF,oBAAsC,iBAAiB,cAAc,cAAc,YAAY,CAAC,CAAC,CAAC,SAC/F,eAAe;EACd,cAAc,aAAa,WAAW;GACpC,WAAW,WAAW;GACtB,gBAAgB,WAAW;GAC3B,QAAQ;EACV,CAAC;CACH,CACF;CAGF,OAAO;AACT;;;;;AAgCA,IAAa,qBAAqB,EAAE,IAAI,SAAS,eAAuC;CACtF,MAAM,CAAC,cAAc,mBAAmB,SAAoC;CAE5E,MAAM,cAAc,OAAO,QAAQ;CACnC,YAAY,UAAU;CAEtB,gBAAgB;EACd,MAAM,gBAAgB,mBAAmB,OAAO;EAChD,MAAM,CAAC,cAAc,oBAAsC,CACzD,WAAsB,WAAwB;GAC5C;GACA,YAAY,oBAAA,YAAA,EAAA,UAAG,YAAY,QAAU,CAAA;EACvC,CAAC,CACH,CAAC;EAED,cAAc,aAAa,WAAW;GACpC,WAAW,WAAW;GACtB,gBAAgB,WAAW;GAC3B,QAAQ;EACV,CAAC;EAED,gBAAgB;GACd;GACA,aAAa,QAAQ;GACrB,YAAY,QAAQ;GACpB,UAAU,QAAQ;GAClB,SAAS;EACX,CAAC;EAED,aAAa;GACX,cAAc,aAAa,OAAO,WAAW,WAAW,WAAW,cAAc;GAGjF,SAAS,YAAY,cAAc,SAAS,CAAC;EAC/C;CACF,GAAG,CAAC,IAAI,OAAO,CAAC;CAGhB,IAAI,CAAC,gBAAgB,aAAa,YAAY,IAC5C,OAAO,oBAAA,YAAA,CAAI,CAAA;CAGb,OAAO,oBAAC,sBAAD,EAAsB,GAAI,aAAe,CAAA;AAClD;;;;;AAMA,IAAa,qBAA4B,OAA2C,CAAC,MAAiB;CACpG,QAAQ,OAAO,YAAY;EACzB,MAAM,UAAU,QAAQ;EAExB,MAAM,UAAU,cAAe,OAAO,SAAS,aAAa,KAAK,OAAc,IAAI,MAAO,CAAC,SAAS,IAAI,CAAC;EAEzG,OACE,oBAAC,mBAAD;GAAmB,IAAI;GAAkB;GACvC,UAAA,oBAAC,OAAD,CAAQ,CAAA;EACS,CAAA;CAEvB;AACF;AAEA,IAAM,wBAAwB,EAC5B,UACA,YACA,eACA,aACA,cAC+B;CAG/B,MAAM,CAAC,WAAW,gBAAgB,SAAS,KAAK;CAGhD,eACE,OAAO,eAAe;EACpB,MAAM,QAAQ,IAAI,YAAY,KAAK,UAAU,cAAc,SAAS,KAAK,CAAC,KAAK,CAAC,CAAC;EAKjF,SAAS,YACP,2BAA2B,aAAa,CAAC,CAAC,KAExC,OAAO,QACL,OAAO,WAAW;GAChB,IAAI,CAAC,WAAW,OAAO,SACrB,aAAa,IAAI;EAErB,CAAC,CACH,CACF,CACF;CACF,GACA;EAAC;EAAY;EAAe;CAAO,CACrC;CAEA,MAAM,MAAM,OAAO;EACjB;EACA;EACA,UAAU,YAAY,WAAW,4BAA4B;CAC/D,CAAC;CACD,OAAO,YAAY,oBAAC,KAAD,CAAM,CAAA,IAAI,oBAAA,YAAA,CAAI,CAAA;AACnC;AAEA,IAAM,YAAY,SAAgB;CAChC,KAAK,IAAI,KAAK,6BAA6B;CAC3C,MAAM;CACN,MAAM,CAAC,QAAQ;AACjB,CAAC;AAID,IAAM,cAAc,OAAc,SAAS,CAAC,CAAC,KAC3C,UAAiB;CACf,IAAI;CACJ,aAAa;CACb,gBAAgB,OAAO,QAAQ,CAAC,CAAC;AACnC,CAAC,GACD,IACF,CAAC,CAAC;;;;;;;;;;AC1NF,IAAa,oBACV,UAAU,UACV,UAAU;CACT,SAAiB,OAAO;CACxB,OAAO,oBAAC,OAAD,CAAQ,CAAA;AACjB"}
|
|
1
|
+
{"version":3,"file":"testing.mjs","names":["__dxlog_file","ActivationEvents.Idle","ActivationEvents.CommandsRequested","ActivationEvent.pluginStart","__dxlog_file","PluginManager.make","Capabilities.PluginManager","Capabilities.AtomRegistry","ActivationEvents.Startup","ActivationEvent.eventKey","Capabilities.OperationInvoker","Capabilities.ProcessManagerRuntime","Capabilities.OperationInvoker","Capability.contribute","Plugin.Service","PluginManager.make","Capabilities.PluginManager","Capabilities.AtomRegistry","ActivationEvents.Startup","PluginManager.make","Capabilities.PluginManager","Capabilities.AtomRegistry","CapabilityManager.expandContributions","Capability.contribute","Capabilities.ReactRoot","_Fragment","Plugin.makeMeta","Plugin.define","Plugin.addModule","ActivationEvents.Startup","Plugin.make"],"sources":["../../src/testing/demand-gated.ts","../../src/testing/harness.ts","../../src/testing/operationCapture.ts","../../src/testing/service.ts","../../src/testing/withPluginManager.tsx","../../src/testing/withSurfaceDebug.tsx"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport { log } from '@dxos/log';\n\nimport { ActivationEvents } from '../common/index.ts';\nimport { ActivationEvent, type PluginManager } from '../core/index.ts';\n\n/**\n * Fires every activation event that a running app fires in response to demand: the\n * {@link ActivationEvents.Idle} wave, {@link ActivationEvents.CommandsRequested}, then each core\n * and enabled plugin's start event.\n *\n * Testing only, which is why it lives here rather than in the public `ActivationEvents` module.\n * A plugin's start fires when one of its surfaces renders, and that signal does not exist here: a\n * headless harness mounts no surfaces, and a story mounts exactly one in isolation, so both would\n * otherwise sit at whatever the startup pass activated and assert against modules that never load.\n *\n * The idle wave is included as an ordering barrier, not because the manager omits it — the\n * scheduler fires it from a forked daemon, so a caller that asserts as soon as `start()` returns\n * could otherwise race it. Firing here is idempotent against the wave guard either way.\n *\n * Fires unconditionally rather than tracking real demand, because narrowing it to the surfaces a\n * story mounts would starve any story whose subject depends on a sibling plugin's start-gated\n * contributions. The cost is that storybook cannot catch demand-gating regressions; only the\n * runtime modules-at-ready budget covers those.\n *\n * Sequential so the work trickles instead of saturating the main thread; per-plugin failures are\n * logged and skipped so one broken feature cannot stall the rest.\n */\nexport const activateDemandGatedModules = (\n manager: Pick<PluginManager.PluginManager, 'getCore' | 'getEnabled' | 'activate'>,\n): Effect.Effect<void> =>\n Effect.forEach(\n [\n ActivationEvents.Idle,\n // Demanded by a host building a command tree — a CLI binary or a terminal panel — and\n // nothing here is either.\n ActivationEvents.CommandsRequested,\n ...new Set([...manager.getCore(), ...manager.getEnabled()].map(ActivationEvent.pluginStart)),\n ],\n (event) =>\n manager\n .activate(event)\n .pipe(\n Effect.catch((error) =>\n Effect.sync(() => log.warn('activation event failed', { event: event.id, error: String(error) })),\n ),\n ),\n { discard: true },\n );\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Duration from 'effect/Duration';\nimport * as Effect from 'effect/Effect';\nimport * as PubSub from 'effect/PubSub';\nimport type * as Registry from 'effect/reactivity/AtomRegistry';\n\nimport type * as Operation from '@dxos/compute/Operation';\nimport * as EffectEx from '@dxos/effect/EffectEx';\nimport { invariant } from '@dxos/invariant';\n\nimport { ActivationEvents, Capabilities } from '../common/index.ts';\nimport { ActivationEvent, type Capability, type CapabilityManager, type Plugin, PluginManager } from '../core/index.ts';\nimport { activateDemandGatedModules } from './demand-gated.ts';\n\nexport type TestAppOptions = {\n /**\n * Plugins to register. Plugins whose `meta.profile.tags` includes `'system'` are treated as core\n * (force-enabled). For test convenience, plugins without a `'system'` tag are enabled by\n * default unless `enabled` is provided.\n */\n plugins: Plugin.Plugin[];\n /** Plugin ids that are enabled by default in addition to core. Defaults to all non-system plugin ids. */\n enabled?: string[];\n /** Additional activation events fired before Startup. */\n setupEvents?: ActivationEvent.ActivationEvent[];\n /**\n * Whether to automatically fire Startup during setup.\n * Defaults to true.\n */\n autoStart?: boolean;\n /**\n * Whether to register the PluginManager + AtomRegistry framework capabilities.\n * Defaults to true.\n */\n registerFrameworkCapabilities?: boolean;\n /**\n * Completes when the host is idle, gating the Idle wave. Off-browser the real wait resolves\n * immediately; pass `Effect.never` to keep idle-gated modules inactive, as on a browser cold boot.\n */\n whenIdle?: Effect.Effect<void>;\n /**\n * Resolves an id `manager.add` is given that names none of `plugins` — a URL, as a remote plugin\n * is added. Without it such an id fails, as an unknown plugin does.\n */\n pluginLoader?: PluginManager.ManagerOptions['pluginLoader'];\n};\n\n/**\n * A running plugin manager plus helpers for driving it in tests.\n */\nexport interface TestHarness {\n readonly manager: PluginManager.PluginManager;\n readonly capabilities: CapabilityManager.CapabilityManager;\n readonly registry: Registry.AtomRegistry;\n\n /** Activate the given event. Equivalent to `manager.activate(event)`. */\n fire(event: ActivationEvent.ActivationEvent | string): Promise<boolean>;\n /** Re-activate all modules that were activated by the given event. */\n reset(event: ActivationEvent.ActivationEvent | string): Promise<boolean>;\n\n /** Returns the first contributed capability for the given interface. Throws if none are present. */\n get<T>(iface: Capability.InterfaceDef<T>): T;\n /** Returns all contributed capabilities for the given interface. */\n getAll<T>(iface: Capability.InterfaceDef<T>): T[];\n /** Waits until at least one capability is contributed for the given interface. */\n waitForCapability<T>(iface: Capability.InterfaceDef<T>, opts?: { timeout?: number }): Promise<T>;\n /** Waits until the given activation event has completed. */\n waitForEvent(event: ActivationEvent.ActivationEvent | string, opts?: { timeout?: number }): Promise<void>;\n\n /** Invokes an operation through the `Capabilities.OperationInvoker` capability. */\n invoke<I, O>(op: Operation.Definition<I, O>, ...args: void extends I ? [input?: I] : [input: I]): Promise<O>;\n\n /**\n * Waits for `Capabilities.ProcessManagerRuntime` and runs the given effect on it.\n * Convenience around `waitForCapability(ProcessManagerRuntime).runPromise(effect)`.\n */\n runPromise<A, E>(\n effect: Effect.Effect<A, E, Capabilities.ProcessManagerRuntimeServices>,\n options?: { readonly timeout?: number; readonly signal?: AbortSignal },\n ): Promise<A>;\n\n enable(id: string): Promise<boolean>;\n disable(id: string): Promise<boolean>;\n\n /** Shuts down the underlying plugin manager. */\n dispose(): Promise<void>;\n\n /** Async-disposable support so tests can use `await using harness = ...`. */\n [Symbol.asyncDispose](): Promise<void>;\n}\n\nconst DEFAULT_TIMEOUT_MS = 5_000;\n\n/**\n * Creates a TestHarness with the same bootstrap sequence that `useApp` performs,\n * minus the React provider tree.\n *\n * For Node-only tests, this is enough to fire activation events, read\n * capabilities, and invoke operations.\n *\n * For React tests, pass the returned harness to `render` or `renderSurface`\n * from `@dxos/app-framework/testing-react`.\n *\n * TODO(wittjosiah): Consider running activation tests under a browser runner.\n * A plugin's `#capabilities` resolves to its `capabilities/node.ts` under the `node` export\n * condition, so a Node-run activation test asserts the NODE barrel's wiring, not the one the\n * app ships. The two are hand-maintained siblings and drifted silently — 35 modules were gated\n * in `index.ts` and ungated in `node.ts` (found 2026-08-04; a `CreateObject` module read as\n * startup-eager in tests while the browser build gated it correctly). They were realigned, but\n * nothing keeps them that way, and a lint rule is the wrong instrument: the barrels legitimately\n * diverge (node omits React surfaces entirely), so \"same gates\" is not a property that holds in\n * general. Running these tests in a browser runner exercises the shipped barrel directly and\n * makes the question moot.\n */\nexport const createTestApp = async (opts: TestAppOptions): Promise<TestHarness> => {\n const {\n plugins,\n enabled = plugins\n .filter(({ meta }) => !meta.profile.tags?.includes('system'))\n .map((plugin) => plugin.meta.profile.key),\n setupEvents = [],\n autoStart = true,\n registerFrameworkCapabilities = true,\n whenIdle,\n pluginLoader: fallbackLoader,\n } = opts;\n\n const pluginLoader = (id: string) => {\n const plugin = plugins.find((plugin) => plugin.meta.profile.key === id);\n if (!plugin && fallbackLoader) {\n return fallbackLoader(id);\n }\n return Effect.sync(() => {\n invariant(plugin, `Plugin not found: ${id}`);\n return { plugin };\n });\n };\n\n const manager = PluginManager.make({ pluginLoader, plugins, enabled, whenIdle });\n\n if (registerFrameworkCapabilities) {\n manager.capabilities.contribute({\n interface: Capabilities.PluginManager,\n implementation: manager,\n module: 'org.dxos.app-framework.plugin-manager',\n });\n manager.capabilities.contribute({\n interface: Capabilities.AtomRegistry,\n implementation: manager.registry,\n module: 'org.dxos.app-framework.atom-registry',\n });\n }\n\n if (autoStart) {\n try {\n await EffectEx.runAndForwardErrors(\n Effect.all([\n ...setupEvents.map((event) => manager.activate(event)),\n manager.activate(ActivationEvents.Startup),\n ]),\n );\n // In the app plugins start on demand (surface render), which a headless harness never\n // triggers — fire every start event before the test body runs so start-gated modules\n // are present.\n await EffectEx.runAndForwardErrors(activateDemandGatedModules(manager));\n } catch (err) {\n await EffectEx.runAndForwardErrors(manager.shutdown()).catch(() => undefined);\n throw err;\n }\n }\n\n return new TestHarnessImpl(manager);\n};\n\nclass TestHarnessImpl implements TestHarness {\n constructor(readonly manager: PluginManager.PluginManager) {}\n\n get capabilities(): CapabilityManager.CapabilityManager {\n return this.manager.capabilities;\n }\n\n get registry(): Registry.AtomRegistry {\n return this.manager.registry;\n }\n\n fire(event: ActivationEvent.ActivationEvent | string): Promise<boolean> {\n return EffectEx.runAndForwardErrors(this.manager.activate(event));\n }\n\n reset(event: ActivationEvent.ActivationEvent | string): Promise<boolean> {\n return EffectEx.runAndForwardErrors(this.manager.reset(event));\n }\n\n get<T>(iface: Capability.InterfaceDef<T>): T {\n return this.manager.capabilities.get(iface);\n }\n\n getAll<T>(iface: Capability.InterfaceDef<T>): T[] {\n return this.manager.capabilities.getAll(iface);\n }\n\n waitForCapability<T>(iface: Capability.InterfaceDef<T>, opts?: { timeout?: number }): Promise<T> {\n const timeout = opts?.timeout ?? DEFAULT_TIMEOUT_MS;\n return EffectEx.runAndForwardErrors(\n this.manager.capabilities.waitFor(iface).pipe(\n Effect.timeoutOrElse({\n duration: Duration.millis(timeout),\n orElse: () => Effect.fail(timeoutError(iface.identifier)),\n }),\n ),\n );\n }\n\n waitForEvent(event: ActivationEvent.ActivationEvent | string, opts?: { timeout?: number }): Promise<void> {\n const key = typeof event === 'string' ? event : ActivationEvent.eventKey(event);\n const timeout = opts?.timeout ?? DEFAULT_TIMEOUT_MS;\n\n const program = Effect.gen({ self: this }, function* () {\n const queue = yield* PubSub.subscribe(this.manager.activation);\n // Re-check after subscribing to avoid a race where the event fires\n // between the caller invoking this and the subscription being installed.\n if (this.manager.getEventsFired().includes(key)) {\n return;\n }\n while (true) {\n const message = yield* PubSub.take(queue);\n if (message.event === key && message.state === 'activated') {\n return;\n }\n }\n }).pipe(\n Effect.scoped,\n Effect.timeoutOrElse({\n duration: Duration.millis(timeout),\n orElse: () => Effect.fail(timeoutError(key)),\n }),\n );\n\n return EffectEx.runAndForwardErrors(program);\n }\n\n async invoke<I, O>(op: Operation.Definition<I, O>, ...args: [input?: I]): Promise<O> {\n const invoker = await this.waitForCapability(Capabilities.OperationInvoker);\n const result = await invoker.invokePromise(op as any, ...(args as [any]));\n if (result.error) {\n throw result.error;\n }\n return result.data as O;\n }\n\n async runPromise<A, E>(\n effect: Effect.Effect<A, E, Capabilities.ProcessManagerRuntimeServices>,\n options?: { readonly timeout?: number; readonly signal?: AbortSignal },\n ): Promise<A> {\n const runtime = await this.waitForCapability(Capabilities.ProcessManagerRuntime, { timeout: options?.timeout });\n return runtime.runPromise(effect, options?.signal ? { signal: options.signal } : undefined);\n }\n\n enable(id: string): Promise<boolean> {\n return EffectEx.runAndForwardErrors(this.manager.enable(id));\n }\n\n disable(id: string): Promise<boolean> {\n return EffectEx.runAndForwardErrors(this.manager.disable(id));\n }\n\n async dispose(): Promise<void> {\n await EffectEx.runAndForwardErrors(this.manager.shutdown());\n }\n\n [Symbol.asyncDispose](): Promise<void> {\n return this.dispose();\n }\n}\n\nconst timeoutError = (id: string) => new Error(`Timed out waiting for ${id}`);\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\n\nimport type * as Operation from '@dxos/compute/Operation';\n\nimport { Capabilities } from '../common/index.ts';\nimport { Capability } from '../core/index.ts';\n\nexport type CapturedCall<I = unknown> = {\n /** The DXN key string of the invoked operation. */\n operationKey: string;\n /** The input passed to the operation. */\n input: I;\n};\n\ntype CapabilityManagerLike = {\n get: (cap: Capability.InterfaceDef<Capabilities.OperationInvoker>) => Capabilities.OperationInvoker;\n getAll: (cap: Capability.InterfaceDef<Capabilities.OperationInvoker>) => Capabilities.OperationInvoker[];\n};\n\nexport type OperationCapture = {\n /**\n * Wraps the real OperationInvoker from the given manager. Pass to\n * `withPluginManager({ capabilities: (m) => capture.wrap(m) })`.\n */\n wrap(manager: CapabilityManagerLike): Capability.AnyContribution[];\n /** Returns all recorded calls (mocked or real) for the given operation. */\n getCalls<I, O>(op: Operation.Definition<I, O>): CapturedCall<I>[];\n /** Clears all recorded calls (useful between play function steps). */\n reset(): void;\n};\n\n/**\n * Creates a capture that wraps the real `Capabilities.OperationInvoker`:\n *\n * - **Mocked operations** (declared in `mockedOperations`) are intercepted: the call is recorded\n * and returns `{ data: undefined }` without executing. Use this for side-effecting operations\n * you don't want to run in tests, such as `LayoutOperation.Open` (navigation).\n *\n * - **All other operations** are forwarded to the real invoker and still execute normally. The\n * call is still recorded so you can assert it was triggered even though it ran for real.\n *\n * Pass a `spyFn` wrapper (e.g. `fn` from `storybook/test`) to get Storybook Actions panel\n * integration and vi-style matchers on the recording.\n *\n * @example\n * ```ts\n * import { fn } from 'storybook/test';\n *\n * const capture = makeOperationCapture(\n * // These ops are mocked: captured but not executed.\n * [AssistantOperation.RunPromptInNewChat, LayoutOperation.Open],\n * fn,\n * );\n *\n * // Wire into withPluginManager:\n * capabilities: (manager) => capture.wrap(manager)\n *\n * // Assert in a play function:\n * const calls = capture.getCalls(AssistantOperation.RunPromptInNewChat);\n * expect(calls).toHaveLength(1);\n * expect(calls[0].input.prompt).toBe('Draft a new document');\n * ```\n *\n * @idiom org.dxos.app-framework.testing.operationCapture\n * applies: Storybook play-function tests for components that call plugin operations\n * instead-of: Loading every plugin whose operations the component triggers\n * uses: {@link makeOperationCapture}, {@link withPluginManager}\n */\nexport const makeOperationCapture = (\n mockedOperations: readonly Operation.Definition.Any[],\n spyFn?: (impl: (...args: any[]) => any) => any,\n): OperationCapture => {\n const calls: CapturedCall[] = [];\n\n const mockedKeys = new Set(mockedOperations.map((op) => String(op.meta.key)));\n\n const record = (op: Operation.Definition<any, any>, input?: unknown) => {\n calls.push({ operationKey: String(op.meta.key), input: input ?? {} });\n };\n\n const recordFn = spyFn ? spyFn(record) : record;\n\n return {\n wrap(manager) {\n // Use getAll to find the real invoker that was registered before our wrapper. manager.get\n // returns the last contribution (ours, once added), but getAll returns them all in order.\n // On first invocation (when activation is complete) we find the non-wrapper contribution.\n let real: Capabilities.OperationInvoker | undefined;\n const delegate = () => {\n if (!real) {\n const all = manager.getAll(Capabilities.OperationInvoker);\n real = all.find((inv) => inv !== wrapped);\n }\n return real;\n };\n\n const wrapped: Capabilities.OperationInvoker = {\n get invocations() {\n return delegate()!.invocations;\n },\n get pendingFollowups() {\n return delegate()!.pendingFollowups;\n },\n get awaitFollowups() {\n return delegate()!.awaitFollowups;\n },\n invoke: (op: Operation.Definition<any, any>, input?: unknown, ...rest: any[]) => {\n recordFn(op, input);\n if (mockedKeys.has(String(op.meta.key))) {\n return Effect.succeed(undefined as any);\n }\n return (delegate()!.invoke as any)(op, input, ...rest);\n },\n invokePromise: async (op: Operation.Definition<any, any>, input?: unknown, ...rest: any[]) => {\n recordFn(op, input);\n if (mockedKeys.has(String(op.meta.key))) {\n return { data: undefined };\n }\n return (delegate()!.invokePromise as any)(op, input, ...rest);\n },\n schedule: (op: Operation.Definition<any, any>, input?: unknown, ...rest: any[]) => {\n recordFn(op, input);\n if (mockedKeys.has(String(op.meta.key))) {\n return Effect.succeed(undefined);\n }\n return (delegate()!.schedule as any)(op, input, ...rest);\n },\n };\n\n return [Capability.contribute(Capabilities.OperationInvoker, wrapped)];\n },\n getCalls<I, O>(op: Operation.Definition<I, O>): CapturedCall<I>[] {\n const key = String(op.meta.key);\n return calls.filter((c) => c.operationKey === key) as CapturedCall<I>[];\n },\n reset() {\n calls.length = 0;\n },\n };\n};\n","//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\nimport * as Layer from 'effect/Layer';\n\nimport { invariant } from '@dxos/invariant';\n\nimport { ActivationEvents, Capabilities } from '../common/index.ts';\nimport { Plugin, PluginManager } from '../core/index.ts';\n\n/**\n * Creates a Plugin.Service layer from a list of plugins.\n * This is primarily used for testing.\n */\nexport const fromPlugins = (plugins: Plugin.Plugin[]) =>\n Layer.effect(\n Plugin.Service,\n Effect.gen(function* () {\n // TODO(wittjosiah): Try to dedupe logic between here, createCliApp and useApp.\n\n const pluginLoader = (id: string) =>\n Effect.sync(() => {\n const plugin = plugins.find((plugin) => plugin.meta.profile.key === id);\n invariant(plugin, `Plugin not found: ${id}`);\n return { plugin };\n });\n\n const manager = PluginManager.make({\n pluginLoader,\n plugins,\n enabled: plugins.map((plugin) => plugin.meta.profile.key),\n });\n\n manager.capabilities.contribute({\n interface: Capabilities.PluginManager,\n implementation: manager,\n module: 'org.dxos.app-framework.plugin-manager',\n });\n\n manager.capabilities.contribute({\n interface: Capabilities.AtomRegistry,\n implementation: manager.registry,\n module: 'org.dxos.app-framework.atom-registry',\n });\n\n yield* manager.activate(ActivationEvents.Startup);\n\n return manager;\n }),\n );\n","//\n// Copyright 2025 DXOS.org\n//\n\nimport { type Decorator, type StoryContext } from '@storybook/react-vite';\nimport * as Effect from 'effect/Effect';\nimport React, { type PropsWithChildren, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { raise } from '@dxos/debug';\nimport * as EffectEx from '@dxos/effect/EffectEx';\nimport { DXN } from '@dxos/keys';\nimport { ErrorFallback } from '@dxos/react-error-boundary';\nimport { useAsyncEffect } from '@dxos/react-hooks';\nimport { type MaybeProvider, getProviderValue } from '@dxos/util';\n\nimport { ActivationEvents, Capabilities } from '../common/index.ts';\nimport { type ActivationEvent, Capability, CapabilityManager, Plugin, PluginManager } from '../core/index.ts';\nimport { type UseAppOptions, useApp } from '../ui/index.ts';\nimport { activateDemandGatedModules } from './demand-gated.ts';\n\n/**\n * The fallback a crashed story renders, overridable per story via `withPluginManager({ fallback })`.\n * A global because importing `./testing` from the storybook preview drags the plugin core into every\n * project's dependency pre-bundle.\n */\ndeclare global {\n // eslint-disable-next-line no-var\n var __STORY_ERROR_FALLBACK__: NonNullable<UseAppOptions['fallback']> | undefined;\n}\n\n/**\n * Builds a plugin manager for test hosts. Stories go through {@link withPluginManager}; headless\n * hook tests use this directly to supply the `PluginManagerProvider` value their wrapper needs.\n */\nexport const setupPluginManager = ({\n capabilities,\n plugins = [],\n ...options\n}: UseAppOptions & Pick<WithPluginManagerOptions, 'capabilities'> = {}) => {\n // Auto-enable every non-system plugin so stories don't have to spell out\n // enablement. System-tagged plugins are force-enabled by the manager.\n const enabled = plugins\n .filter(({ meta }) => !meta.profile.tags?.includes('system'))\n .map(({ meta }) => meta.profile.key);\n const pluginManager = PluginManager.make({\n pluginLoader: () => raise(new Error('Not implemented')),\n plugins: [StoryPlugin, ...plugins],\n enabled,\n ...options,\n });\n\n // The framework capabilities a real host contributes, mirroring `createTestApp`. Without these\n // no MODULE provides `AtomRegistry`, so any module requiring it fails the dependency pass's\n // missing-provider check with nothing to wait for — reached as soon as a requiring module sits\n // on the startup pass (attention, graph, the process manager).\n pluginManager.capabilities.contribute({\n interface: Capabilities.PluginManager,\n implementation: pluginManager,\n module: 'org.dxos.app-framework.plugin-manager',\n });\n pluginManager.capabilities.contribute({\n interface: Capabilities.AtomRegistry,\n implementation: pluginManager.registry,\n module: 'org.dxos.app-framework.atom-registry',\n });\n\n if (capabilities) {\n // Fixtures hand us `Contribution`s (from `Capability.contribute`); expand them to the raw\n // interface/implementation entries the manager ingests — the same path module activation uses.\n CapabilityManager.expandContributions(getProviderValue(capabilities, pluginManager.capabilities)).forEach(\n (capability) => {\n pluginManager.capabilities.contribute({\n interface: capability.interface,\n implementation: capability.implementation,\n module: 'story',\n });\n },\n );\n }\n\n return pluginManager;\n};\n\ntype ManagedPluginManagerState = {\n fallback?: UseAppOptions['fallback'];\n fireEvents?: (ActivationEvent.ActivationEvent | string)[];\n pluginManager: PluginManager.PluginManager;\n setupEvents?: ActivationEvent.ActivationEvent[];\n storyId: string;\n};\n\nexport type WithPluginManagerOptions = UseAppOptions & {\n /** @deprecated */\n capabilities?: MaybeProvider<Capability.AnyContribution[], CapabilityManager.CapabilityManager>;\n /** @deprecated */\n fireEvents?: (ActivationEvent.ActivationEvent | string)[];\n};\n\nexport type WithPluginManagerInitializer<Args = void> =\n | WithPluginManagerOptions\n | ((context: StoryContext<Args>) => WithPluginManagerOptions);\n\nexport type PluginManagerHostProps = PropsWithChildren<{\n /** Keys the manager: a new id builds a new one, and the old one shuts down. */\n id: string;\n /** Read with `id`; a new value also rebuilds the manager, so memoize it. */\n options: WithPluginManagerOptions;\n}>;\n\n/**\n * Hosts `children` as the root of a plugin app built from `options`. The decorator form is\n * {@link withPluginManager}; this form lets one story host several apps, e.g. one per client.\n */\nexport const PluginManagerHost = ({ id, options, children }: PluginManagerHostProps) => {\n const [managerState, setManagerState] = useState<ManagedPluginManagerState>();\n // The root is contributed once per manager, so it reads the latest children rather than capturing them.\n const childrenRef = useRef(children);\n childrenRef.current = children;\n\n useEffect(() => {\n const pluginManager = setupPluginManager(options);\n const [capability] = CapabilityManager.expandContributions([\n Capability.contribute(Capabilities.ReactRoot, {\n id,\n root: () => <>{childrenRef.current}</>,\n }),\n ]);\n\n pluginManager.capabilities.contribute({\n interface: capability.interface,\n implementation: capability.implementation,\n module: 'org.dxos.app-framework.with-plugin-manager',\n });\n\n setManagerState({\n pluginManager,\n setupEvents: options.setupEvents,\n fireEvents: options.fireEvents,\n fallback: options.fallback,\n storyId: id,\n });\n\n return () => {\n pluginManager.capabilities.remove(capability.interface, capability.implementation);\n // A story switch tears down while the start-event trickle is still activating, which\n // interrupts the shutdown fiber — expected; real failures still surface.\n EffectEx.runDetached(pluginManager.shutdown());\n };\n }, [id, options]);\n\n // Avoid mounting useApp with a stale manager from the previous story.\n if (!managerState || managerState.storyId !== id) {\n return <></>;\n }\n\n return <WithPluginManagerApp {...managerState} />;\n};\n\n/**\n * Wraps a story with a plugin manager.\n * NOTE: This builds up and tears down the plugin manager on every render.\n */\nexport const withPluginManager = <Args,>(init: WithPluginManagerInitializer<Args> = {}): Decorator => {\n return (Story, context) => {\n const storyId = context.id;\n // Storybook replaces the full context object often, so the manager is keyed by story id.\n const options = useMemo(() => (typeof init === 'function' ? init(context as any) : init), [storyId, init]);\n\n return (\n <PluginManagerHost id={storyId} options={options}>\n <Story />\n </PluginManagerHost>\n );\n };\n};\n\nconst WithPluginManagerApp = ({\n fallback,\n fireEvents,\n pluginManager,\n setupEvents,\n storyId,\n}: ManagedPluginManagerState) => {\n // Gates the first render: rendering before the start events land lets a component read a\n // capability that has not been contributed yet, which strict `useCapability` throws on.\n const [activated, setActivated] = useState(false);\n\n // Fire deprecated events only after the effect-owned manager for this story exists.\n useAsyncEffect(\n async (controller) => {\n await Promise.all(fireEvents?.map((event) => pluginManager.activate(event)) ?? []);\n // In the app plugins start on demand (surface render), but stories render one surface in\n // isolation — fire every start event so start-gated modules are present regardless of\n // which plugin's surface the story exercises. A story switch shuts the manager down\n // mid-trickle, interrupting the activation fiber — expected; real failures still surface.\n EffectEx.runDetached(\n activateDemandGatedModules(pluginManager).pipe(\n // Interruption skips this, so a torn-down story never flips the gate.\n Effect.andThen(\n Effect.sync(() => {\n if (!controller.signal.aborted) {\n setActivated(true);\n }\n }),\n ),\n ),\n );\n },\n [fireEvents, pluginManager, storyId],\n );\n\n const App = useApp({\n pluginManager,\n setupEvents,\n fallback: fallback ?? globalThis.__STORY_ERROR_FALLBACK__ ?? ErrorFallback,\n });\n return activated ? <App /> : <></>;\n};\n\nconst storyMeta = Plugin.makeMeta({\n key: DXN.make('org.dxos.appFramework.story'),\n name: 'Story',\n tags: ['system'],\n});\n\n// No-op plugin to ensure there exists at least one plugin for the startup event.\n// This is necessary because `createApp` expects the startup event to complete before the app is ready.\nconst StoryPlugin = Plugin.define(storyMeta).pipe(\n Plugin.addModule({\n id: 'Story',\n activatesOn: ActivationEvents.Startup,\n activate: () => Effect.succeed([]),\n }),\n Plugin.make,\n)();\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport { type Decorator } from '@storybook/react-vite';\nimport React from 'react';\n\nimport { Surface } from '../ui/index.ts';\n\n/**\n * Storybook decorator that enables the surface debug overlays (`<dx-surface>` wrappers + boundary\n * badges) for the wrapped story. The flag is a `window` singleton, so it is (re)applied on every\n * render — enabling it on decorated stories and clearing it otherwise, so the setting never leaks\n * between stories. Prefer this over the `.storybook/preview` flag when the story must also render\n * under the aggregate root Storybook, which does not load a per-package preview.\n */\nexport const withSurfaceDebug =\n (enabled = true): Decorator =>\n (Story) => {\n Surface.setDebug(enabled);\n return <Story />;\n };\n"],"mappings":"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"}
|