@pathmx/core 0.5.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/LICENSE.md +172 -0
- package/README.md +111 -0
- package/actions/actions.ts +307 -0
- package/actions/draft.ts +105 -0
- package/actions/transaction.ts +164 -0
- package/assets.ts +149 -0
- package/authority/access.ts +820 -0
- package/authority/actors.ts +271 -0
- package/authority/agents.ts +95 -0
- package/authority/credentials.ts +144 -0
- package/authority/model.ts +71 -0
- package/authority/sharing.ts +89 -0
- package/browser-bundle.ts +61 -0
- package/canonical.ts +41 -0
- package/cli/dev.ts +134 -0
- package/cli/export.ts +74 -0
- package/cli/index.ts +52 -0
- package/cli/lint.ts +164 -0
- package/cli/mv.ts +30 -0
- package/cli/perms.ts +182 -0
- package/cli/plugin-packages.ts +159 -0
- package/cli/plugins.ts +95 -0
- package/cli/query.ts +225 -0
- package/cli/readme.md +95 -0
- package/cli/release.ts +75 -0
- package/cli/rm.ts +22 -0
- package/cli/serve.ts +100 -0
- package/cli/tree.ts +131 -0
- package/cli/update.ts +78 -0
- package/cli/utils.ts +53 -0
- package/core.ts +96 -0
- package/database.ts +189 -0
- package/dependencies.ts +60 -0
- package/dist/pathmx.js +1224 -0
- package/document.ts +194 -0
- package/environment.ts +110 -0
- package/environments/bun-plugins.ts +68 -0
- package/environments/bun-publish.ts +194 -0
- package/environments/bun.ts +223 -0
- package/globals.d.ts +14 -0
- package/graph.ts +153 -0
- package/host/compiler.ts +314 -0
- package/host/create.ts +66 -0
- package/host/engine.ts +630 -0
- package/host/plugin-host.ts +487 -0
- package/host/render.ts +102 -0
- package/host/response.ts +20 -0
- package/host/shell.html +15 -0
- package/host/source-sync.ts +254 -0
- package/html-attributes.ts +15 -0
- package/html.ts +48 -0
- package/icons/LICENSE +43 -0
- package/icons/lucide.ts +54 -0
- package/index.ts +75 -0
- package/invalidation.ts +85 -0
- package/log.ts +84 -0
- package/ops/href.ts +87 -0
- package/ops/index.ts +9 -0
- package/ops/move-source.ts +114 -0
- package/ops/plan.ts +47 -0
- package/ops/remove-source.ts +70 -0
- package/package.json +46 -0
- package/path.ts +75 -0
- package/pattern.ts +314 -0
- package/perf.ts +88 -0
- package/plugins/actor-path.ts +43 -0
- package/plugins/actor-profile.ts +55 -0
- package/plugins/agent-browsing.ts +183 -0
- package/plugins/app-component.ts +23 -0
- package/plugins/block-layout/index.ts +78 -0
- package/plugins/block-layout/theme.css +90 -0
- package/plugins/callout/index.ts +236 -0
- package/plugins/callout/theme.css +138 -0
- package/plugins/canonical-links.ts +144 -0
- package/plugins/code-highlight/client.ts +89 -0
- package/plugins/code-highlight/index.ts +147 -0
- package/plugins/code-highlight/theme.css +89 -0
- package/plugins/context.ts +131 -0
- package/plugins/datatype/Datatype[wdth,wght].woff2 +0 -0
- package/plugins/datatype/OFL.txt +96 -0
- package/plugins/datatype/index.ts +287 -0
- package/plugins/definition-list.ts +236 -0
- package/plugins/directive-definitions.ts +13 -0
- package/plugins/embedding/client.ts +88 -0
- package/plugins/embedding/index.ts +43 -0
- package/plugins/image/index.ts +68 -0
- package/plugins/image/theme.css +43 -0
- package/plugins/include.ts +119 -0
- package/plugins/index.ts +91 -0
- package/plugins/input/authoring.ts +236 -0
- package/plugins/input/config.ts +85 -0
- package/plugins/input/index.ts +359 -0
- package/plugins/input/model.ts +173 -0
- package/plugins/input/state.ts +272 -0
- package/plugins/layout.ts +313 -0
- package/plugins/literate/client.ts +208 -0
- package/plugins/literate/index.ts +742 -0
- package/plugins/math/index.ts +140 -0
- package/plugins/meta.ts +42 -0
- package/plugins/navigation/index.ts +158 -0
- package/plugins/navigation/model.ts +364 -0
- package/plugins/preset.ts +65 -0
- package/plugins/query/index.ts +322 -0
- package/plugins/rss/index.ts +46 -0
- package/plugins/runtime/actions.ts +62 -0
- package/plugins/runtime/client.ts +8 -0
- package/plugins/runtime/document.ts +506 -0
- package/plugins/runtime/error.ts +154 -0
- package/plugins/runtime/heading-links.ts +31 -0
- package/plugins/runtime/index.ts +104 -0
- package/plugins/runtime/live.ts +51 -0
- package/plugins/runtime/navigation.ts +113 -0
- package/plugins/runtime/pending.ts +53 -0
- package/plugins/runtime/publication.ts +19 -0
- package/plugins/runtime/start.ts +177 -0
- package/plugins/runtime/static-client.ts +6 -0
- package/plugins/runtime/static-live.ts +188 -0
- package/plugins/runtime/view-transition.ts +72 -0
- package/plugins/runtime/viewport.ts +110 -0
- package/plugins/schema.ts +24 -0
- package/plugins/scripts.ts +140 -0
- package/plugins/source-preview/client.ts +256 -0
- package/plugins/source-preview/index.ts +132 -0
- package/plugins/source-preview/model.ts +11 -0
- package/plugins/source-preview/preview.css +107 -0
- package/plugins/styles.ts +145 -0
- package/plugins/theme/components.ts +10 -0
- package/plugins/theme/foundation.css +358 -0
- package/plugins/theme/index.ts +333 -0
- package/plugins/theme/prose.css +284 -0
- package/plugins/theme/scheme.js +63 -0
- package/plugins/theme/toggle.css +44 -0
- package/plugins/theme/view-transition.css +68 -0
- package/plugins/toc/client.ts +146 -0
- package/plugins/toc/index.ts +232 -0
- package/plugins/toc/theme.css +172 -0
- package/plugins/types.ts +538 -0
- package/problem.ts +41 -0
- package/project.ts +6 -0
- package/publish/build.ts +402 -0
- package/publish/concurrent.ts +32 -0
- package/publish/identity.ts +63 -0
- package/publish/index.ts +11 -0
- package/publish/location.ts +167 -0
- package/publish/model.ts +58 -0
- package/publish/plan.ts +300 -0
- package/publish/validate.ts +150 -0
- package/query/candidate-index.ts +101 -0
- package/query/dependency-index.ts +99 -0
- package/query/fields.ts +216 -0
- package/query/invalidation.ts +48 -0
- package/query/kernel.ts +776 -0
- package/query/model.ts +79 -0
- package/repository.ts +374 -0
- package/runtime-profile.ts +34 -0
- package/schema/model.ts +92 -0
- package/schema/registry.ts +642 -0
- package/schema/standard.ts +226 -0
- package/server/context.ts +94 -0
- package/server/css-imports.ts +66 -0
- package/server/http.ts +333 -0
- package/server/page.ts +21 -0
- package/server/protocols.ts +12 -0
- package/server/representations.ts +66 -0
- package/server/router.ts +131 -0
- package/server/routes.ts +202 -0
- package/server/serve.ts +5 -0
- package/server/watch.ts +120 -0
- package/source/blocks.ts +71 -0
- package/source/format.ts +164 -0
- package/source/index.ts +67 -0
- package/source/interpolate.ts +63 -0
- package/source/markdown/blocks.ts +46 -0
- package/source/markdown/comments.ts +32 -0
- package/source/markdown/fences.ts +67 -0
- package/source/markdown/headings.ts +88 -0
- package/source/markdown/index.ts +34 -0
- package/source/markdown/inline-code.ts +6 -0
- package/source/markdown/links.ts +326 -0
- package/source/markdown/lists.ts +223 -0
- package/source/markdown/prose.ts +74 -0
- package/source/markdown/scan.ts +79 -0
- package/source/markdown/text.ts +82 -0
- package/source/meta.ts +87 -0
- package/source/source.ts +121 -0
- package/source/topmatter.ts +57 -0
- package/source/utils.ts +21 -0
- package/source-diagnostic.ts +63 -0
- package/text-file.ts +26 -0
- package/util.ts +35 -0
- package/view/components.ts +499 -0
- package/view/model.ts +91 -0
- package/view/projection.ts +162 -0
- package/view/session.ts +146 -0
- package/view/syntax.ts +372 -0
package/plugins/types.ts
ADDED
|
@@ -0,0 +1,538 @@
|
|
|
1
|
+
import type { ReadAccess, SourceCapability } from "../authority/access.ts"
|
|
2
|
+
import type { GraphEdge } from "../graph.ts"
|
|
3
|
+
import type { Html } from "../html.ts"
|
|
4
|
+
import type { RouteInvalidation } from "../invalidation.ts"
|
|
5
|
+
import type { CommitResult } from "../repository.ts"
|
|
6
|
+
import type { RuntimeProfile } from "../runtime-profile.ts"
|
|
7
|
+
import type { Source, SourceBlock, SourceNode } from "../source/index.ts"
|
|
8
|
+
import type {
|
|
9
|
+
Actor,
|
|
10
|
+
ActorProfile,
|
|
11
|
+
CredentialSession,
|
|
12
|
+
Principal,
|
|
13
|
+
} from "../authority/model.ts"
|
|
14
|
+
import type { Dependency, DependencyContext } from "../dependencies.ts"
|
|
15
|
+
import type { PathMXDataSchema, StandardSchemaV1 } from "../schema/standard.ts"
|
|
16
|
+
import type { CredentialHost } from "../authority/credentials.ts"
|
|
17
|
+
import type { SourceTransaction } from "../actions/transaction.ts"
|
|
18
|
+
import type { View } from "../view/model.ts"
|
|
19
|
+
import type { AgentAdmission, AgentJob } from "../authority/agents.ts"
|
|
20
|
+
import type { Log } from "../log.ts"
|
|
21
|
+
import type { PluginDatabase, SqlDatabase } from "../database.ts"
|
|
22
|
+
import type { Command } from "commander"
|
|
23
|
+
import type { ApplicationSchema, SchemaContribution } from "../schema/model.ts"
|
|
24
|
+
import type { PatternInstaller } from "../pattern.ts"
|
|
25
|
+
import type {
|
|
26
|
+
HtmlElement,
|
|
27
|
+
HtmlStringRewrite,
|
|
28
|
+
PathMXYaml,
|
|
29
|
+
} from "../environment.ts"
|
|
30
|
+
import type { PreparedQueryPlan } from "../query/kernel.ts"
|
|
31
|
+
import type { QueryRequest } from "../query/model.ts"
|
|
32
|
+
|
|
33
|
+
export type { Actor, Source }
|
|
34
|
+
export type { Dependency, DependencyContext }
|
|
35
|
+
|
|
36
|
+
export type Awaitable<T> = T | Promise<T>
|
|
37
|
+
|
|
38
|
+
export type CompileContext = DependencyContext & {
|
|
39
|
+
source: Source
|
|
40
|
+
block?: SourceBlock
|
|
41
|
+
/** Compiler-owned placement of this content in the rendered document. */
|
|
42
|
+
scope: "page" | "embedded"
|
|
43
|
+
slots: string[]
|
|
44
|
+
/** Authored element names found once for the owning Source. */
|
|
45
|
+
elements: ReadonlySet<string>
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type DocumentStylesheet =
|
|
49
|
+
| Readonly<{ type: "stylesheet"; href: string; media?: string }>
|
|
50
|
+
| Readonly<{
|
|
51
|
+
type: "stylesheet"
|
|
52
|
+
name: string
|
|
53
|
+
text: string
|
|
54
|
+
media?: string
|
|
55
|
+
}>
|
|
56
|
+
|
|
57
|
+
export type DocumentStyle = Readonly<{
|
|
58
|
+
type: "style"
|
|
59
|
+
text: string
|
|
60
|
+
}>
|
|
61
|
+
|
|
62
|
+
export type DocumentPreload = Readonly<{
|
|
63
|
+
type: "preload"
|
|
64
|
+
href: string
|
|
65
|
+
as: string
|
|
66
|
+
contentType?: string
|
|
67
|
+
crossorigin?: boolean
|
|
68
|
+
}>
|
|
69
|
+
|
|
70
|
+
export type DocumentScript =
|
|
71
|
+
| Readonly<{ type: "script"; href: string; module?: boolean }>
|
|
72
|
+
| Readonly<{ type: "script"; source: string; module?: boolean }>
|
|
73
|
+
| Readonly<{ type: "script"; text: string; module?: boolean }>
|
|
74
|
+
| Readonly<{ type: "script"; name: string; text: string; module?: boolean }>
|
|
75
|
+
|
|
76
|
+
export type DocumentTitle = Readonly<{ type: "title"; text: string }>
|
|
77
|
+
|
|
78
|
+
/** `attrs` render verbatim: `{ charset }`, `{ name, content }`, `{ name, media, content }`. */
|
|
79
|
+
export type DocumentMeta = Readonly<{
|
|
80
|
+
type: "meta"
|
|
81
|
+
attrs: Readonly<Record<string, string>>
|
|
82
|
+
}>
|
|
83
|
+
|
|
84
|
+
/** Linked hrefs may be internal (`/app.js`) or external (`https://…`). */
|
|
85
|
+
export type DocumentAsset =
|
|
86
|
+
| DocumentStylesheet
|
|
87
|
+
| DocumentStyle
|
|
88
|
+
| DocumentPreload
|
|
89
|
+
| DocumentScript
|
|
90
|
+
| DocumentTitle
|
|
91
|
+
| DocumentMeta
|
|
92
|
+
|
|
93
|
+
export type AssetContext = {
|
|
94
|
+
addAsset(...assets: DocumentAsset[]): void
|
|
95
|
+
/** Bundle one browser entrypoint and atomically contribute its JS/CSS outputs. */
|
|
96
|
+
addBrowserBundle(entrypoint: string | URL, name: string): Promise<void>
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export type PageContext = DependencyContext &
|
|
100
|
+
AssetContext & {
|
|
101
|
+
source: Source
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export type SourceTransition = Readonly<{
|
|
105
|
+
before?: Source
|
|
106
|
+
after?: Source
|
|
107
|
+
}>
|
|
108
|
+
|
|
109
|
+
export type PluginInvalidationTarget =
|
|
110
|
+
| Readonly<{
|
|
111
|
+
type: "route"
|
|
112
|
+
route: string
|
|
113
|
+
actors?: Iterable<string>
|
|
114
|
+
}>
|
|
115
|
+
| Readonly<{
|
|
116
|
+
type: "actor"
|
|
117
|
+
actors: Iterable<string>
|
|
118
|
+
}>
|
|
119
|
+
|
|
120
|
+
export type PluginInvalidation = Readonly<{
|
|
121
|
+
/** Cached pages whose compiled output or dependency records are stale. */
|
|
122
|
+
dependencies?: Iterable<Dependency>
|
|
123
|
+
sourceIds?: Iterable<string>
|
|
124
|
+
/** Connected routes that must reconcile without implying a rebuild. */
|
|
125
|
+
targets?: Iterable<PluginInvalidationTarget>
|
|
126
|
+
}>
|
|
127
|
+
|
|
128
|
+
export type CompiledPage = Readonly<{
|
|
129
|
+
html: string
|
|
130
|
+
assets: readonly DocumentAsset[]
|
|
131
|
+
sourceId: string
|
|
132
|
+
route: string
|
|
133
|
+
}>
|
|
134
|
+
|
|
135
|
+
export type DocumentAssetContext = AssetContext & {
|
|
136
|
+
page?: CompiledPage
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export type ViewContext = Readonly<{
|
|
140
|
+
view: View
|
|
141
|
+
session: CredentialSession
|
|
142
|
+
/** @deprecated Prefer `view.principal`; retained during the View migration. */
|
|
143
|
+
principal: Principal
|
|
144
|
+
/** @deprecated Internal render Source; migrate safe reads to `view`. */
|
|
145
|
+
source: Source
|
|
146
|
+
route: string
|
|
147
|
+
/** Database isolated to the View Component's owning plugin. */
|
|
148
|
+
database?: SqlDatabase
|
|
149
|
+
}>
|
|
150
|
+
|
|
151
|
+
type ViewComponentUseBase = Readonly<{
|
|
152
|
+
props: Readonly<Record<string, string>>
|
|
153
|
+
origin: Source
|
|
154
|
+
}>
|
|
155
|
+
|
|
156
|
+
export type ViewComponentUse<Data = undefined> = ViewComponentUseBase &
|
|
157
|
+
([Data] extends [undefined]
|
|
158
|
+
? Readonly<{ data?: undefined }>
|
|
159
|
+
: Readonly<{ data: Data }>)
|
|
160
|
+
|
|
161
|
+
export type ViewComponent<
|
|
162
|
+
Compiled = undefined,
|
|
163
|
+
DataSchema extends PathMXDataSchema | undefined = undefined,
|
|
164
|
+
> = Readonly<{
|
|
165
|
+
/** Internal `plugin:name` identity; authored Sources use the generated `x-plugin-name` tag. */
|
|
166
|
+
tag: string
|
|
167
|
+
/** Browser entrypoint bundled only on pages that author this component. */
|
|
168
|
+
client?: string | URL
|
|
169
|
+
/** Validate authored element attributes before exposing the raw props. */
|
|
170
|
+
props?: StandardSchemaV1
|
|
171
|
+
/** Validate one structured record supplied by a data-aware renderer. */
|
|
172
|
+
data?: DataSchema
|
|
173
|
+
compile?(
|
|
174
|
+
use: ViewComponentUse,
|
|
175
|
+
ctx: PageContext,
|
|
176
|
+
app: AppContext,
|
|
177
|
+
): Awaitable<Compiled>
|
|
178
|
+
render(
|
|
179
|
+
use: ViewComponentUse<
|
|
180
|
+
DataSchema extends PathMXDataSchema
|
|
181
|
+
? StandardSchemaV1.InferOutput<DataSchema>
|
|
182
|
+
: undefined
|
|
183
|
+
>,
|
|
184
|
+
compiled: Compiled,
|
|
185
|
+
ctx: ViewContext,
|
|
186
|
+
app: AppContext,
|
|
187
|
+
): Awaitable<Html>
|
|
188
|
+
}>
|
|
189
|
+
|
|
190
|
+
/** Type-erased storage boundary; use defineViewComponent for authored inference. */
|
|
191
|
+
export type AnyViewComponent = Readonly<{
|
|
192
|
+
tag: string
|
|
193
|
+
client?: string | URL
|
|
194
|
+
props?: StandardSchemaV1
|
|
195
|
+
data?: PathMXDataSchema
|
|
196
|
+
compile?: (...args: any[]) => Awaitable<unknown>
|
|
197
|
+
render: (...args: any[]) => Awaitable<Html>
|
|
198
|
+
}>
|
|
199
|
+
|
|
200
|
+
/** @internal Runtime-authored component definition used by Literate Components. */
|
|
201
|
+
export type AuthoredDataComponent = Readonly<{
|
|
202
|
+
tag: string
|
|
203
|
+
available(origin: Source): boolean
|
|
204
|
+
compile?(
|
|
205
|
+
origin: Source,
|
|
206
|
+
ctx: PageContext,
|
|
207
|
+
app: AppContext,
|
|
208
|
+
): Awaitable<unknown>
|
|
209
|
+
render(
|
|
210
|
+
use: ViewComponentUse<unknown>,
|
|
211
|
+
compiled: unknown,
|
|
212
|
+
ctx: ViewContext,
|
|
213
|
+
app: AppContext,
|
|
214
|
+
): Awaitable<Html>
|
|
215
|
+
}>
|
|
216
|
+
|
|
217
|
+
export type ViewVariableUse = Readonly<{
|
|
218
|
+
path: readonly string[]
|
|
219
|
+
origin: Source
|
|
220
|
+
}>
|
|
221
|
+
|
|
222
|
+
export type ViewVariableValue = string | number | boolean | null | undefined
|
|
223
|
+
|
|
224
|
+
export type ViewVariable = Readonly<{
|
|
225
|
+
namespace: string
|
|
226
|
+
render(
|
|
227
|
+
use: ViewVariableUse,
|
|
228
|
+
ctx: ViewContext,
|
|
229
|
+
app: AppContext,
|
|
230
|
+
): Awaitable<ViewVariableValue>
|
|
231
|
+
}>
|
|
232
|
+
|
|
233
|
+
export type ServerGraph = Readonly<{
|
|
234
|
+
linksFrom(path: string): readonly GraphEdge[]
|
|
235
|
+
linksTo(path: string): readonly GraphEdge[]
|
|
236
|
+
neighbors(path: string): readonly SourceNode[]
|
|
237
|
+
backlinks(path: string): readonly SourceNode[]
|
|
238
|
+
}>
|
|
239
|
+
|
|
240
|
+
export type ServerRenderOptions = Readonly<{
|
|
241
|
+
status?: number
|
|
242
|
+
headers?: HeadersInit
|
|
243
|
+
}>
|
|
244
|
+
|
|
245
|
+
export type PluginLog = Readonly<Pick<Log, "debug" | "info" | "warn" | "error">>
|
|
246
|
+
|
|
247
|
+
export type PluginContext = Readonly<{
|
|
248
|
+
plugin: string
|
|
249
|
+
log: PluginLog
|
|
250
|
+
runtime: RuntimeProfile
|
|
251
|
+
database?: SqlDatabase
|
|
252
|
+
}>
|
|
253
|
+
|
|
254
|
+
type AppSources = Readonly<{
|
|
255
|
+
/** Resolve a Source id, exact Source path, or public route. */
|
|
256
|
+
get(idOrPath: string): Source | undefined
|
|
257
|
+
all(): readonly Source[]
|
|
258
|
+
/** Resolve only a public page route. */
|
|
259
|
+
resolve(pathname: string): Source | undefined
|
|
260
|
+
/** Normalize a repository-relative value to an absolute graph path. */
|
|
261
|
+
path(value: string): string
|
|
262
|
+
isPage(source: Source): boolean
|
|
263
|
+
builtPages(): readonly CompiledPage[]
|
|
264
|
+
}>
|
|
265
|
+
|
|
266
|
+
type AppActors = Readonly<{
|
|
267
|
+
profile(actorId: string): ActorProfile | undefined
|
|
268
|
+
homeActorId(path: string): string | undefined
|
|
269
|
+
}>
|
|
270
|
+
|
|
271
|
+
type AppAccess = Readonly<{
|
|
272
|
+
read(principal: Principal, target: Source | string): ReadAccess
|
|
273
|
+
can(
|
|
274
|
+
principal: Principal,
|
|
275
|
+
target: Source | string,
|
|
276
|
+
capability: SourceCapability,
|
|
277
|
+
): boolean
|
|
278
|
+
canEmbed(container: string, dependency: string): boolean
|
|
279
|
+
}>
|
|
280
|
+
|
|
281
|
+
type AppAssets = Readonly<{
|
|
282
|
+
load(url: URL): Awaitable<Blob>
|
|
283
|
+
publish(name: string, blob: Blob, contentType?: string): Promise<string>
|
|
284
|
+
}>
|
|
285
|
+
|
|
286
|
+
type AppHtml = Readonly<{
|
|
287
|
+
rewrite: HtmlStringRewrite
|
|
288
|
+
}>
|
|
289
|
+
|
|
290
|
+
type AppCompiler = Readonly<{
|
|
291
|
+
block(
|
|
292
|
+
source: Source,
|
|
293
|
+
block: SourceBlock,
|
|
294
|
+
dependencies?: DependencyContext,
|
|
295
|
+
options?: { id?: string },
|
|
296
|
+
): Promise<string>
|
|
297
|
+
/** Compile another Source as a document while excluding the calling Plugin. */
|
|
298
|
+
document(
|
|
299
|
+
source: Source,
|
|
300
|
+
dependencies: DependencyContext,
|
|
301
|
+
): Promise<Readonly<{ html: string; assets: readonly DocumentAsset[] }>>
|
|
302
|
+
}>
|
|
303
|
+
|
|
304
|
+
type AppComponents = Readonly<{
|
|
305
|
+
claim(sourcePath: string, tags: Iterable<string>): void
|
|
306
|
+
release(sourcePath: string): void
|
|
307
|
+
has(tag: string): boolean
|
|
308
|
+
/** @internal Replace runtime-authored structured-data component definitions. */
|
|
309
|
+
replaceData(
|
|
310
|
+
sourcePath: string,
|
|
311
|
+
components: Iterable<AuthoredDataComponent>,
|
|
312
|
+
): void
|
|
313
|
+
/** @internal Prepare one structured-data component once during page compile. */
|
|
314
|
+
prepareData(
|
|
315
|
+
tag: string,
|
|
316
|
+
props: Readonly<Record<string, string>>,
|
|
317
|
+
origin: Source,
|
|
318
|
+
ctx: PageContext,
|
|
319
|
+
): Promise<unknown>
|
|
320
|
+
/** @internal Render one validated record through a prepared component. */
|
|
321
|
+
renderData(prepared: unknown, data: unknown, ctx: ViewContext): Promise<Html>
|
|
322
|
+
}>
|
|
323
|
+
|
|
324
|
+
type AppDiagnostics = Readonly<{
|
|
325
|
+
/** Stop indexing one invalid Source with a lint-collectable Plugin issue. */
|
|
326
|
+
invalid(source: Source, message: string): never
|
|
327
|
+
}>
|
|
328
|
+
|
|
329
|
+
type AppQuery = Readonly<{
|
|
330
|
+
/** @internal Normalize, validate, and track a compile-time query plan. */
|
|
331
|
+
prepare(
|
|
332
|
+
query: string,
|
|
333
|
+
request?: QueryRequest<unknown>,
|
|
334
|
+
): Promise<PreparedQueryPlan>
|
|
335
|
+
}>
|
|
336
|
+
|
|
337
|
+
/** Request-independent capabilities available to Plugin hooks and components. */
|
|
338
|
+
export type AppContext = PluginContext &
|
|
339
|
+
Readonly<{
|
|
340
|
+
schema: ApplicationSchema
|
|
341
|
+
query: AppQuery
|
|
342
|
+
yaml: PathMXYaml
|
|
343
|
+
sources: AppSources
|
|
344
|
+
graph: ServerGraph
|
|
345
|
+
actors: AppActors
|
|
346
|
+
access: AppAccess
|
|
347
|
+
assets: AppAssets
|
|
348
|
+
html: AppHtml
|
|
349
|
+
compile: AppCompiler
|
|
350
|
+
components: AppComponents
|
|
351
|
+
diagnostics: AppDiagnostics
|
|
352
|
+
}>
|
|
353
|
+
|
|
354
|
+
export type PluginCommandContext = Readonly<{
|
|
355
|
+
plugin: string
|
|
356
|
+
pathsRoot: string
|
|
357
|
+
/** Explicit CLI Action root, when it differs from the project convention. */
|
|
358
|
+
actionsRoot?: string
|
|
359
|
+
projectRoot: string
|
|
360
|
+
stateRoot: string
|
|
361
|
+
log: PluginLog
|
|
362
|
+
database?: SqlDatabase
|
|
363
|
+
/** Plan and install user-owned project files through the portable Pattern boundary. */
|
|
364
|
+
patterns: PatternInstaller
|
|
365
|
+
}>
|
|
366
|
+
|
|
367
|
+
export type PublishContext = Readonly<{
|
|
368
|
+
/** Add one finite public GET pathname to the static publication. */
|
|
369
|
+
route(pathname: string): void
|
|
370
|
+
/** Reject publication when an authored use has no static representation. */
|
|
371
|
+
unsupported(source: Source, message: string): void
|
|
372
|
+
}>
|
|
373
|
+
|
|
374
|
+
export type ServerContext = Readonly<{
|
|
375
|
+
request: Request
|
|
376
|
+
url: URL
|
|
377
|
+
/** Route path relative to the owning plugin's `/api/<plugin-id>/` mount. */
|
|
378
|
+
path: string
|
|
379
|
+
plugin: string
|
|
380
|
+
/** Structured logger whose messages are prefixed with the owning Plugin id. */
|
|
381
|
+
log: PluginLog
|
|
382
|
+
runtime: RuntimeProfile
|
|
383
|
+
/** Database isolated to the route's owning plugin. */
|
|
384
|
+
database?: SqlDatabase
|
|
385
|
+
graph: ServerGraph
|
|
386
|
+
source(idOrPath: string): Source | undefined
|
|
387
|
+
sources(): readonly Source[]
|
|
388
|
+
resolve(pathname: string): Source | undefined
|
|
389
|
+
isPublic(source: Source | string): boolean
|
|
390
|
+
session(): Promise<CredentialSession>
|
|
391
|
+
/** Return the memoized viewer-filtered Source and graph projection. */
|
|
392
|
+
view(): Promise<View>
|
|
393
|
+
readAccess(source: Source | string): Promise<ReadAccess>
|
|
394
|
+
onSync(listener: (event: RouteInvalidation) => void): () => void
|
|
395
|
+
render(
|
|
396
|
+
source: Source | string,
|
|
397
|
+
options?: ServerRenderOptions,
|
|
398
|
+
): Promise<Response>
|
|
399
|
+
mutate(
|
|
400
|
+
run: (transaction: SourceTransaction) => Awaitable<void>,
|
|
401
|
+
): Promise<CommitResult>
|
|
402
|
+
/** Commit one idempotent, target-only mutation under an admitted Agent Actor. */
|
|
403
|
+
mutateAsAgent(admission: AgentAdmission, run: AgentJob): Promise<CommitResult>
|
|
404
|
+
/** Delegate an auth URL to the CredentialHost owned by the auth plugin. */
|
|
405
|
+
handleCredentials(): Promise<Response>
|
|
406
|
+
}>
|
|
407
|
+
|
|
408
|
+
export type ServerRouteHandler = (ctx: ServerContext) => Awaitable<Response>
|
|
409
|
+
|
|
410
|
+
export type ServerRoute = Readonly<{
|
|
411
|
+
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS" | "*"
|
|
412
|
+
path: string
|
|
413
|
+
handle: ServerRouteHandler
|
|
414
|
+
}>
|
|
415
|
+
|
|
416
|
+
export type StreamHandler = {
|
|
417
|
+
element(el: HtmlElement): void
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
const PLUGIN_ID = /^[a-z0-9]+(?:-[a-z0-9]+)*$/
|
|
421
|
+
|
|
422
|
+
export function canonicalPluginId(id: string) {
|
|
423
|
+
if (!PLUGIN_ID.test(id)) throw new Error(`Invalid plugin id: ${id}`)
|
|
424
|
+
return id
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/** Optional lifecycle hooks. Implement any subset. */
|
|
428
|
+
export type Plugin = {
|
|
429
|
+
/** Stable build-plugin identity used for diagnostics and composition. */
|
|
430
|
+
id: string
|
|
431
|
+
/** Earlier-installed Plugin ids this Plugin cannot operate without. */
|
|
432
|
+
requires?: readonly string[]
|
|
433
|
+
/** Discoverable Source, Block, prop, query, and Action declarations. */
|
|
434
|
+
schema?: SchemaContribution
|
|
435
|
+
/** Optional isolated SQL state owned and migrated by this plugin. */
|
|
436
|
+
database?: PluginDatabase
|
|
437
|
+
/** Trusted local administrator commands mounted below `pmx <plugin-id>`. */
|
|
438
|
+
commands?(group: Command, ctx: PluginCommandContext): void
|
|
439
|
+
/** Optional request-admission provider owned by this plugin. */
|
|
440
|
+
credentials?: CredentialHost
|
|
441
|
+
/** Portable HTTP handlers. Routes run before credential resolution. */
|
|
442
|
+
routes?: readonly ServerRoute[]
|
|
443
|
+
/** Viewer-aware leaf components authored through this plugin's namespace. */
|
|
444
|
+
components?: readonly AnyViewComponent[]
|
|
445
|
+
/** Escaped scalar namespaces resolved while rendering an admitted view. */
|
|
446
|
+
variables?: readonly ViewVariable[]
|
|
447
|
+
/** Perf/diagnostic label; defaults to the factory function's name. */
|
|
448
|
+
name?: string
|
|
449
|
+
/** Initialize plugin-owned resources after registration and before indexing. */
|
|
450
|
+
setup?(ctx: PluginContext): Awaitable<void>
|
|
451
|
+
/** Release plugin-owned resources during application shutdown. */
|
|
452
|
+
close?(ctx: PluginContext): Awaitable<void>
|
|
453
|
+
/** Report Source-local repository issues when `pmx lint` explicitly runs. */
|
|
454
|
+
lint?(
|
|
455
|
+
report: (source: Source, message: string) => void,
|
|
456
|
+
app: AppContext,
|
|
457
|
+
): Awaitable<void>
|
|
458
|
+
/** Contribute finite GET routes and static-compatibility diagnostics. */
|
|
459
|
+
publish?(ctx: PublishContext, app: AppContext): Awaitable<void>
|
|
460
|
+
/** Inspect or enrich a source when it is added to the index. */
|
|
461
|
+
index?(source: Source, app: AppContext): void
|
|
462
|
+
/** Remove plugin state associated with a source before reindexing or deletion. */
|
|
463
|
+
unindex?(sourcePath: string, app: AppContext): void
|
|
464
|
+
/** Transform interpolated Markdown before it is rendered to HTML. */
|
|
465
|
+
precompile?(
|
|
466
|
+
markdown: string,
|
|
467
|
+
ctx: CompileContext,
|
|
468
|
+
app: AppContext,
|
|
469
|
+
): Awaitable<string>
|
|
470
|
+
/** Transform HTML immediately after rendering a source or block. */
|
|
471
|
+
postcompile?(
|
|
472
|
+
html: string,
|
|
473
|
+
ctx: CompileContext,
|
|
474
|
+
app: AppContext,
|
|
475
|
+
): Awaitable<string>
|
|
476
|
+
/** Transform an assembled page and collect its page-specific assets. */
|
|
477
|
+
page?(html: string, ctx: PageContext, app: AppContext): Awaitable<string>
|
|
478
|
+
/** Describe pages affected by plugin-owned state after a Source transition. */
|
|
479
|
+
invalidate?(
|
|
480
|
+
transition: SourceTransition,
|
|
481
|
+
app: AppContext,
|
|
482
|
+
): PluginInvalidation | undefined
|
|
483
|
+
/** Collect document-level assets, optionally using the compiled page. */
|
|
484
|
+
documentAssets?(ctx: DocumentAssetContext, app: AppContext): Awaitable<void>
|
|
485
|
+
/** Register selector handlers for streaming transformations of final HTML. */
|
|
486
|
+
streamSelectors?(
|
|
487
|
+
ctx: ViewContext,
|
|
488
|
+
app: AppContext,
|
|
489
|
+
): Record<string, StreamHandler>
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/** Create a per-Engine plugin instance. Stateful plugins keep data in the closure. */
|
|
493
|
+
export type PluginFactory = () => Plugin
|
|
494
|
+
|
|
495
|
+
/** Preserve inference for repository-authored build plugins. */
|
|
496
|
+
export function definePlugin<const Definition extends Plugin>(
|
|
497
|
+
definition: Definition,
|
|
498
|
+
) {
|
|
499
|
+
return definition
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/** Preserve compile-result inference for a viewer-aware component. */
|
|
503
|
+
export function defineViewComponent<
|
|
504
|
+
Compiled,
|
|
505
|
+
DataSchema extends PathMXDataSchema | undefined = undefined,
|
|
506
|
+
>(view: ViewComponent<Compiled, DataSchema>) {
|
|
507
|
+
return view
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/** Define one actor-aware scalar namespace rendered through opaque view slots. */
|
|
511
|
+
export function defineViewVariable(variable: ViewVariable) {
|
|
512
|
+
return variable
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
function serverRoute(
|
|
516
|
+
method: ServerRoute["method"],
|
|
517
|
+
path: string,
|
|
518
|
+
handle: ServerRouteHandler,
|
|
519
|
+
): ServerRoute {
|
|
520
|
+
return { method, path, handle }
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
function methodRoute(method: Exclude<ServerRoute["method"], "*">) {
|
|
524
|
+
return (path: string, handle: ServerRouteHandler) =>
|
|
525
|
+
serverRoute(method, path, handle)
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/** Define relative routes mounted below `/api/<plugin-id>/`. */
|
|
529
|
+
export const route = Object.freeze({
|
|
530
|
+
get: methodRoute("GET"),
|
|
531
|
+
post: methodRoute("POST"),
|
|
532
|
+
put: methodRoute("PUT"),
|
|
533
|
+
patch: methodRoute("PATCH"),
|
|
534
|
+
delete: methodRoute("DELETE"),
|
|
535
|
+
options: methodRoute("OPTIONS"),
|
|
536
|
+
all: (path: string, handle: ServerRouteHandler) =>
|
|
537
|
+
serverRoute("*", path, handle),
|
|
538
|
+
})
|
package/problem.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export type ProblemDetails = {
|
|
2
|
+
type: "about:blank"
|
|
3
|
+
title: string
|
|
4
|
+
status: number
|
|
5
|
+
detail: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function actionProblem(
|
|
9
|
+
req: Request,
|
|
10
|
+
status: 400 | 403 | 404,
|
|
11
|
+
detail: string,
|
|
12
|
+
) {
|
|
13
|
+
if (!req.headers.get("accept")?.includes("application/problem+json")) {
|
|
14
|
+
return new Response(detail, {
|
|
15
|
+
status,
|
|
16
|
+
headers: {
|
|
17
|
+
"Content-Type": "text/plain; charset=utf-8",
|
|
18
|
+
Vary: "Accept",
|
|
19
|
+
},
|
|
20
|
+
})
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const problem: ProblemDetails = {
|
|
24
|
+
type: "about:blank",
|
|
25
|
+
title:
|
|
26
|
+
status === 404
|
|
27
|
+
? "Not Found"
|
|
28
|
+
: status === 403
|
|
29
|
+
? "Forbidden"
|
|
30
|
+
: "Bad Request",
|
|
31
|
+
status,
|
|
32
|
+
detail,
|
|
33
|
+
}
|
|
34
|
+
return new Response(JSON.stringify(problem), {
|
|
35
|
+
status,
|
|
36
|
+
headers: {
|
|
37
|
+
"Content-Type": "application/problem+json",
|
|
38
|
+
Vary: "Accept",
|
|
39
|
+
},
|
|
40
|
+
})
|
|
41
|
+
}
|
package/project.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Resolve a conventional project directory beside the authored `paths/` root. */
|
|
2
|
+
export function projectDirectory(pathsRoot: string, name: string) {
|
|
3
|
+
const root = pathsRoot.replaceAll("\\", "/").replace(/\/+$/, "")
|
|
4
|
+
const slash = root.lastIndexOf("/")
|
|
5
|
+
return `${slash === -1 ? "" : root.slice(0, slash + 1)}${name}`
|
|
6
|
+
}
|