@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.
Files changed (195) hide show
  1. package/LICENSE.md +172 -0
  2. package/README.md +111 -0
  3. package/actions/actions.ts +307 -0
  4. package/actions/draft.ts +105 -0
  5. package/actions/transaction.ts +164 -0
  6. package/assets.ts +149 -0
  7. package/authority/access.ts +820 -0
  8. package/authority/actors.ts +271 -0
  9. package/authority/agents.ts +95 -0
  10. package/authority/credentials.ts +144 -0
  11. package/authority/model.ts +71 -0
  12. package/authority/sharing.ts +89 -0
  13. package/browser-bundle.ts +61 -0
  14. package/canonical.ts +41 -0
  15. package/cli/dev.ts +134 -0
  16. package/cli/export.ts +74 -0
  17. package/cli/index.ts +52 -0
  18. package/cli/lint.ts +164 -0
  19. package/cli/mv.ts +30 -0
  20. package/cli/perms.ts +182 -0
  21. package/cli/plugin-packages.ts +159 -0
  22. package/cli/plugins.ts +95 -0
  23. package/cli/query.ts +225 -0
  24. package/cli/readme.md +95 -0
  25. package/cli/release.ts +75 -0
  26. package/cli/rm.ts +22 -0
  27. package/cli/serve.ts +100 -0
  28. package/cli/tree.ts +131 -0
  29. package/cli/update.ts +78 -0
  30. package/cli/utils.ts +53 -0
  31. package/core.ts +96 -0
  32. package/database.ts +189 -0
  33. package/dependencies.ts +60 -0
  34. package/dist/pathmx.js +1224 -0
  35. package/document.ts +194 -0
  36. package/environment.ts +110 -0
  37. package/environments/bun-plugins.ts +68 -0
  38. package/environments/bun-publish.ts +194 -0
  39. package/environments/bun.ts +223 -0
  40. package/globals.d.ts +14 -0
  41. package/graph.ts +153 -0
  42. package/host/compiler.ts +314 -0
  43. package/host/create.ts +66 -0
  44. package/host/engine.ts +630 -0
  45. package/host/plugin-host.ts +487 -0
  46. package/host/render.ts +102 -0
  47. package/host/response.ts +20 -0
  48. package/host/shell.html +15 -0
  49. package/host/source-sync.ts +254 -0
  50. package/html-attributes.ts +15 -0
  51. package/html.ts +48 -0
  52. package/icons/LICENSE +43 -0
  53. package/icons/lucide.ts +54 -0
  54. package/index.ts +75 -0
  55. package/invalidation.ts +85 -0
  56. package/log.ts +84 -0
  57. package/ops/href.ts +87 -0
  58. package/ops/index.ts +9 -0
  59. package/ops/move-source.ts +114 -0
  60. package/ops/plan.ts +47 -0
  61. package/ops/remove-source.ts +70 -0
  62. package/package.json +46 -0
  63. package/path.ts +75 -0
  64. package/pattern.ts +314 -0
  65. package/perf.ts +88 -0
  66. package/plugins/actor-path.ts +43 -0
  67. package/plugins/actor-profile.ts +55 -0
  68. package/plugins/agent-browsing.ts +183 -0
  69. package/plugins/app-component.ts +23 -0
  70. package/plugins/block-layout/index.ts +78 -0
  71. package/plugins/block-layout/theme.css +90 -0
  72. package/plugins/callout/index.ts +236 -0
  73. package/plugins/callout/theme.css +138 -0
  74. package/plugins/canonical-links.ts +144 -0
  75. package/plugins/code-highlight/client.ts +89 -0
  76. package/plugins/code-highlight/index.ts +147 -0
  77. package/plugins/code-highlight/theme.css +89 -0
  78. package/plugins/context.ts +131 -0
  79. package/plugins/datatype/Datatype[wdth,wght].woff2 +0 -0
  80. package/plugins/datatype/OFL.txt +96 -0
  81. package/plugins/datatype/index.ts +287 -0
  82. package/plugins/definition-list.ts +236 -0
  83. package/plugins/directive-definitions.ts +13 -0
  84. package/plugins/embedding/client.ts +88 -0
  85. package/plugins/embedding/index.ts +43 -0
  86. package/plugins/image/index.ts +68 -0
  87. package/plugins/image/theme.css +43 -0
  88. package/plugins/include.ts +119 -0
  89. package/plugins/index.ts +91 -0
  90. package/plugins/input/authoring.ts +236 -0
  91. package/plugins/input/config.ts +85 -0
  92. package/plugins/input/index.ts +359 -0
  93. package/plugins/input/model.ts +173 -0
  94. package/plugins/input/state.ts +272 -0
  95. package/plugins/layout.ts +313 -0
  96. package/plugins/literate/client.ts +208 -0
  97. package/plugins/literate/index.ts +742 -0
  98. package/plugins/math/index.ts +140 -0
  99. package/plugins/meta.ts +42 -0
  100. package/plugins/navigation/index.ts +158 -0
  101. package/plugins/navigation/model.ts +364 -0
  102. package/plugins/preset.ts +65 -0
  103. package/plugins/query/index.ts +322 -0
  104. package/plugins/rss/index.ts +46 -0
  105. package/plugins/runtime/actions.ts +62 -0
  106. package/plugins/runtime/client.ts +8 -0
  107. package/plugins/runtime/document.ts +506 -0
  108. package/plugins/runtime/error.ts +154 -0
  109. package/plugins/runtime/heading-links.ts +31 -0
  110. package/plugins/runtime/index.ts +104 -0
  111. package/plugins/runtime/live.ts +51 -0
  112. package/plugins/runtime/navigation.ts +113 -0
  113. package/plugins/runtime/pending.ts +53 -0
  114. package/plugins/runtime/publication.ts +19 -0
  115. package/plugins/runtime/start.ts +177 -0
  116. package/plugins/runtime/static-client.ts +6 -0
  117. package/plugins/runtime/static-live.ts +188 -0
  118. package/plugins/runtime/view-transition.ts +72 -0
  119. package/plugins/runtime/viewport.ts +110 -0
  120. package/plugins/schema.ts +24 -0
  121. package/plugins/scripts.ts +140 -0
  122. package/plugins/source-preview/client.ts +256 -0
  123. package/plugins/source-preview/index.ts +132 -0
  124. package/plugins/source-preview/model.ts +11 -0
  125. package/plugins/source-preview/preview.css +107 -0
  126. package/plugins/styles.ts +145 -0
  127. package/plugins/theme/components.ts +10 -0
  128. package/plugins/theme/foundation.css +358 -0
  129. package/plugins/theme/index.ts +333 -0
  130. package/plugins/theme/prose.css +284 -0
  131. package/plugins/theme/scheme.js +63 -0
  132. package/plugins/theme/toggle.css +44 -0
  133. package/plugins/theme/view-transition.css +68 -0
  134. package/plugins/toc/client.ts +146 -0
  135. package/plugins/toc/index.ts +232 -0
  136. package/plugins/toc/theme.css +172 -0
  137. package/plugins/types.ts +538 -0
  138. package/problem.ts +41 -0
  139. package/project.ts +6 -0
  140. package/publish/build.ts +402 -0
  141. package/publish/concurrent.ts +32 -0
  142. package/publish/identity.ts +63 -0
  143. package/publish/index.ts +11 -0
  144. package/publish/location.ts +167 -0
  145. package/publish/model.ts +58 -0
  146. package/publish/plan.ts +300 -0
  147. package/publish/validate.ts +150 -0
  148. package/query/candidate-index.ts +101 -0
  149. package/query/dependency-index.ts +99 -0
  150. package/query/fields.ts +216 -0
  151. package/query/invalidation.ts +48 -0
  152. package/query/kernel.ts +776 -0
  153. package/query/model.ts +79 -0
  154. package/repository.ts +374 -0
  155. package/runtime-profile.ts +34 -0
  156. package/schema/model.ts +92 -0
  157. package/schema/registry.ts +642 -0
  158. package/schema/standard.ts +226 -0
  159. package/server/context.ts +94 -0
  160. package/server/css-imports.ts +66 -0
  161. package/server/http.ts +333 -0
  162. package/server/page.ts +21 -0
  163. package/server/protocols.ts +12 -0
  164. package/server/representations.ts +66 -0
  165. package/server/router.ts +131 -0
  166. package/server/routes.ts +202 -0
  167. package/server/serve.ts +5 -0
  168. package/server/watch.ts +120 -0
  169. package/source/blocks.ts +71 -0
  170. package/source/format.ts +164 -0
  171. package/source/index.ts +67 -0
  172. package/source/interpolate.ts +63 -0
  173. package/source/markdown/blocks.ts +46 -0
  174. package/source/markdown/comments.ts +32 -0
  175. package/source/markdown/fences.ts +67 -0
  176. package/source/markdown/headings.ts +88 -0
  177. package/source/markdown/index.ts +34 -0
  178. package/source/markdown/inline-code.ts +6 -0
  179. package/source/markdown/links.ts +326 -0
  180. package/source/markdown/lists.ts +223 -0
  181. package/source/markdown/prose.ts +74 -0
  182. package/source/markdown/scan.ts +79 -0
  183. package/source/markdown/text.ts +82 -0
  184. package/source/meta.ts +87 -0
  185. package/source/source.ts +121 -0
  186. package/source/topmatter.ts +57 -0
  187. package/source/utils.ts +21 -0
  188. package/source-diagnostic.ts +63 -0
  189. package/text-file.ts +26 -0
  190. package/util.ts +35 -0
  191. package/view/components.ts +499 -0
  192. package/view/model.ts +91 -0
  193. package/view/projection.ts +162 -0
  194. package/view/session.ts +146 -0
  195. package/view/syntax.ts +372 -0
@@ -0,0 +1,216 @@
1
+ import type { QueryScalar } from "./model.ts"
2
+
3
+ type JsonSchema = Readonly<Record<string, unknown>>
4
+
5
+ export type QueryField = Readonly<{
6
+ path: string
7
+ label?: string
8
+ description?: string
9
+ filterable: boolean
10
+ sortable: boolean
11
+ }>
12
+
13
+ /** @internal Read a discoverable field from a query projection or its data map. */
14
+ export function queryRecordValue(record: unknown, path: string): unknown {
15
+ const segments = path.split(".")
16
+ const read = (value: unknown, parts: readonly string[]) => {
17
+ let current = value
18
+ for (const segment of parts) {
19
+ if (current == null || typeof current !== "object") return
20
+ current = (current as Record<string, unknown>)[segment]
21
+ }
22
+ return current
23
+ }
24
+ const direct = read(record, segments)
25
+ if (direct !== undefined) return direct
26
+ if (segments[0] === "source") {
27
+ const source = read(record, ["source"])
28
+ const nested = read(source, segments.slice(1))
29
+ if (nested !== undefined) return nested
30
+ const sourceData = read(source, ["data"])
31
+ const nestedData = read(sourceData, segments.slice(1))
32
+ if (nestedData !== undefined) return nestedData
33
+ }
34
+ return read(read(record, ["data"]), segments)
35
+ }
36
+
37
+ function object(value: unknown): JsonSchema | undefined {
38
+ return value != null && typeof value === "object" && !Array.isArray(value)
39
+ ? (value as JsonSchema)
40
+ : undefined
41
+ }
42
+
43
+ function reference(root: JsonSchema, value: unknown) {
44
+ if (typeof value !== "string" || !value.startsWith("#/")) return
45
+ let current: unknown = root
46
+ for (const encoded of value.slice(2).split("/")) {
47
+ const node = object(current)
48
+ if (!node) return
49
+ const key = encoded.replaceAll("~1", "/").replaceAll("~0", "~")
50
+ current = node[key]
51
+ }
52
+ return object(current)
53
+ }
54
+
55
+ function dereference(root: JsonSchema, schema: JsonSchema) {
56
+ return reference(root, schema.$ref) ?? schema
57
+ }
58
+
59
+ function scalarType(value: unknown) {
60
+ const types = Array.isArray(value) ? value : [value]
61
+ return (
62
+ types.length > 0 &&
63
+ types.every(
64
+ (type) =>
65
+ type === "string" ||
66
+ type === "number" ||
67
+ type === "integer" ||
68
+ type === "boolean" ||
69
+ type === "null",
70
+ )
71
+ )
72
+ }
73
+
74
+ function scalarSchema(root: JsonSchema, raw: JsonSchema): boolean {
75
+ const schema = dereference(root, raw)
76
+ if (scalarType(schema.type)) return true
77
+ if (
78
+ Object.hasOwn(schema, "const") &&
79
+ (schema.const == null ||
80
+ typeof schema.const === "string" ||
81
+ typeof schema.const === "number" ||
82
+ typeof schema.const === "boolean")
83
+ ) {
84
+ return true
85
+ }
86
+ if (
87
+ Array.isArray(schema.enum) &&
88
+ schema.enum.length > 0 &&
89
+ schema.enum.every(
90
+ (value) =>
91
+ value == null ||
92
+ typeof value === "string" ||
93
+ typeof value === "number" ||
94
+ typeof value === "boolean",
95
+ )
96
+ ) {
97
+ return true
98
+ }
99
+ for (const option of [schema.anyOf, schema.oneOf]) {
100
+ if (
101
+ Array.isArray(option) &&
102
+ option.length > 0 &&
103
+ option.every((candidate) => {
104
+ const nested = object(candidate)
105
+ return nested ? scalarSchema(root, nested) : false
106
+ })
107
+ ) {
108
+ return true
109
+ }
110
+ }
111
+ return false
112
+ }
113
+
114
+ function collect(
115
+ root: JsonSchema,
116
+ raw: JsonSchema,
117
+ prefix: string,
118
+ fields: Map<string, QueryField>,
119
+ ) {
120
+ const schema = dereference(root, raw)
121
+ if (prefix && scalarSchema(root, schema)) {
122
+ fields.set(
123
+ prefix,
124
+ Object.freeze({
125
+ path: prefix,
126
+ ...(typeof schema.title === "string" ? { label: schema.title } : {}),
127
+ ...(typeof schema.description === "string"
128
+ ? { description: schema.description }
129
+ : {}),
130
+ filterable: true,
131
+ sortable: true,
132
+ }),
133
+ )
134
+ return
135
+ }
136
+ const properties = object(schema.properties)
137
+ if (properties) {
138
+ for (const [name, candidate] of Object.entries(properties)) {
139
+ const nested = object(candidate)
140
+ if (!nested) continue
141
+ collect(root, nested, prefix ? `${prefix}.${name}` : name, fields)
142
+ }
143
+ }
144
+ if (Array.isArray(schema.allOf)) {
145
+ for (const candidate of schema.allOf) {
146
+ const nested = object(candidate)
147
+ if (nested) collect(root, nested, prefix, fields)
148
+ }
149
+ }
150
+ }
151
+
152
+ export class QueryFieldCatalog {
153
+ private fields = new Map<string, QueryField>()
154
+
155
+ add(path: string, label?: string) {
156
+ this.fields.set(
157
+ path,
158
+ Object.freeze({
159
+ path,
160
+ ...(label ? { label } : {}),
161
+ filterable: true,
162
+ sortable: true,
163
+ }),
164
+ )
165
+ return this
166
+ }
167
+
168
+ addObjectSchema(schema: JsonSchema, prefix = "") {
169
+ collect(schema, schema, prefix, this.fields)
170
+ return this
171
+ }
172
+
173
+ addArrayOutput(schema: JsonSchema) {
174
+ const root = dereference(schema, schema)
175
+ const type = root.type
176
+ if (type !== "array" && !(Array.isArray(type) && type.includes("array"))) {
177
+ throw new Error("Query output JSON Schema must describe an array.")
178
+ }
179
+ const items = object(root.items)
180
+ if (!items) {
181
+ throw new Error("Query output JSON Schema must describe array items.")
182
+ }
183
+ collect(schema, items, "", this.fields)
184
+ return this
185
+ }
186
+
187
+ has(path: string) {
188
+ return this.fields.has(path)
189
+ }
190
+
191
+ require(path: string, operation: "filter" | "sort") {
192
+ const field = this.fields.get(path)
193
+ const supported =
194
+ operation === "filter" ? field?.filterable : field?.sortable
195
+ if (!supported) {
196
+ throw new Error(`Field ${path} does not support query ${operation}.`)
197
+ }
198
+ }
199
+
200
+ list() {
201
+ return Object.freeze(
202
+ [...this.fields.values()].sort((left, right) =>
203
+ left.path.localeCompare(right.path),
204
+ ),
205
+ )
206
+ }
207
+ }
208
+
209
+ export function queryScalar(value: unknown): value is QueryScalar {
210
+ return (
211
+ value == null ||
212
+ typeof value === "string" ||
213
+ (typeof value === "number" && Number.isFinite(value)) ||
214
+ typeof value === "boolean"
215
+ )
216
+ }
@@ -0,0 +1,48 @@
1
+ import type { Dependency } from "../dependencies.ts"
2
+ import type { Engine } from "../host/engine.ts"
3
+ import type { RouteInvalidations } from "../invalidation.ts"
4
+ import { queryDependency } from "./kernel.ts"
5
+ import type { Source } from "../source/index.ts"
6
+
7
+ type QueryInvalidation = Readonly<{
8
+ key: string
9
+ actors?: readonly string[]
10
+ }>
11
+
12
+ function addRoutes(
13
+ engine: Engine,
14
+ routes: RouteInvalidations,
15
+ queries: Iterable<QueryInvalidation>,
16
+ ) {
17
+ for (const query of queries) {
18
+ for (const pagePath of engine.dependentsOf(queryDependency(query))) {
19
+ const page = engine.pageCache.get(pagePath)
20
+ if (!page) continue
21
+ if (query.actors) routes.addActors(page.route, query.actors)
22
+ else routes.add(page.route)
23
+ }
24
+ }
25
+ }
26
+
27
+ /** @internal Map derived query invalidation back onto compiled route consumers. */
28
+ export function dependencies(
29
+ engine: Engine,
30
+ routes: RouteInvalidations,
31
+ dependencies: Iterable<Dependency>,
32
+ ) {
33
+ addRoutes(engine, routes, engine.queries.invalidateDependencies(dependencies))
34
+ }
35
+
36
+ /** @internal Invalidate one canonical Source transition and its derived routes. */
37
+ export function source(
38
+ engine: Engine,
39
+ routes: RouteInvalidations,
40
+ before: Source | undefined,
41
+ after: Source | undefined,
42
+ path: string,
43
+ ) {
44
+ addRoutes(engine, routes, [
45
+ ...engine.queries.transition(before, after),
46
+ ...engine.queries.invalidateDependencies([{ type: "source", path }]),
47
+ ])
48
+ }