@astrale-os/sdk 0.1.9 → 0.2.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 (80) hide show
  1. package/dist/auth/index.d.ts +1 -1
  2. package/dist/auth/index.d.ts.map +1 -1
  3. package/dist/auth/index.js +1 -1
  4. package/dist/auth/index.js.map +1 -1
  5. package/dist/cli/run.d.ts +0 -1
  6. package/dist/cli/run.d.ts.map +1 -1
  7. package/dist/cli/run.js +21 -10
  8. package/dist/cli/run.js.map +1 -1
  9. package/dist/config/adapter.d.ts +19 -11
  10. package/dist/config/adapter.d.ts.map +1 -1
  11. package/dist/config/adapter.js.map +1 -1
  12. package/dist/config/define-domain.d.ts +13 -29
  13. package/dist/config/define-domain.d.ts.map +1 -1
  14. package/dist/config/define-domain.js +22 -33
  15. package/dist/config/define-domain.js.map +1 -1
  16. package/dist/config/deploy.d.ts +1 -1
  17. package/dist/config/deploy.js +1 -1
  18. package/dist/config/index.d.ts +1 -1
  19. package/dist/config/index.d.ts.map +1 -1
  20. package/dist/define/remote-function.d.ts +9 -14
  21. package/dist/define/remote-function.d.ts.map +1 -1
  22. package/dist/define/remote-function.js +9 -8
  23. package/dist/define/remote-function.js.map +1 -1
  24. package/dist/define/view.d.ts +14 -6
  25. package/dist/define/view.d.ts.map +1 -1
  26. package/dist/define/view.js +8 -6
  27. package/dist/define/view.js.map +1 -1
  28. package/dist/dispatch/identity.d.ts +10 -9
  29. package/dist/dispatch/identity.d.ts.map +1 -1
  30. package/dist/dispatch/identity.js +9 -15
  31. package/dist/dispatch/identity.js.map +1 -1
  32. package/dist/domain/binding.d.ts +18 -0
  33. package/dist/domain/binding.d.ts.map +1 -0
  34. package/dist/domain/binding.js +29 -0
  35. package/dist/domain/binding.js.map +1 -0
  36. package/dist/domain/build-spec.d.ts.map +1 -1
  37. package/dist/domain/build-spec.js +10 -7
  38. package/dist/domain/build-spec.js.map +1 -1
  39. package/dist/domain/define.d.ts +27 -27
  40. package/dist/domain/define.d.ts.map +1 -1
  41. package/dist/domain/define.js +31 -49
  42. package/dist/domain/define.js.map +1 -1
  43. package/dist/domain/extend-core.d.ts.map +1 -1
  44. package/dist/domain/extend-core.js +9 -1
  45. package/dist/domain/extend-core.js.map +1 -1
  46. package/dist/domain/extend-functions.d.ts +44 -0
  47. package/dist/domain/extend-functions.d.ts.map +1 -0
  48. package/dist/domain/extend-functions.js +69 -0
  49. package/dist/domain/extend-functions.js.map +1 -0
  50. package/dist/domain/extend-views.d.ts +45 -0
  51. package/dist/domain/extend-views.d.ts.map +1 -0
  52. package/dist/domain/extend-views.js +116 -0
  53. package/dist/domain/extend-views.js.map +1 -0
  54. package/dist/index.d.ts +2 -2
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.js +1 -1
  57. package/dist/index.js.map +1 -1
  58. package/dist/server/auxiliary-routes.js +1 -1
  59. package/dist/server/auxiliary-routes.js.map +1 -1
  60. package/dist/server/worker-entry.d.ts +3 -3
  61. package/dist/server/worker-entry.js +3 -3
  62. package/package.json +2 -5
  63. package/src/auth/index.ts +1 -1
  64. package/src/cli/run.ts +21 -12
  65. package/src/config/adapter.ts +16 -11
  66. package/src/config/define-domain.ts +34 -56
  67. package/src/config/deploy.ts +1 -1
  68. package/src/config/index.ts +1 -1
  69. package/src/define/remote-function.ts +9 -14
  70. package/src/define/view.ts +14 -6
  71. package/src/dispatch/identity.ts +15 -21
  72. package/src/domain/binding.ts +37 -0
  73. package/src/domain/build-spec.ts +18 -7
  74. package/src/domain/define.ts +67 -62
  75. package/src/domain/extend-functions.ts +86 -0
  76. package/src/domain/extend-views.ts +151 -0
  77. package/src/index.ts +7 -2
  78. package/src/server/auxiliary-routes.ts +1 -1
  79. package/src/server/worker-entry.ts +3 -3
  80. package/src/domain/extend-core.ts +0 -287
@@ -1,287 +0,0 @@
1
- /**
2
- * Build an augmented `Core<S>` that includes auto-materialized View and
3
- * standalone-function nodes (one per entry in `defineRemoteDomain`'s `views` /
4
- * `remoteFunctions` config), plus their parent Folder + optional `view_for`
5
- * edges. Returns the resolved effective bindings alongside so callers don't
6
- * recompute them.
7
- *
8
- * Standalone callables (the former `RemoteFunction` class) are materialized as
9
- * the canonical kernel `Function` node class — "remote" is just a `binding`,
10
- * not a distinct kind, so there is no per-domain class to configure.
11
- *
12
- * Conflicts: if the user core already declares a top-level node at
13
- * `<viewsFolder>` or `<functionsFolder>`, throws — the auto-materialization
14
- * reserves those slugs.
15
- */
16
-
17
- import type { FunctionBinding } from '@astrale-os/kernel-api/routed'
18
- import type {
19
- AnyEdgeDef,
20
- AnyNodeDef,
21
- Core,
22
- CoreEdgeEntry,
23
- CoreNodeEntry,
24
- Schema,
25
- } from '@astrale-os/kernel-dsl'
26
-
27
- import { Folder, K, KernelSchema } from '@astrale-os/kernel-core'
28
- import { buildCorePath } from '@astrale-os/kernel-dsl'
29
-
30
- /** Canonical node class for standalone callables (the former `RemoteFunction`). */
31
- const FUNCTION_CLASS = KernelSchema.classes.Function as unknown as AnyNodeDef
32
- /** Canonical node class for GUI views. */
33
- const VIEW_CLASS = KernelSchema.classes.View as unknown as AnyNodeDef
34
- /** Canonical edge class linking a View to its target. */
35
- const VIEW_FOR_EDGE_CLASS = KernelSchema.classes.view_for as unknown as AnyEdgeDef
36
-
37
- import type { AnyRemoteFunctionDef } from '../define/remote-function'
38
- import type { ViewDef } from '../define/view'
39
-
40
- export const DEFAULT_VIEWS_FOLDER = 'views'
41
- export const DEFAULT_FUNCTIONS_FOLDER = 'functions'
42
- const SLUG_RE = /^[a-z][a-z0-9-]*$/
43
-
44
- export type ExtendCoreConfig = {
45
- schema: Schema
46
- origin: string
47
- userCore?: Core
48
- /**
49
- * The worker's serving URL — the base every auto-materialized binding
50
- * resolves against. OMITTED at define time (the URL is known only to the
51
- * spec producers): the aux nodes then materialize structure-only (paths,
52
- * names, refs — what identity/subs resolution needs) with no `binding`
53
- * stamped and empty binding maps. Every install graph comes from a
54
- * `materializeRemoteDomain(domain, url)` call where it is present.
55
- */
56
- url?: string
57
-
58
- viewClass?: AnyNodeDef
59
- viewForEdgeClass?: AnyEdgeDef
60
- viewsFolder?: string
61
- // oxlint-disable-next-line no-explicit-any
62
- views?: Record<string, ViewDef<any>>
63
-
64
- functionsFolder?: string
65
- remoteFunctions?: Record<string, AnyRemoteFunctionDef>
66
- }
67
-
68
- export type ExtendCoreResult = {
69
- core: Core
70
- viewBindings: Record<string, FunctionBinding>
71
- remoteFunctionBindings: Record<string, FunctionBinding>
72
- }
73
-
74
- export function extendCore(config: ExtendCoreConfig): ExtendCoreResult {
75
- const {
76
- schema,
77
- origin,
78
- userCore,
79
- url,
80
- viewClass = VIEW_CLASS,
81
- viewForEdgeClass = VIEW_FOR_EDGE_CLASS,
82
- viewsFolder = DEFAULT_VIEWS_FOLDER,
83
- views,
84
- functionsFolder = DEFAULT_FUNCTIONS_FOLDER,
85
- remoteFunctions,
86
- } = config
87
-
88
- validateInputs(config)
89
-
90
- const nodes: CoreNodeEntry[] = userCore ? [...userCore.__nodes] : []
91
- const edges: CoreEdgeEntry[] = userCore ? [...userCore.__edges] : []
92
- const viewBindings: Record<string, FunctionBinding> = {}
93
- const remoteFunctionBindings: Record<string, FunctionBinding> = {}
94
-
95
- if (views && viewClass) {
96
- // Enforce ViewDef's documented exclusivity: `mount` (SPA route) cannot be
97
- // combined with `render` (inline HTML handler) or an explicit `binding` —
98
- // silently ignoring one of them would deploy a view that behaves
99
- // differently than its definition reads.
100
- for (const [slug, def] of Object.entries(views)) {
101
- if (def.mount && (def.render || def.binding)) {
102
- throw new Error(
103
- `defineRemoteDomain: view "${slug}" sets \`mount\` together with ` +
104
- `${def.render ? '`render`' : '`binding`'} — they are mutually exclusive.`,
105
- )
106
- }
107
- }
108
- assertNoConflict(nodes, origin, viewsFolder)
109
- addFolderAndEntries({
110
- origin,
111
- folderSlug: viewsFolder,
112
- nodes,
113
- entries: Object.entries(views).map(([slug, def]) => {
114
- const binding = url
115
- ? def.mount
116
- ? { remoteUrl: joinWorkerPath(url, def.mount) }
117
- : resolveBinding(def.binding, url, viewsFolder, slug)
118
- : undefined
119
- if (binding) viewBindings[slug] = binding
120
- return {
121
- slug,
122
- nodeClass: viewClass,
123
- data: buildFunctionData(slug, binding),
124
- edges: buildViewForEdges(slug, def, viewForEdgeClass, viewsFolder, origin),
125
- }
126
- }),
127
- edges,
128
- })
129
- }
130
-
131
- if (remoteFunctions) {
132
- assertNoConflict(nodes, origin, functionsFolder)
133
- addFolderAndEntries({
134
- origin,
135
- folderSlug: functionsFolder,
136
- nodes,
137
- entries: Object.entries(remoteFunctions).map(([slug, def]) => {
138
- const binding = url ? resolveBinding(def.binding, url, functionsFolder, slug) : undefined
139
- if (binding) remoteFunctionBindings[slug] = binding
140
- return {
141
- slug,
142
- // Standalone callables materialize as the canonical kernel Function class.
143
- nodeClass: FUNCTION_CLASS,
144
- data: {
145
- ...buildFunctionData(slug, binding),
146
- [K.$.i('Function').ref.key]: def.ref ?? `function.${slug}`,
147
- },
148
- edges: [],
149
- }
150
- }),
151
- edges,
152
- })
153
- }
154
-
155
- return {
156
- core: { schema, domain: origin, __nodes: nodes, __edges: edges },
157
- viewBindings,
158
- remoteFunctionBindings,
159
- }
160
- }
161
-
162
- /** Join a worker-relative mount path onto the serving url (single slash). */
163
- function joinWorkerPath(url: string, mount: string): string {
164
- const base = url.replace(/\/+$/, '')
165
- return `${base}/${mount.replace(/^\/+/, '')}`
166
- }
167
-
168
- export function resolveBinding(
169
- override: FunctionBinding | undefined,
170
- url: string,
171
- folderSlug: string,
172
- slug: string,
173
- ): FunctionBinding {
174
- // Same trailing-slash discipline as `joinWorkerPath` — a `url` ending in `/`
175
- // must not produce `//` in the binding (the kernel pins iss by exact string).
176
- const base = url.replace(/\/+$/, '')
177
- if (override) {
178
- return {
179
- ...override,
180
- remoteUrl: override.remoteUrl ?? `${base}/${folderSlug}/${slug}`,
181
- }
182
- }
183
- return { remoteUrl: `${base}/${folderSlug}/${slug}` }
184
- }
185
-
186
- // ── Internal ───────────────────────────────────────────────────────────────
187
-
188
- function validateInputs(config: ExtendCoreConfig): void {
189
- if (config.views) {
190
- for (const slug of Object.keys(config.views)) {
191
- if (!SLUG_RE.test(slug)) {
192
- throw new Error(`defineRemoteDomain: invalid view slug "${slug}" — must match ${SLUG_RE}.`)
193
- }
194
- }
195
- }
196
- if (config.remoteFunctions) {
197
- for (const slug of Object.keys(config.remoteFunctions)) {
198
- if (!SLUG_RE.test(slug)) {
199
- throw new Error(
200
- `defineRemoteDomain: invalid remote-function slug "${slug}" — must match ${SLUG_RE}.`,
201
- )
202
- }
203
- }
204
- }
205
- }
206
-
207
- function assertNoConflict(
208
- nodes: readonly CoreNodeEntry[],
209
- origin: string,
210
- folderSlug: string,
211
- ): void {
212
- const folderPath = buildCorePath(origin, [folderSlug])
213
- if (nodes.some((n) => n.path === folderPath)) {
214
- throw new Error(
215
- `defineRemoteDomain: top-level core slug "${folderSlug}" is reserved by ` +
216
- 'SDK auto-materialization. Move the conflicting node or rename the ' +
217
- '`viewsFolder` / `functionsFolder` config.',
218
- )
219
- }
220
- }
221
-
222
- type EntryDescriptor = {
223
- slug: string
224
- nodeClass: AnyNodeDef
225
- data: Record<string, unknown>
226
- edges: CoreEdgeEntry[]
227
- }
228
-
229
- function addFolderAndEntries(args: {
230
- origin: string
231
- folderSlug: string
232
- entries: EntryDescriptor[]
233
- nodes: CoreNodeEntry[]
234
- edges: CoreEdgeEntry[]
235
- }): void {
236
- const { origin, folderSlug, entries, nodes, edges } = args
237
-
238
- const folderPath = buildCorePath(origin, [folderSlug])
239
- nodes.push({
240
- path: folderPath,
241
- def: Folder as unknown as AnyNodeDef,
242
- data: { [K.Named.name.key]: folderSlug },
243
- })
244
-
245
- for (const entry of entries) {
246
- nodes.push({
247
- path: buildCorePath(origin, [folderSlug, entry.slug]),
248
- def: entry.nodeClass,
249
- data: entry.data,
250
- parent: folderPath,
251
- })
252
- for (const e of entry.edges) edges.push(e)
253
- }
254
- }
255
-
256
- function buildFunctionData(
257
- slug: string,
258
- binding: FunctionBinding | undefined,
259
- ): Record<string, unknown> {
260
- // Match the kernel-core schema serializer which JSON-stringifies the
261
- // `Function.binding` value on Function nodes (see
262
- // kernel/core/domain/serialize/schema.ts). The kernel install validator
263
- // checks `typeof binding === 'string'` then parses; storing a raw object
264
- // trips the validator with "missing remote binding" even when the object IS
265
- // the binding. No binding at all (define-time, no url) → no prop stamped.
266
- return {
267
- [K.Named.name.key]: slug,
268
- ...(binding ? { [K.$.i('Function').binding.key]: JSON.stringify(binding) } : {}),
269
- }
270
- }
271
-
272
- function buildViewForEdges(
273
- slug: string,
274
- def: ViewDef,
275
- edgeClass: AnyEdgeDef | undefined,
276
- viewsFolder: string,
277
- origin: string,
278
- ): CoreEdgeEntry[] {
279
- if (!def.viewFor || !edgeClass) return []
280
- const targets = Array.isArray(def.viewFor) ? def.viewFor : [def.viewFor]
281
- const from = buildCorePath(origin, [viewsFolder, slug])
282
- return targets.map((target) => ({
283
- from,
284
- edge: edgeClass,
285
- to: target as CoreEdgeEntry['to'],
286
- }))
287
- }