@astrale-os/cli 1.0.0-beta.4 → 1.0.0-beta.6
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/dist/astrale.js +55649 -59388
- package/dist/public/connect-core.js +1972 -26831
- package/dist/public/keys/index.js +1754 -40686
- package/dist/public/paths/index.js +859 -39511
- package/dist/types/admin/instance/model.d.ts +3 -4
- package/dist/types/errors.d.ts +1 -1
- package/dist/types/lib/idp.d.ts +1 -0
- package/dist/types/lib/instance-target.d.ts +1 -1
- package/dist/types/lib/log.d.ts +2 -2
- package/dist/types/lib/update.d.ts +30 -0
- package/package.json +4 -6
- package/src/__tests__/fixtures/publication.ts +20 -0
- package/src/admin/__tests__/binding.test.ts +14 -21
- package/src/admin/__tests__/fixture.ts +101 -0
- package/src/admin/binding.ts +86 -6
- package/src/admin/catalog/.spec/api.d.ts +2 -2
- package/src/admin/catalog/__tests__/client.test.ts +20 -49
- package/src/admin/catalog/client.ts +35 -26
- package/src/admin/catalog/model.ts +3 -4
- package/src/admin/graph/.spec/api.d.ts +4 -10
- package/src/admin/graph/nodes.ts +1 -1
- package/src/admin/instance/.spec/api.d.ts +2 -2
- package/src/admin/instance/__tests__/client.test.ts +58 -83
- package/src/admin/instance/client.ts +49 -39
- package/src/admin/instance/model.ts +9 -8
- package/src/commands/__tests__/call-describe.test.ts +46 -33
- package/src/commands/__tests__/domain-install-operation.test.ts +3 -14
- package/src/commands/__tests__/domain-install-owned.test.ts +1 -1
- package/src/commands/__tests__/domain-list.test.ts +5 -25
- package/src/commands/__tests__/install-identity-override.test.ts +3 -14
- package/src/commands/__tests__/read-commands.test.ts +35 -10
- package/src/commands/__tests__/update.test.ts +25 -3
- package/src/commands/call-describe.ts +59 -67
- package/src/commands/call.ts +41 -54
- package/src/commands/domain/install.ts +2 -2
- package/src/commands/domain/uninstall.ts +2 -2
- package/src/commands/get.ts +13 -14
- package/src/commands/identity/__tests__/register.test.ts +3 -3
- package/src/commands/identity/register.ts +5 -4
- package/src/commands/instance/delete.ts +5 -3
- package/src/commands/instance/status.ts +1 -9
- package/src/commands/introspect.ts +4 -11
- package/src/commands/logs.ts +24 -25
- package/src/commands/mutate.ts +6 -5
- package/src/commands/query.ts +27 -30
- package/src/commands/token.ts +8 -7
- package/src/commands/update.ts +31 -11
- package/src/commands/view.ts +4 -3
- package/src/connection/.spec/api.d.ts +7 -8
- package/src/connection/.spec/architecture.md +5 -4
- package/src/connection/.spec/flows/session.ts +2 -2
- package/src/connection/.spec/laws/connection.ts +6 -2
- package/src/connection/.spec/layout.ts +1 -0
- package/src/connection/__tests__/credential.test.ts +1 -1
- package/src/connection/__tests__/errors.test.ts +27 -20
- package/src/connection/__tests__/exchange.test.ts +30 -1
- package/src/connection/__tests__/failure-fixtures.ts +39 -0
- package/src/connection/__tests__/failure-safety.test.ts +75 -0
- package/src/connection/__tests__/self.test.ts +31 -11
- package/src/connection/__tests__/session.test.ts +3 -3
- package/src/connection/call.ts +1 -1
- package/src/connection/credential.ts +2 -2
- package/src/connection/errors.ts +1 -355
- package/src/connection/exchange.ts +47 -23
- package/src/connection/failure/classify.ts +110 -0
- package/src/connection/failure/debug.ts +26 -0
- package/src/connection/failure/index.ts +18 -0
- package/src/connection/failure/model.ts +28 -0
- package/src/connection/failure/render.ts +116 -0
- package/src/connection/reasons.ts +16 -0
- package/src/connection/self.ts +39 -21
- package/src/connection/session.ts +8 -8
- package/src/errors.ts +3 -2
- package/src/graph/.spec/api.d.ts +12 -5
- package/src/graph/.spec/layout.ts +9 -1
- package/src/graph/__tests__/mutation.test.ts +2 -2
- package/src/graph/__tests__/query.test.ts +25 -6
- package/src/graph/class.ts +30 -0
- package/src/graph/index.ts +1 -0
- package/src/graph/query.ts +21 -32
- package/src/identity/.spec/api.d.ts +2 -2
- package/src/identity/__tests__/registration.test.ts +1 -1
- package/src/identity/registration.ts +3 -3
- package/src/lib/__tests__/domain-publication.test.ts +4 -15
- package/src/lib/__tests__/idp.test.ts +25 -0
- package/src/lib/__tests__/instance-target.test.ts +6 -39
- package/src/lib/__tests__/log-errors.test.ts +53 -0
- package/src/lib/__tests__/studio-server-deps.test.ts +1 -1
- package/src/lib/__tests__/update.test.ts +101 -8
- package/src/lib/__tests__/view-open-intent.test.ts +0 -2
- package/src/lib/__tests__/view-server.test.ts +1 -1
- package/src/lib/__tests__/view-session.test.ts +1 -1
- package/src/lib/command-dx.ts +1 -4
- package/src/lib/domain-publication.ts +1 -1
- package/src/lib/idp.ts +29 -1
- package/src/lib/instance-target.ts +3 -14
- package/src/lib/log.ts +11 -6
- package/src/lib/update.ts +120 -26
- package/src/lib/validation.ts +2 -2
- package/src/lib/view/resolve.ts +1 -1
- package/src/program/__tests__/program.test.ts +1 -1
- package/studio/client/dist/assets/{elk-api-lwhFo7vB.js → elk-api-Di4OXGNH.js} +1 -1
- package/studio/client/dist/assets/index-BLm6J11H.js +81 -0
- package/studio/client/dist/assets/index-BiGR8Oo9.css +1 -0
- package/studio/client/dist/assets/index-DTjvkOUX.js +8 -0
- package/studio/client/dist/index.html +2 -2
- package/studio/package.json +2 -9
- package/studio/server/agent/ask.test.ts +1 -1
- package/studio/server/agent/bridge/grant.test.ts +1 -1
- package/studio/server/agent/bridge/routes.test.ts +1 -1
- package/studio/server/agent/harness/claude/adapter.test.ts +15 -5
- package/studio/server/agent/prompts/anchors.test.ts +32 -36
- package/studio/server/agent/prompts/anchors.ts +20 -49
- package/studio/server/agent/prompts/system.test.ts +3 -2
- package/studio/server/agent/prompts/system.ts +3 -3
- package/studio/server/agent/routes.test.ts +1 -1
- package/studio/server/agent/run/coordinator.test.ts +1 -1
- package/studio/server/api/canvas.ts +0 -1
- package/studio/server/api-agent-loadout.test.ts +1 -1
- package/studio/server/api.test.ts +1 -1
- package/studio/server/cache.test.ts +23 -12
- package/studio/server/cache.ts +12 -15
- package/studio/server/domain.test.ts +50 -68
- package/studio/server/domain.ts +82 -63
- package/studio/server/handoff/copy.ts +1 -1
- package/studio/server/index.ts +1 -1
- package/studio/server/instances/probe.test.ts +1 -1
- package/studio/server/introspect/anatomy/views/routes.ts +46 -37
- package/studio/server/introspect/anatomy/views.ts +9 -14
- package/studio/server/introspect/anatomy-extras.test.ts +26 -42
- package/studio/server/introspect/anatomy.test.ts +22 -14
- package/studio/server/introspect/anatomy.ts +6 -9
- package/studio/server/introspect/bundle.ts +0 -3
- package/studio/server/introspect/canonical-schema.test.ts +94 -389
- package/studio/server/introspect/canonical-schema.ts +227 -457
- package/studio/server/introspect/core-extractor.ts +18 -127
- package/studio/server/introspect/core.ts +1 -2
- package/studio/server/introspect/diff.test.ts +11 -7
- package/studio/server/introspect/diff.ts +18 -55
- package/studio/server/introspect/extractor.ts +22 -117
- package/studio/server/introspect/overlay-tsmorph.test.ts +119 -240
- package/studio/server/introspect/overlay.test.ts +26 -54
- package/studio/server/introspect/overlay.ts +10 -37
- package/studio/server/introspect/revision.test.ts +1 -1
- package/studio/server/introspect/revision.ts +1 -1
- package/studio/server/introspect/runtime.test.ts +65 -183
- package/studio/server/introspect/runtime.ts +8 -25
- package/studio/server/introspect/schema-ir-json.test.ts +70 -0
- package/studio/server/introspect/schema-ir-json.ts +38 -68
- package/studio/server/introspect/schema-refs.test.ts +43 -88
- package/studio/server/introspect/schema-refs.ts +14 -49
- package/studio/server/introspect/source-overlay/handlers.ts +116 -636
- package/studio/server/introspect/source-overlay/kernel-calls.ts +0 -3
- package/studio/server/introspect/source-overlay/spans.ts +15 -45
- package/studio/server/state/baseline.test.ts +14 -9
- package/studio/server/state/baseline.ts +3 -5
- package/studio/server/state/visibility.ts +1 -5
- package/studio/server/views/model.ts +3 -3
- package/studio/server/views/target.test.ts +17 -74
- package/studio/server/views/target.ts +24 -50
- package/studio/server/watch.test.ts +11 -11
- package/studio/server/watch.ts +8 -4
- package/studio/server/workspace-watch.ts +2 -2
- package/studio/shared/contracts/schema.ts +38 -107
- package/studio/shared/contracts/surface.test.ts +13 -15
- package/studio/shared/contracts/workspace.ts +2 -11
- package/studio/shared/schema/identity.test.ts +20 -44
- package/studio/shared/schema/identity.ts +9 -23
- package/viewer/dist/main.js +40 -61
- package/studio/client/dist/assets/index-B-c-smo9.js +0 -8
- package/studio/client/dist/assets/index-BckHuAWk.js +0 -81
- package/studio/client/dist/assets/index-C4aNQ6dz.css +0 -1
- package/studio/server/introspect/anatomy/views/legacy.ts +0 -232
|
@@ -1,34 +1,47 @@
|
|
|
1
1
|
import { Path } from '@astrale-os/sdk/graph/path'
|
|
2
|
+
import { bundle, defineSchema, func, method, nodeClass } from '@astrale-os/sdk/schema'
|
|
2
3
|
import { describe, expect, test } from 'bun:test'
|
|
3
4
|
|
|
4
|
-
import {
|
|
5
|
+
import { describeCallableFromBundle } from '../call-describe'
|
|
5
6
|
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
output: { mode: 'value' },
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
|
-
},
|
|
7
|
+
const createInstance = method({
|
|
8
|
+
auth: 'authenticated',
|
|
9
|
+
description: 'Create one child Instance.',
|
|
10
|
+
input: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: { operationId: { type: 'string' }, slug: { type: 'string' } },
|
|
13
|
+
required: ['operationId', 'slug'],
|
|
14
|
+
additionalProperties: false,
|
|
18
15
|
},
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
16
|
+
output: { type: 'object', additionalProperties: true },
|
|
17
|
+
static: true,
|
|
18
|
+
})
|
|
19
|
+
const inspectInstance = method({
|
|
20
|
+
auth: 'authenticated',
|
|
21
|
+
description: 'Inspect one child Instance.',
|
|
22
|
+
input: { type: 'object', properties: {}, additionalProperties: false },
|
|
23
|
+
output: { type: 'object', additionalProperties: true },
|
|
24
|
+
})
|
|
25
|
+
const journal = func({
|
|
26
|
+
auth: 'authenticated',
|
|
27
|
+
description: 'Read the authorized Kernel journal.',
|
|
28
|
+
input: { type: 'object', properties: {}, additionalProperties: false },
|
|
29
|
+
output: { type: 'object', additionalProperties: true },
|
|
30
|
+
})
|
|
31
|
+
const source = defineSchema('host.astrale.ai', {
|
|
32
|
+
classes: {
|
|
33
|
+
Manager: nodeClass({ methods: { createInstance } }),
|
|
34
|
+
Instance: nodeClass({ methods: { inspectInstance } }),
|
|
24
35
|
},
|
|
25
|
-
}
|
|
36
|
+
functions: { journal },
|
|
37
|
+
})
|
|
38
|
+
const installed = bundle.create(source)
|
|
26
39
|
|
|
27
|
-
describe('
|
|
28
|
-
test('reads a static Class method from the Domain
|
|
29
|
-
const described =
|
|
40
|
+
describe('describeCallableFromBundle', () => {
|
|
41
|
+
test('reads a static Class method from the resolved Domain', () => {
|
|
42
|
+
const described = describeCallableFromBundle(
|
|
30
43
|
Path.parse('/:host.astrale.ai:class.Manager:createInstance'),
|
|
31
|
-
|
|
44
|
+
installed,
|
|
32
45
|
)
|
|
33
46
|
expect(described).toMatchObject({
|
|
34
47
|
origin: 'host.astrale.ai',
|
|
@@ -36,30 +49,30 @@ describe('describeCallableFromSchema', () => {
|
|
|
36
49
|
method: 'createInstance',
|
|
37
50
|
dispatch: 'static',
|
|
38
51
|
description: 'Create one child Instance.',
|
|
39
|
-
auth: '
|
|
52
|
+
auth: 'authenticated',
|
|
40
53
|
})
|
|
41
54
|
expect(described?.input).toMatchObject({ required: ['operationId', 'slug'] })
|
|
42
55
|
})
|
|
43
56
|
|
|
44
|
-
test('finds
|
|
57
|
+
test('finds one instance method when the receiver Path is not a Class projection', () => {
|
|
45
58
|
expect(
|
|
46
|
-
|
|
47
|
-
Path.parse('/:host.astrale.ai:core.manager::
|
|
48
|
-
|
|
59
|
+
describeCallableFromBundle(
|
|
60
|
+
Path.parse('/:host.astrale.ai:core.manager::inspectInstance'),
|
|
61
|
+
installed,
|
|
49
62
|
),
|
|
50
63
|
).toMatchObject({
|
|
51
64
|
origin: 'host.astrale.ai',
|
|
52
|
-
class: '
|
|
53
|
-
method: '
|
|
65
|
+
class: 'Instance',
|
|
66
|
+
method: 'inspectInstance',
|
|
54
67
|
dispatch: 'instance',
|
|
55
68
|
})
|
|
56
69
|
})
|
|
57
70
|
|
|
58
|
-
test('reads a standalone Function from the Domain
|
|
71
|
+
test('reads a standalone Function from the resolved Domain', () => {
|
|
59
72
|
expect(
|
|
60
|
-
|
|
73
|
+
describeCallableFromBundle(Path.parse('/:host.astrale.ai:function.journal'), installed),
|
|
61
74
|
).toMatchObject({
|
|
62
|
-
origin: '
|
|
75
|
+
origin: 'host.astrale.ai',
|
|
63
76
|
function: 'journal',
|
|
64
77
|
description: 'Read the authorized Kernel journal.',
|
|
65
78
|
})
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { issuer } from '@astrale-os/sdk/auth'
|
|
3
|
-
import { createDeployment } from '@astrale-os/sdk/deployment'
|
|
4
|
-
import { defineSchema } from '@astrale-os/sdk/schema/v1'
|
|
1
|
+
import { defineSchema } from '@astrale-os/sdk/schema'
|
|
5
2
|
import { afterEach, describe, expect, mock, test } from 'bun:test'
|
|
6
3
|
|
|
4
|
+
import { releaseFor } from '../../__tests__/fixtures/publication'
|
|
7
5
|
import { installDirect } from '../domain/install'
|
|
8
6
|
|
|
9
7
|
const GENERATED = '4a4c9a18-50f6-4d84-a7b7-2d83e3e45dc8'
|
|
@@ -12,16 +10,7 @@ const RETRY = '139137b5-af47-47ce-92b2-b64a2b0c63d7'
|
|
|
12
10
|
const originalFetch = globalThis.fetch
|
|
13
11
|
|
|
14
12
|
const schema = defineSchema('crm.test', {})
|
|
15
|
-
const
|
|
16
|
-
schema,
|
|
17
|
-
handlers: { functions: {}, classes: {}, interfaces: {} },
|
|
18
|
-
})
|
|
19
|
-
const deployed = createDeployment({
|
|
20
|
-
definition,
|
|
21
|
-
issuer: issuer.accept('https://crm.test'),
|
|
22
|
-
bundleHref: 'https://crm.test/domain.bundle.json',
|
|
23
|
-
bindings: { callables: [] },
|
|
24
|
-
}).publication
|
|
13
|
+
const deployed = releaseFor(schema, 'https://crm.test').publication
|
|
25
14
|
|
|
26
15
|
function publicationResponse(): Response {
|
|
27
16
|
return Response.json(deployed)
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { issuer } from '@astrale-os/sdk/auth'
|
|
3
|
-
import { createDeployment } from '@astrale-os/sdk/deployment'
|
|
4
|
-
import { defineSchema } from '@astrale-os/sdk/schema/v1'
|
|
1
|
+
import { defineSchema, schema as schemaApi } from '@astrale-os/sdk/schema'
|
|
5
2
|
import { afterAll, describe, expect, test } from 'bun:test'
|
|
6
3
|
|
|
7
4
|
import type { DomainInfo } from '../../lib/admin-domain'
|
|
8
5
|
|
|
6
|
+
import { releaseFor } from '../../__tests__/fixtures/publication'
|
|
9
7
|
import { byDefaultThenName, domainProjection, probe, type DomainRow } from '../domain/list'
|
|
10
8
|
|
|
11
9
|
const strip = (s: string): string => s.replace(/\[[0-9;]*m/g, '')
|
|
@@ -85,16 +83,7 @@ describe('domain list — canonical Publication check', () => {
|
|
|
85
83
|
|
|
86
84
|
test('reports the admitted schema revision in machine data', async () => {
|
|
87
85
|
const schema = defineSchema('catalog-check.example.dev', {})
|
|
88
|
-
const
|
|
89
|
-
schema,
|
|
90
|
-
handlers: { functions: {}, classes: {}, interfaces: {} },
|
|
91
|
-
})
|
|
92
|
-
const deployed = createDeployment({
|
|
93
|
-
definition,
|
|
94
|
-
issuer: issuer.accept('https://catalog-check.example.dev'),
|
|
95
|
-
bundleHref: 'https://catalog-check.example.dev/domain.bundle.json',
|
|
96
|
-
bindings: { callables: [] },
|
|
97
|
-
}).publication
|
|
86
|
+
const deployed = releaseFor(schema, 'https://catalog-check.example.dev').publication
|
|
98
87
|
const server = Bun.serve({
|
|
99
88
|
port: 0,
|
|
100
89
|
fetch(request) {
|
|
@@ -114,23 +103,14 @@ describe('domain list — canonical Publication check', () => {
|
|
|
114
103
|
),
|
|
115
104
|
).resolves.toMatchObject({
|
|
116
105
|
reachable: true,
|
|
117
|
-
schemaRevision:
|
|
106
|
+
schemaRevision: schemaApi.revision(schema),
|
|
118
107
|
checkError: null,
|
|
119
108
|
})
|
|
120
109
|
})
|
|
121
110
|
|
|
122
111
|
test('rejects a Publication whose origin differs from the catalog entry', async () => {
|
|
123
112
|
const schema = defineSchema('deployed.example.dev', {})
|
|
124
|
-
const
|
|
125
|
-
schema,
|
|
126
|
-
handlers: { functions: {}, classes: {}, interfaces: {} },
|
|
127
|
-
})
|
|
128
|
-
const deployed = createDeployment({
|
|
129
|
-
definition,
|
|
130
|
-
issuer: issuer.accept('https://deployed.example.dev'),
|
|
131
|
-
bundleHref: 'https://deployed.example.dev/domain.bundle.json',
|
|
132
|
-
bindings: { callables: [] },
|
|
133
|
-
}).publication
|
|
113
|
+
const deployed = releaseFor(schema, 'https://deployed.example.dev').publication
|
|
134
114
|
const server = Bun.serve({
|
|
135
115
|
port: 0,
|
|
136
116
|
fetch: () => Response.json(deployed),
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { issuer } from '@astrale-os/sdk/auth'
|
|
3
|
-
import { createDeployment } from '@astrale-os/sdk/deployment'
|
|
4
|
-
import { defineSchema } from '@astrale-os/sdk/schema/v1'
|
|
1
|
+
import { defineSchema } from '@astrale-os/sdk/schema'
|
|
5
2
|
import { afterAll, describe, expect, test } from 'bun:test'
|
|
6
3
|
|
|
4
|
+
import { releaseFor } from '../../__tests__/fixtures/publication'
|
|
7
5
|
import { domainRefFromTarget, isIdentityOverride, probeDeclaredOrigin } from '../domain/install'
|
|
8
6
|
|
|
9
7
|
describe('admin-path target classification', () => {
|
|
@@ -47,16 +45,7 @@ describe('declared-origin Publication probe', () => {
|
|
|
47
45
|
|
|
48
46
|
test('reads origin from a well-formed canonical Publication', async () => {
|
|
49
47
|
const schema = defineSchema('crm.acme.dev', {})
|
|
50
|
-
const
|
|
51
|
-
schema,
|
|
52
|
-
handlers: { functions: {}, classes: {}, interfaces: {} },
|
|
53
|
-
})
|
|
54
|
-
const deployed = createDeployment({
|
|
55
|
-
definition,
|
|
56
|
-
issuer: issuer.accept('https://crm.acme.dev'),
|
|
57
|
-
bundleHref: 'https://crm.acme.dev/domain.bundle.json',
|
|
58
|
-
bindings: { callables: [] },
|
|
59
|
-
}).publication
|
|
48
|
+
const deployed = releaseFor(schema, 'https://crm.acme.dev').publication
|
|
60
49
|
const url = servePublication((req) =>
|
|
61
50
|
new URL(req.url).pathname === '/.well-known/astrale/domain.json'
|
|
62
51
|
? Response.json(deployed)
|
|
@@ -36,6 +36,8 @@ let mutations: unknown[] = []
|
|
|
36
36
|
let queryResult: unknown
|
|
37
37
|
let getResult: unknown
|
|
38
38
|
let mutationResult: unknown
|
|
39
|
+
let selfFailure: unknown
|
|
40
|
+
let selfContexts: unknown[] = []
|
|
39
41
|
|
|
40
42
|
const queryMock = mock(async (ast: unknown, options?: unknown) => {
|
|
41
43
|
queryCalls.push({ ast, options })
|
|
@@ -49,7 +51,9 @@ const mutateMock = mock(async (mutation: unknown) => {
|
|
|
49
51
|
mutations.push(mutation)
|
|
50
52
|
return mutationResult
|
|
51
53
|
})
|
|
52
|
-
const expandSelfInPathMock = mock(async (path: string) => {
|
|
54
|
+
const expandSelfInPathMock = mock(async (path: string, context: unknown) => {
|
|
55
|
+
selfContexts.push(context)
|
|
56
|
+
if (selfFailure !== undefined) throw selfFailure
|
|
53
57
|
if (path === '@self') {
|
|
54
58
|
return {
|
|
55
59
|
path: '@expanded-self',
|
|
@@ -59,10 +63,11 @@ const expandSelfInPathMock = mock(async (path: string) => {
|
|
|
59
63
|
return { path, meta: undefined }
|
|
60
64
|
})
|
|
61
65
|
const withSelfHintMock = mock(async (action: () => Promise<unknown>) => action())
|
|
66
|
+
const commandContext = {
|
|
67
|
+
graph: { query: queryMock, getOrThrow: getOrThrowMock, mutate: mutateMock },
|
|
68
|
+
}
|
|
62
69
|
const runKernelCommandMock = mock(async (run: RunOpts) => {
|
|
63
|
-
const result = await run.fn(
|
|
64
|
-
graph: { query: queryMock, getOrThrow: getOrThrowMock, mutate: mutateMock },
|
|
65
|
-
})
|
|
70
|
+
const result = await run.fn(commandContext)
|
|
66
71
|
await run.format?.(result, run.opts, true)
|
|
67
72
|
})
|
|
68
73
|
|
|
@@ -88,6 +93,8 @@ beforeEach(() => {
|
|
|
88
93
|
}
|
|
89
94
|
getResult = undefined
|
|
90
95
|
mutationResult = { createdNodes: {} }
|
|
96
|
+
selfFailure = undefined
|
|
97
|
+
selfContexts = []
|
|
91
98
|
queryMock.mockClear()
|
|
92
99
|
getOrThrowMock.mockClear()
|
|
93
100
|
mutateMock.mockClear()
|
|
@@ -161,7 +168,7 @@ describe('query command', () => {
|
|
|
161
168
|
])
|
|
162
169
|
})
|
|
163
170
|
|
|
164
|
-
test('authors a
|
|
171
|
+
test('authors a Class source through the same canonical Query V6 call', async () => {
|
|
165
172
|
const { queryCommand } = await import('../query')
|
|
166
173
|
|
|
167
174
|
await queryCommand([], {
|
|
@@ -179,8 +186,8 @@ describe('query command', () => {
|
|
|
179
186
|
kind: 'node',
|
|
180
187
|
terms: [
|
|
181
188
|
{
|
|
182
|
-
kind: '
|
|
183
|
-
|
|
189
|
+
kind: 'class',
|
|
190
|
+
class: { origin: 'issues.astrale.ai', kind: 'class', name: 'Issue' },
|
|
184
191
|
},
|
|
185
192
|
],
|
|
186
193
|
binding: 'n0',
|
|
@@ -193,6 +200,17 @@ describe('query command', () => {
|
|
|
193
200
|
])
|
|
194
201
|
})
|
|
195
202
|
|
|
203
|
+
test('resolves @self inside the command session and never relabels transport failure as input', async () => {
|
|
204
|
+
const { queryCommand } = await import('../query')
|
|
205
|
+
await queryCommand(['@self'], { json: true, limit: '2' })
|
|
206
|
+
expect(selfContexts).toEqual([commandContext])
|
|
207
|
+
|
|
208
|
+
const aggregate = new AggregateError([], '')
|
|
209
|
+
selfFailure = aggregate
|
|
210
|
+
await expect(queryCommand(['@self'], { json: true, limit: '2' })).rejects.toBe(aggregate)
|
|
211
|
+
expect(errors.join('\n')).not.toContain('INVALID_INPUT')
|
|
212
|
+
})
|
|
213
|
+
|
|
196
214
|
/** @evidence TEST-CLI-QUERY-REJECTS-V1-BEFORE-CONNECTION */
|
|
197
215
|
test('rejects a legacy AST before opening the command connection', async () => {
|
|
198
216
|
const { queryCommand } = await import('../query')
|
|
@@ -215,7 +233,7 @@ describe('get command', () => {
|
|
|
215
233
|
const { getCommand } = await import('../get')
|
|
216
234
|
getResult = {
|
|
217
235
|
id: 'note-1',
|
|
218
|
-
class: '
|
|
236
|
+
class: 'notes.example.dev:class.Note',
|
|
219
237
|
props: { 'notes.example.dev:class.Note.property.title': 'Hello' },
|
|
220
238
|
}
|
|
221
239
|
|
|
@@ -226,6 +244,13 @@ describe('get command', () => {
|
|
|
226
244
|
expect(stdout).not.toContain('__labels')
|
|
227
245
|
expect(stdout).not.toContain('classId')
|
|
228
246
|
})
|
|
247
|
+
|
|
248
|
+
test('resolves @self through the same point-read command context', async () => {
|
|
249
|
+
const { getCommand } = await import('../get')
|
|
250
|
+
await getCommand('@self', { json: true })
|
|
251
|
+
expect(selfContexts).toEqual([commandContext])
|
|
252
|
+
expect(getTargets).toEqual(['@expanded-self'])
|
|
253
|
+
})
|
|
229
254
|
})
|
|
230
255
|
|
|
231
256
|
describe('mutate command', () => {
|
|
@@ -242,7 +267,7 @@ describe('mutate command', () => {
|
|
|
242
267
|
{
|
|
243
268
|
op: 'node.create',
|
|
244
269
|
as: 'note',
|
|
245
|
-
class: '
|
|
270
|
+
class: 'notes.example.dev:class.Note',
|
|
246
271
|
props: {},
|
|
247
272
|
},
|
|
248
273
|
],
|
|
@@ -258,7 +283,7 @@ describe('mutate command', () => {
|
|
|
258
283
|
{
|
|
259
284
|
op: 'node.create',
|
|
260
285
|
as: 'note',
|
|
261
|
-
class: '
|
|
286
|
+
class: 'notes.example.dev:class.Note',
|
|
262
287
|
props: {},
|
|
263
288
|
},
|
|
264
289
|
],
|
|
@@ -35,9 +35,11 @@ describe('CLI update staleness', () => {
|
|
|
35
35
|
const result = await cliStale(
|
|
36
36
|
{ channel: 'canary' },
|
|
37
37
|
{
|
|
38
|
-
update: async () => {
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
update: async () => ({
|
|
39
|
+
status: 'managed',
|
|
40
|
+
currentVersion: '1.0.0-beta.0',
|
|
41
|
+
executable: '/opt/homebrew/bin/node',
|
|
42
|
+
}),
|
|
41
43
|
fetchPackageVersion: async ({ channel }) => {
|
|
42
44
|
expect(channel).toBe('canary')
|
|
43
45
|
return '1.0.0-canary.0'
|
|
@@ -52,6 +54,26 @@ describe('CLI update staleness', () => {
|
|
|
52
54
|
})
|
|
53
55
|
})
|
|
54
56
|
|
|
57
|
+
test('does not misclassify a script update failure as package-managed', async () => {
|
|
58
|
+
const fetchPackageVersion = mock(async () => '9.9.9')
|
|
59
|
+
const result = await cliStale(
|
|
60
|
+
{},
|
|
61
|
+
{
|
|
62
|
+
update: async () => {
|
|
63
|
+
throw new Error('release endpoint unavailable')
|
|
64
|
+
},
|
|
65
|
+
fetchPackageVersion,
|
|
66
|
+
},
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
expect(result).toMatchObject({
|
|
70
|
+
stale: false,
|
|
71
|
+
managed: false,
|
|
72
|
+
error: 'release endpoint unavailable',
|
|
73
|
+
})
|
|
74
|
+
expect(fetchPackageVersion).not.toHaveBeenCalled()
|
|
75
|
+
})
|
|
76
|
+
|
|
55
77
|
test('maps the default to beta and the stable channel to npm latest', async () => {
|
|
56
78
|
const originalFetch = globalThis.fetch
|
|
57
79
|
const fetchMock = mock(async (input: RequestInfo | URL) => {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { Path } from '@astrale-os/sdk/graph/path'
|
|
2
|
+
import type { ResolvedFunction, ResolvedMethod } from '@astrale-os/sdk/schema'
|
|
2
3
|
|
|
3
|
-
import {
|
|
4
|
+
import { bundle, schema } from '@astrale-os/sdk/schema'
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
import { AstraleError } from '../errors'
|
|
6
7
|
|
|
7
8
|
export interface CallableDescription {
|
|
8
9
|
readonly path: string
|
|
@@ -18,40 +19,40 @@ export interface CallableDescription {
|
|
|
18
19
|
readonly candidates?: readonly CallableDescription[]
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
/** Resolve one callable
|
|
22
|
-
export function
|
|
22
|
+
/** Resolve one callable from an admitted installed Domain bundle. */
|
|
23
|
+
export function describeCallableFromBundle(
|
|
23
24
|
path: Path,
|
|
24
|
-
|
|
25
|
+
input: unknown,
|
|
25
26
|
): CallableDescription | undefined {
|
|
26
27
|
if (path.ast.anchor.kind !== 'domain') return undefined
|
|
27
28
|
const origin = path.ast.anchor.origin
|
|
28
29
|
const last = path.ast.steps.at(-1)
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
if (last === undefined) return undefined
|
|
31
|
+
const domain = schema.resolve(bundle.accept(input).root)
|
|
32
|
+
if (domain.origin !== origin) return undefined
|
|
31
33
|
|
|
32
34
|
if (last.kind === 'method') {
|
|
33
|
-
const
|
|
34
|
-
if (
|
|
35
|
-
owner
|
|
36
|
-
(owner
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
const ownerStep = path.ast.steps.at(-2)
|
|
36
|
+
if (ownerStep?.kind === 'projection' && ownerStep.projection.kind === 'class') {
|
|
37
|
+
const owner = domain.classes[ownerStep.projection.name]
|
|
38
|
+
if (owner?.kind !== 'node') return undefined
|
|
39
|
+
const method = namedMethod(
|
|
40
|
+
last.dispatch === 'static' ? owner.static.methods : owner.methods,
|
|
41
|
+
last.name,
|
|
42
|
+
last.dispatch,
|
|
40
43
|
)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return Object.freeze({
|
|
45
|
-
path: path.raw,
|
|
46
|
-
origin,
|
|
47
|
-
class: owner.projection.name,
|
|
48
|
-
method: last.name,
|
|
49
|
-
dispatch: last.dispatch,
|
|
50
|
-
...callableFields(method),
|
|
51
|
-
})
|
|
52
|
-
}
|
|
44
|
+
return method === undefined
|
|
45
|
+
? undefined
|
|
46
|
+
: description(path, origin, owner.ref.name, method, last.dispatch)
|
|
53
47
|
}
|
|
54
|
-
|
|
48
|
+
|
|
49
|
+
const matches = Object.values(domain.classes).flatMap((owner) => {
|
|
50
|
+
if (owner.kind !== 'node') return []
|
|
51
|
+
const method = namedMethod(owner.methods, last.name, last.dispatch)
|
|
52
|
+
return method === undefined
|
|
53
|
+
? []
|
|
54
|
+
: [description(path, origin, owner.ref.name, method, last.dispatch)]
|
|
55
|
+
})
|
|
55
56
|
if (matches.length === 1) return matches[0]
|
|
56
57
|
if (matches.length > 1) {
|
|
57
58
|
return Object.freeze({
|
|
@@ -66,13 +67,13 @@ export function describeCallableFromSchema(
|
|
|
66
67
|
}
|
|
67
68
|
|
|
68
69
|
if (last.kind === 'projection' && last.projection.kind === 'function') {
|
|
69
|
-
const
|
|
70
|
-
if (
|
|
70
|
+
const callable = domain.functions[last.projection.name]
|
|
71
|
+
if (callable === undefined) return undefined
|
|
71
72
|
return Object.freeze({
|
|
72
73
|
path: path.raw,
|
|
73
74
|
origin,
|
|
74
|
-
function:
|
|
75
|
-
...callableFields(
|
|
75
|
+
function: callable.ref.name,
|
|
76
|
+
...callableFields(callable),
|
|
76
77
|
})
|
|
77
78
|
}
|
|
78
79
|
return undefined
|
|
@@ -86,46 +87,37 @@ export function missingCallableDescription(path: string): AstraleError {
|
|
|
86
87
|
)
|
|
87
88
|
}
|
|
88
89
|
|
|
89
|
-
function
|
|
90
|
-
|
|
90
|
+
function namedMethod(
|
|
91
|
+
methods: Iterable<ResolvedMethod>,
|
|
92
|
+
name: string,
|
|
93
|
+
dispatch: 'static' | 'instance',
|
|
94
|
+
): ResolvedMethod | undefined {
|
|
95
|
+
const expectedStatic = dispatch === 'static'
|
|
96
|
+
return [...methods].find((method) => method.name === name && method.static === expectedStatic)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function description(
|
|
100
|
+
path: Path,
|
|
91
101
|
origin: string,
|
|
92
|
-
|
|
93
|
-
|
|
102
|
+
className: string,
|
|
103
|
+
callable: ResolvedMethod,
|
|
94
104
|
dispatch: 'static' | 'instance',
|
|
95
|
-
): CallableDescription
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
Object.freeze({
|
|
105
|
-
path,
|
|
106
|
-
origin,
|
|
107
|
-
class: className,
|
|
108
|
-
method,
|
|
109
|
-
dispatch,
|
|
110
|
-
...callableFields(methodDef),
|
|
111
|
-
}),
|
|
112
|
-
)
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
return matches
|
|
105
|
+
): CallableDescription {
|
|
106
|
+
return Object.freeze({
|
|
107
|
+
path: path.raw,
|
|
108
|
+
origin,
|
|
109
|
+
class: className,
|
|
110
|
+
method: callable.name,
|
|
111
|
+
dispatch,
|
|
112
|
+
...callableFields(callable),
|
|
113
|
+
})
|
|
116
114
|
}
|
|
117
115
|
|
|
118
|
-
function callableFields(
|
|
116
|
+
function callableFields(callable: ResolvedFunction | ResolvedMethod): Partial<CallableDescription> {
|
|
119
117
|
return {
|
|
120
|
-
...(
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
118
|
+
...(callable.description === undefined ? {} : { description: callable.description }),
|
|
119
|
+
auth: callable.auth,
|
|
120
|
+
input: callable.input,
|
|
121
|
+
output: callable.output,
|
|
124
122
|
}
|
|
125
123
|
}
|
|
126
|
-
|
|
127
|
-
function asRecord(input: unknown): JsonRecord | undefined {
|
|
128
|
-
return input !== null && typeof input === 'object' && !Array.isArray(input)
|
|
129
|
-
? (input as JsonRecord)
|
|
130
|
-
: undefined
|
|
131
|
-
}
|