@astrale-os/cli 1.0.0-beta.1 → 1.0.0-beta.10
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/README.md +23 -12
- package/dist/astrale.js +51471 -56290
- package/dist/public/connect-core.js +2028 -26846
- package/dist/public/keys/index.js +1755 -40694
- package/dist/public/paths/index.js +859 -39518
- package/dist/types/admin/binding.d.ts +19 -0
- package/dist/types/admin/instance/client.d.ts +22 -0
- package/dist/types/admin/instance/index.d.ts +2 -0
- package/dist/types/admin/instance/model.d.ts +5 -12
- package/dist/types/connection/auth.d.ts +3 -0
- package/dist/types/connection/call.d.ts +3 -0
- package/dist/types/connection/command.d.ts +27 -0
- package/dist/types/connection/credential.d.ts +14 -0
- package/dist/types/connection/errors.d.ts +1 -0
- package/dist/types/connection/exchange.d.ts +9 -0
- package/dist/types/connection/failure/classify.d.ts +2 -0
- package/dist/types/connection/failure/index.d.ts +5 -0
- package/dist/types/connection/failure/model.d.ts +25 -0
- package/dist/types/connection/failure/render.d.ts +3 -0
- package/dist/types/connection/index.d.ts +8 -0
- package/dist/types/connection/reasons.d.ts +37 -0
- package/dist/types/connection/self.d.ts +37 -0
- package/dist/types/connection/session.d.ts +31 -0
- package/dist/types/connection/target.d.ts +38 -0
- package/dist/types/errors.d.ts +1 -1
- package/dist/types/lib/admin-instance.d.ts +17 -0
- package/dist/types/lib/admin-target.d.ts +6 -2
- package/dist/types/lib/failure-debug.d.ts +1 -0
- package/dist/types/lib/idp.d.ts +7 -0
- package/dist/types/lib/instance-target.d.ts +1 -1
- package/dist/types/lib/instance.d.ts +10 -2
- package/dist/types/lib/log.d.ts +5 -3
- package/dist/types/lib/meta.d.ts +2 -2
- package/dist/types/lib/proc.d.ts +43 -0
- package/dist/types/lib/self.d.ts +9 -0
- package/dist/types/lib/update.d.ts +131 -0
- package/package.json +8 -10
- package/src/__tests__/fixtures/publication.ts +20 -0
- package/src/admin/__tests__/binding.test.ts +31 -0
- package/src/admin/__tests__/fixture.ts +101 -0
- package/src/admin/binding.ts +98 -0
- 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 +36 -32
- 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 +39 -164
- package/src/admin/instance/client.ts +35 -124
- package/src/admin/instance/index.ts +1 -2
- package/src/admin/instance/model.ts +11 -20
- package/src/commands/__tests__/admin-instance.test.ts +11 -8
- package/src/commands/__tests__/auth-login.test.ts +54 -1
- package/src/commands/__tests__/call-describe.test.ts +46 -33
- package/src/commands/__tests__/call.test.ts +5 -1
- package/src/commands/__tests__/domain-install-operation.test.ts +12 -7
- package/src/commands/__tests__/domain-install-owned.test.ts +6 -2
- package/src/commands/__tests__/domain-list.test.ts +63 -4
- package/src/commands/__tests__/install-identity-override.test.ts +19 -19
- package/src/commands/__tests__/instance-list-rows.test.ts +1 -1
- package/src/commands/__tests__/instance-status.test.ts +139 -0
- package/src/commands/__tests__/read-commands.test.ts +35 -10
- package/src/commands/__tests__/studio-descriptor.test.ts +22 -0
- package/src/commands/__tests__/update.test.ts +48 -19
- package/src/commands/call-describe.ts +60 -68
- package/src/commands/call.ts +43 -56
- package/src/commands/domain/install.ts +13 -17
- package/src/commands/domain/list.ts +18 -13
- package/src/commands/domain/publish.ts +14 -11
- package/src/commands/domain/uninstall.ts +2 -2
- package/src/commands/get.ts +14 -15
- package/src/commands/identity/__tests__/register.test.ts +3 -3
- package/src/commands/identity/register.ts +5 -4
- package/src/commands/instance/create.ts +8 -16
- package/src/commands/instance/delete.ts +12 -9
- package/src/commands/instance/list.ts +2 -2
- package/src/commands/instance/status.ts +66 -20
- package/src/commands/instance/use.ts +16 -12
- package/src/commands/introspect.ts +9 -16
- package/src/commands/logs.ts +24 -25
- package/src/commands/mutate.ts +6 -5
- package/src/commands/query.ts +27 -30
- package/src/commands/studio.ts +20 -0
- package/src/commands/token.ts +8 -7
- package/src/commands/update.ts +38 -14
- package/src/commands/view.ts +7 -6
- 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 +20 -1
- package/src/connection/__tests__/errors.test.ts +43 -32
- package/src/connection/__tests__/exchange.test.ts +36 -6
- 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/__tests__/target.test.ts +1 -0
- package/src/connection/auth.ts +13 -0
- 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 +52 -27
- package/src/connection/failure/classify.ts +110 -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 +19 -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/keys/__tests__/keys.test.ts +4 -0
- package/src/keys/credential.ts +1 -0
- package/src/lib/__tests__/admin-target.test.ts +12 -0
- package/src/lib/__tests__/command-dx.test.ts +1 -1
- package/src/lib/__tests__/domain-publication.test.ts +138 -0
- package/src/lib/__tests__/idp-session.test.ts +22 -0
- package/src/lib/__tests__/idp.test.ts +36 -4
- package/src/lib/__tests__/instance-candidates.test.ts +1 -3
- package/src/lib/__tests__/instance-target.test.ts +7 -39
- package/src/lib/__tests__/instance.test.ts +6 -0
- package/src/lib/__tests__/log-errors.test.ts +64 -0
- package/src/lib/__tests__/studio-server-deps.test.ts +53 -16
- package/src/lib/__tests__/update.test.ts +113 -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/admin-instance.ts +14 -8
- package/src/lib/admin-target.ts +21 -2
- package/src/lib/command-dx.ts +9 -9
- package/src/lib/domain-publication.ts +104 -0
- package/src/lib/failure-debug.ts +26 -0
- package/src/lib/idp.ts +39 -4
- package/src/lib/instance-candidates.ts +2 -2
- package/src/lib/instance-target.ts +3 -14
- package/src/lib/instance.ts +22 -12
- package/src/lib/log.ts +16 -9
- package/src/lib/login-flow.ts +13 -3
- package/src/lib/meta.ts +2 -2
- package/src/lib/provision-instance.ts +34 -57
- package/src/lib/update.ts +124 -30
- package/src/lib/validation.ts +2 -2
- package/src/lib/view/resolve.ts +1 -1
- package/src/program/__tests__/program.test.ts +20 -4
- package/src/program/build.ts +2 -2
- package/src/setup/__tests__/instance-step.test.ts +27 -10
- package/src/setup/steps/instance.ts +22 -15
- package/studio/client/dist/assets/{elk-api-D2xgMJvi.js → elk-api-ByzoDZWH.js} +1 -1
- package/studio/client/dist/assets/index-B0RCgUOT.js +8 -0
- package/studio/client/dist/assets/index-BiGR8Oo9.css +1 -0
- package/studio/client/dist/assets/index-N8J8EKlB.js +81 -0
- package/studio/client/dist/index.html +2 -2
- package/studio/package.json +5 -10
- 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/bridge/stdio.ts +8 -1
- package/studio/server/agent/conversation.test.ts +10 -5
- package/studio/server/agent/conversation.ts +56 -8
- package/studio/server/agent/harness/claude/adapter.test.ts +15 -5
- package/studio/server/agent/harness/codex/loadout.ts +18 -21
- package/studio/server/agent/harness/gateway/config.ts +20 -18
- package/studio/server/agent/harness/selection.ts +9 -1
- 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 +6 -5
- package/studio/server/agent/prompts/turn.ts +13 -4
- package/studio/server/agent/routes.test.ts +1 -1
- package/studio/server/agent/run/completion.ts +2 -2
- package/studio/server/agent/run/coordinator.test.ts +1 -1
- package/studio/server/agent/run/preparation.ts +6 -5
- package/studio/server/agent/run/transcript.test.ts +35 -1
- package/studio/server/agent/run/transcript.ts +169 -3
- package/studio/server/agent/run/usage.test.ts +24 -0
- package/studio/server/agent/run/usage.ts +26 -1
- package/studio/server/api/canvas.ts +43 -0
- package/studio/server/api/comments.ts +85 -0
- package/studio/server/api/context.ts +61 -0
- package/studio/server/api/deployment.ts +39 -0
- package/studio/server/api/documents.ts +55 -0
- package/studio/server/api/domain.ts +59 -0
- package/studio/server/api/http.ts +45 -0
- package/studio/server/api/project.ts +57 -0
- package/studio/server/api/schema.ts +12 -0
- package/studio/server/api/views.ts +57 -0
- package/studio/server/api/workspace.ts +60 -0
- package/studio/server/api-agent-loadout.test.ts +1 -1
- package/studio/server/api.test.ts +147 -0
- package/studio/server/api.ts +20 -422
- package/studio/server/cache.test.ts +122 -0
- package/studio/server/cache.ts +162 -11
- package/studio/server/cli-consumers.test.ts +494 -0
- package/studio/server/cli.test.ts +88 -0
- package/studio/server/cli.ts +240 -0
- package/studio/server/client-package.ts +25 -1
- package/studio/server/domain.test.ts +50 -40
- package/studio/server/domain.ts +83 -52
- package/studio/server/environment/dotenv-preview.test.ts +39 -0
- package/studio/server/environment/dotenv-preview.ts +27 -0
- package/studio/server/environment/files.test.ts +53 -0
- package/studio/server/{state/env.ts → environment/files.ts} +7 -48
- package/studio/server/{state → handoff}/copy.ts +21 -6
- package/studio/server/handoff/service.test.ts +22 -0
- package/studio/server/{state/handoff.ts → handoff/service.ts} +21 -14
- package/studio/server/index.ts +1 -1
- package/studio/server/instances/active.ts +72 -0
- package/studio/server/instances/deploy-record.test.ts +31 -0
- package/studio/server/instances/deploy-record.ts +37 -0
- package/studio/server/instances/deploy.ts +56 -0
- package/studio/server/{state/instance.test.ts → instances/probe.test.ts} +25 -21
- package/studio/server/instances/probe.ts +67 -0
- package/studio/server/instances/status.test.ts +12 -0
- package/studio/server/instances/status.ts +49 -0
- package/studio/server/introspect/anatomy/client-tree.ts +57 -0
- package/studio/server/introspect/anatomy/env-fields.ts +66 -0
- package/studio/server/introspect/anatomy/schema-definition.ts +53 -0
- package/studio/server/introspect/anatomy/source.ts +181 -0
- package/studio/server/introspect/anatomy/views/routes.ts +114 -0
- package/studio/server/introspect/anatomy/views.ts +53 -0
- package/studio/server/introspect/anatomy-extras.test.ts +106 -35
- package/studio/server/introspect/anatomy-extras.ts +7 -726
- package/studio/server/introspect/anatomy.test.ts +22 -14
- package/studio/server/introspect/anatomy.ts +52 -28
- package/studio/server/introspect/bundle.ts +15 -9
- package/studio/server/introspect/canonical-schema.test.ts +93 -309
- package/studio/server/introspect/canonical-schema.ts +257 -425
- package/studio/server/introspect/config-preview.test.ts +32 -0
- package/studio/server/introspect/config-preview.ts +119 -0
- package/studio/server/introspect/core-extractor.ts +18 -127
- package/studio/server/introspect/core.ts +1 -2
- package/studio/server/introspect/diff.test.ts +18 -18
- package/studio/server/introspect/diff.ts +44 -90
- package/studio/server/introspect/extractor.ts +23 -116
- package/studio/server/introspect/hash.ts +5 -2
- package/studio/server/introspect/overlay-tsmorph.test.ts +119 -240
- package/studio/server/introspect/overlay-tsmorph.ts +7 -1305
- package/studio/server/introspect/overlay.test.ts +26 -54
- package/studio/server/introspect/overlay.ts +10 -37
- package/studio/server/introspect/revision.test.ts +54 -0
- package/studio/server/introspect/revision.ts +49 -0
- package/studio/server/introspect/runtime.test.ts +83 -143
- package/studio/server/introspect/runtime.ts +40 -11
- package/studio/server/introspect/schema-ir-json.test.ts +70 -0
- package/studio/server/introspect/schema-ir-json.ts +151 -0
- 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/annotations.ts +14 -0
- package/studio/server/introspect/source-overlay/handlers.ts +161 -0
- package/studio/server/introspect/source-overlay/kernel-calls.ts +46 -0
- package/studio/server/introspect/source-overlay/project.ts +248 -0
- package/studio/server/introspect/source-overlay/spans.ts +330 -0
- package/studio/server/json.ts +46 -0
- package/studio/server/lifecycle.ts +5 -1
- package/studio/server/sse.test.ts +26 -0
- package/studio/server/sse.ts +4 -1
- package/studio/server/state/baseline.test.ts +223 -7
- package/studio/server/state/baseline.ts +148 -34
- package/studio/server/state/comments.test.ts +66 -1
- package/studio/server/state/comments.ts +173 -10
- package/studio/server/state/context.ts +34 -2
- package/studio/server/state/documents.ts +42 -1
- package/studio/server/state/integrations.ts +27 -1
- package/studio/server/state/layout.test.ts +34 -0
- package/studio/server/state/layout.ts +44 -17
- package/studio/server/state/settings.ts +29 -22
- package/studio/server/state/store.test.ts +122 -0
- package/studio/server/state/store.ts +66 -17
- package/studio/server/state/visibility.ts +22 -11
- package/studio/server/views/model.test.ts +57 -0
- package/studio/server/views/model.ts +66 -0
- package/studio/server/views/runtime.ts +40 -0
- package/studio/server/views/selection-repository.test.ts +31 -0
- package/studio/server/views/selection-repository.ts +60 -0
- package/studio/server/views/session.test.ts +73 -0
- package/studio/server/views/session.ts +166 -0
- package/studio/server/views/target.test.ts +78 -0
- package/studio/server/views/target.ts +222 -0
- package/studio/server/watch.test.ts +11 -11
- package/studio/server/watch.ts +9 -5
- package/studio/server/workspace/catalog.test.ts +17 -0
- package/studio/server/workspace/catalog.ts +43 -0
- package/studio/server/{state → workspace}/create.test.ts +1 -1
- package/studio/server/{state → workspace}/create.ts +1 -1
- package/studio/server/{state → workspace}/git.ts +1 -1
- package/studio/server/workspace/updates.ts +83 -0
- package/studio/server/workspace-state.ts +1 -1
- package/studio/server/workspace-watch.ts +2 -2
- package/studio/shared/contracts/README.md +16 -0
- package/studio/shared/contracts/agent.ts +270 -0
- package/studio/shared/contracts/runtime.ts +50 -0
- package/studio/shared/contracts/schema.ts +393 -0
- package/studio/shared/contracts/surface.test.ts +317 -0
- package/studio/shared/contracts/workspace.ts +265 -0
- package/studio/shared/layout.test.ts +116 -0
- package/studio/shared/schema/identity.test.ts +34 -0
- package/studio/shared/schema/identity.ts +68 -0
- package/studio/shared/types.ts +11 -1099
- package/studio/tsconfig.json +1 -1
- package/viewer/dist/main.js +40 -61
- package/.check-workspace.cjs +0 -40
- package/src/commands/__tests__/instance-create-hosts.test.ts +0 -29
- package/studio/client/dist/assets/index-BMdnsIJA.css +0 -1
- package/studio/client/dist/assets/index-D-vRV8w7.js +0 -8
- package/studio/client/dist/assets/index-LGSWRrk8.js +0 -81
- package/studio/server/state/catalog.ts +0 -117
- package/studio/server/state/instance.ts +0 -280
- package/studio/server/state/updates.ts +0 -63
- package/studio/server/state/views.test.ts +0 -286
- package/studio/server/state/views.ts +0 -535
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { issuer, jwk, provision } from '@astrale-os/sdk/auth'
|
|
2
|
-
import { ClassPath } from '@astrale-os/sdk/graph/class'
|
|
3
2
|
import { normalizeProperties } from '@astrale-os/sdk/graph/properties'
|
|
4
3
|
import { expect, mock, test } from 'bun:test'
|
|
5
4
|
import { exportJWK, generateKeyPair, jwtVerify } from 'jose'
|
|
6
5
|
|
|
6
|
+
import { classKey } from '../../../graph'
|
|
7
7
|
import { formatIdentityRegistration, prepareIdentityProvision } from '../register'
|
|
8
8
|
|
|
9
9
|
/** @evidence TEST-CLI-IDENTITY-REGISTER-JSON-EXACT */
|
|
@@ -46,7 +46,7 @@ test('builds one exact Mutation V3 identity birth bound to a self proof', async
|
|
|
46
46
|
kid: 'alice-key',
|
|
47
47
|
})
|
|
48
48
|
const kernelIssuer = issuer.accept('https://kernel.example')
|
|
49
|
-
const classPath =
|
|
49
|
+
const classPath = classKey('/:accounts.example:class.User', '--class')
|
|
50
50
|
const properties = normalizeProperties({
|
|
51
51
|
'accounts.example:class.User.property.name': 'Alice',
|
|
52
52
|
})
|
|
@@ -70,7 +70,7 @@ test('builds one exact Mutation V3 identity birth bound to a self proof', async
|
|
|
70
70
|
{
|
|
71
71
|
op: 'node.create',
|
|
72
72
|
as: 'identity',
|
|
73
|
-
class: '
|
|
73
|
+
class: 'accounts.example:class.User',
|
|
74
74
|
props: { 'accounts.example:class.User.property.name': 'Alice' },
|
|
75
75
|
},
|
|
76
76
|
],
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { IssuerId, JsonWebKey, ProvisionRequest } from '@astrale-os/sdk/auth'
|
|
2
|
+
import type { ClassKey as ClassKeyValue } from '@astrale-os/sdk/graph/class'
|
|
2
3
|
import type { JWK } from 'jose'
|
|
3
4
|
|
|
4
5
|
import { provision, jwk } from '@astrale-os/sdk/auth'
|
|
5
|
-
import {
|
|
6
|
-
import { LocalBinding } from '@astrale-os/sdk/graph/model'
|
|
6
|
+
import { LocalBinding } from '@astrale-os/sdk/graph'
|
|
7
7
|
import { normalizeProperties } from '@astrale-os/sdk/graph/properties'
|
|
8
8
|
import { MutationAST } from '@astrale-os/sdk/mutation'
|
|
9
9
|
import { importJWK, SignJWT } from 'jose'
|
|
@@ -14,6 +14,7 @@ import type { IdentityRegistrationResult } from '../../identity/index'
|
|
|
14
14
|
import type { CommandDefinition } from '../../program/index'
|
|
15
15
|
|
|
16
16
|
import { registrationKeyForTarget, runKernelCommand } from '../../connection'
|
|
17
|
+
import { classKey } from '../../graph'
|
|
17
18
|
import { getIdentity, setRegistration, submitIdentityProvision } from '../../identity/index'
|
|
18
19
|
import { fileExists, keypairPaths } from '../../keys/index'
|
|
19
20
|
import { fatal, log } from '../../lib/log'
|
|
@@ -83,7 +84,7 @@ Example:
|
|
|
83
84
|
|
|
84
85
|
const privateKey = await readJwk(privatePath)
|
|
85
86
|
const publicKey = jwk.acceptPublic(await readJwk(publicPath))
|
|
86
|
-
const classPath =
|
|
87
|
+
const classPath = classKey(opts.class, '--class')
|
|
87
88
|
const properties = normalizeProperties(opts.props ? JSON.parse(opts.props) : {})
|
|
88
89
|
|
|
89
90
|
await runKernelCommand<IdentityRegistrationResult>({
|
|
@@ -142,7 +143,7 @@ export function formatIdentityRegistration(
|
|
|
142
143
|
/** Build and self-prove one exact canonical provision request for the target Kernel. */
|
|
143
144
|
export async function prepareIdentityProvision(input: {
|
|
144
145
|
readonly name: string
|
|
145
|
-
readonly classPath:
|
|
146
|
+
readonly classPath: ClassKeyValue
|
|
146
147
|
readonly properties: ReturnType<typeof normalizeProperties>
|
|
147
148
|
readonly privateKey: JWK
|
|
148
149
|
readonly publicKey: JsonWebKey
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import type { CommandDefinition } from '../../program/index'
|
|
2
2
|
|
|
3
|
+
import { formatKernelError } from '../../connection/errors'
|
|
3
4
|
import { ADMIN_TARGET_OPTIONS } from '../../lib/admin-target'
|
|
4
|
-
import { fatal } from '../../lib/log'
|
|
5
5
|
import { isMachine, output } from '../../lib/output'
|
|
6
6
|
import { promptText } from '../../lib/prompt'
|
|
7
7
|
import { provisionInstance, type ProvisionOpts } from '../../lib/provision-instance'
|
|
8
8
|
import { validateSlug } from '../../lib/validation'
|
|
9
9
|
|
|
10
|
-
// Re-exported for tests + `astrale setup`, which share the provisioning saga.
|
|
11
|
-
export { assertAlphaCreateIdentity, parseEligibleHostIds } from '../../lib/provision-instance'
|
|
12
|
-
|
|
13
10
|
/** inquirer `validate` for a slug: true when valid, else the human message. */
|
|
14
11
|
function slugError(value: string): true | string {
|
|
15
12
|
try {
|
|
@@ -22,12 +19,12 @@ function slugError(value: string): true | string {
|
|
|
22
19
|
|
|
23
20
|
export default {
|
|
24
21
|
name: 'create',
|
|
25
|
-
description: 'Provision an
|
|
22
|
+
description: 'Provision an instance through the Admin control plane',
|
|
26
23
|
afterHelpText: `
|
|
27
24
|
Behavior:
|
|
28
|
-
|
|
29
|
-
logged in with WorkOS.
|
|
30
|
-
|
|
25
|
+
Requests a new Instance from the configured Admin Domain. The caller must be
|
|
26
|
+
logged in with WorkOS. Admin owns infrastructure placement. The new instance
|
|
27
|
+
becomes the active instance.
|
|
31
28
|
|
|
32
29
|
Run with no slug in a terminal and it prompts for one (validated live). With
|
|
33
30
|
no TTY — or --ci / --no-prompt — the slug argument is required up front, so
|
|
@@ -38,13 +35,7 @@ Examples:
|
|
|
38
35
|
$ astrale instance create demo
|
|
39
36
|
`,
|
|
40
37
|
arguments: [{ name: 'id', description: 'Instance slug', required: false }],
|
|
41
|
-
options: [
|
|
42
|
-
...ADMIN_TARGET_OPTIONS,
|
|
43
|
-
{
|
|
44
|
-
flags: '--host-id <id>',
|
|
45
|
-
description: 'Advanced: host node id to provision on when multiple hosts are available',
|
|
46
|
-
},
|
|
47
|
-
],
|
|
38
|
+
options: [...ADMIN_TARGET_OPTIONS],
|
|
48
39
|
action: async (id: string | undefined, opts: ProvisionOpts) => {
|
|
49
40
|
try {
|
|
50
41
|
// Interactive (TTY only): prompt for the slug when omitted, with live
|
|
@@ -63,7 +54,8 @@ Examples:
|
|
|
63
54
|
return
|
|
64
55
|
}
|
|
65
56
|
} catch (e) {
|
|
66
|
-
|
|
57
|
+
await formatKernelError(e, isMachine(opts), undefined, opts.debug)
|
|
58
|
+
process.exit(1)
|
|
67
59
|
}
|
|
68
60
|
},
|
|
69
61
|
} satisfies CommandDefinition
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { KernelCommandOpts } from '../../connection'
|
|
2
2
|
import type { CommandDefinition } from '../../program/index'
|
|
3
3
|
|
|
4
|
+
import { AdminInstanceNotFoundError } from '../../admin/instance'
|
|
5
|
+
import { formatKernelError } from '../../connection/errors'
|
|
4
6
|
import { deleteOwnedInstance } from '../../lib/admin-instance'
|
|
5
7
|
import { ADMIN_TARGET_OPTIONS, type AdminTargetCommandOpts } from '../../lib/admin-target'
|
|
6
8
|
import { clearActive, readInstances, removeInstance, resolveInstanceKey } from '../../lib/instance'
|
|
7
|
-
import {
|
|
9
|
+
import { log, withSpinner } from '../../lib/log'
|
|
8
10
|
import { isMachine, output } from '../../lib/output'
|
|
9
11
|
|
|
10
12
|
type DeleteOpts = KernelCommandOpts &
|
|
@@ -18,10 +20,9 @@ export default {
|
|
|
18
20
|
afterHelpText: `
|
|
19
21
|
Behavior:
|
|
20
22
|
Calls Instance.delete on the configured admin kernel: best-effort decommission
|
|
21
|
-
of the instance's
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
after the delete succeeds unless --keep-bookmark is passed.
|
|
23
|
+
of the instance's route and tenant reservation, then removes the Instance
|
|
24
|
+
projection. A same-name local bookmark is removed after the delete succeeds
|
|
25
|
+
unless --keep-bookmark is passed.
|
|
25
26
|
`,
|
|
26
27
|
arguments: [{ name: 'id', description: 'Instance slug', required: true }],
|
|
27
28
|
options: [
|
|
@@ -53,14 +54,16 @@ Behavior:
|
|
|
53
54
|
} catch (e) {
|
|
54
55
|
// Bookmark-only id → no admin Instance → kernel NOT_FOUND. Point to
|
|
55
56
|
// `forget` (local drop) instead of surfacing the raw path error.
|
|
56
|
-
|
|
57
|
-
e instanceof
|
|
58
|
-
|
|
57
|
+
if (
|
|
58
|
+
e instanceof AdminInstanceNotFoundError &&
|
|
59
|
+
resolveInstanceKey(await readInstances(), id)
|
|
60
|
+
) {
|
|
59
61
|
log.error(`No admin-managed instance "${id}".`)
|
|
60
62
|
log.dim(` hint: it's a local bookmark — drop it with: astrale instance forget ${id}`)
|
|
61
63
|
process.exit(1)
|
|
62
64
|
}
|
|
63
|
-
|
|
65
|
+
await formatKernelError(e, isMachine(opts), undefined, opts.debug)
|
|
66
|
+
process.exit(1)
|
|
64
67
|
}
|
|
65
68
|
},
|
|
66
69
|
} satisfies CommandDefinition
|
|
@@ -7,7 +7,7 @@ import type { CommandDefinition } from '../../program/index'
|
|
|
7
7
|
import { AstraleError } from '../../errors'
|
|
8
8
|
import { listOwnedInstances } from '../../lib/admin-instance'
|
|
9
9
|
import {
|
|
10
|
-
|
|
10
|
+
formatInstanceState,
|
|
11
11
|
type InstanceInfo,
|
|
12
12
|
type OwnedInstanceInfo,
|
|
13
13
|
} from '../../lib/admin-instance'
|
|
@@ -136,7 +136,7 @@ export function buildInstanceRows(
|
|
|
136
136
|
name: twin?.active ? `${item.slug} ${chalk.green('*')}` : item.slug,
|
|
137
137
|
kind: 'managed',
|
|
138
138
|
url: item.url ?? '',
|
|
139
|
-
extra: [
|
|
139
|
+
extra: [formatInstanceState(item), twin ? formatBookmarkConnection(twin) : '']
|
|
140
140
|
.filter(Boolean)
|
|
141
141
|
.join(' · '),
|
|
142
142
|
})
|
|
@@ -3,44 +3,90 @@ import chalk from 'chalk'
|
|
|
3
3
|
import type { KernelCommandOpts } from '../../connection'
|
|
4
4
|
import type { CommandDefinition } from '../../program/index'
|
|
5
5
|
|
|
6
|
+
import { formatKernelError } from '../../connection/errors'
|
|
6
7
|
import { AstraleError } from '../../errors'
|
|
7
|
-
import { statusOwnedInstance } from '../../lib/admin-instance'
|
|
8
|
+
import { statusOwnedInstance, type InstanceInfo } from '../../lib/admin-instance'
|
|
8
9
|
import { ADMIN_TARGET_OPTIONS, type AdminTargetCommandOpts } from '../../lib/admin-target'
|
|
9
|
-
import {
|
|
10
|
+
import { resolveInstance } from '../../lib/instance'
|
|
11
|
+
import { log, withSpinner } from '../../lib/log'
|
|
10
12
|
import { isMachine, output, type RawOutputOpts } from '../../lib/output'
|
|
13
|
+
import { probeBookmark } from './use'
|
|
11
14
|
|
|
12
|
-
type StatusOpts = KernelCommandOpts &
|
|
15
|
+
type StatusOpts = KernelCommandOpts &
|
|
16
|
+
AdminTargetCommandOpts &
|
|
17
|
+
RawOutputOpts & { bookmarked?: boolean }
|
|
18
|
+
|
|
19
|
+
interface BookmarkStatus {
|
|
20
|
+
readonly slug: string
|
|
21
|
+
readonly url: string
|
|
22
|
+
readonly issuer: string
|
|
23
|
+
readonly kind: 'bookmark'
|
|
24
|
+
readonly state: 'ready'
|
|
25
|
+
}
|
|
13
26
|
|
|
14
27
|
export default {
|
|
15
28
|
name: 'status',
|
|
16
|
-
description: 'Show
|
|
29
|
+
description: 'Show managed instance status or probe a bookmark',
|
|
17
30
|
arguments: [{ name: 'id', description: 'Instance slug', required: true }],
|
|
18
|
-
options: [
|
|
31
|
+
options: [
|
|
32
|
+
...ADMIN_TARGET_OPTIONS,
|
|
33
|
+
{ flags: '--bookmarked', description: 'Probe a locally bookmarked kernel connection' },
|
|
34
|
+
],
|
|
19
35
|
action: async (id: string, opts: StatusOpts) => {
|
|
20
36
|
try {
|
|
21
37
|
const result = await withSpinner(`Fetching instance ${id}`, !isMachine(opts), () =>
|
|
22
|
-
|
|
23
|
-
if (!(error instanceof Error) || error.name !== 'NotFoundError') throw error
|
|
24
|
-
throw new AstraleError(
|
|
25
|
-
'INSTANCE_NOT_FOUND',
|
|
26
|
-
`No owned instance matches "${id}".`,
|
|
27
|
-
'Run `astrale instance list` to see your instances.',
|
|
28
|
-
)
|
|
29
|
-
}),
|
|
38
|
+
resolveStatus(id, opts),
|
|
30
39
|
)
|
|
31
40
|
if (isMachine(opts)) {
|
|
32
41
|
output(result, opts)
|
|
33
42
|
return
|
|
34
43
|
}
|
|
35
44
|
console.log(`${chalk.bold(result.slug)} ${chalk.dim(result.url)}`)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if (result.
|
|
39
|
-
if (result
|
|
40
|
-
|
|
41
|
-
if (result.createdAt) log.dim(` created: ${result.createdAt}`)
|
|
45
|
+
const phase = 'phase' in result ? result.phase : undefined
|
|
46
|
+
log.dim(` state: ${result.state}${phase ? ` (${phase})` : ''}`)
|
|
47
|
+
if ('error' in result && result.error) log.dim(` error: ${result.error}`)
|
|
48
|
+
if ('organizationId' in result && result.organizationId)
|
|
49
|
+
log.dim(` organization: ${result.organizationId}`)
|
|
50
|
+
if ('createdAt' in result && result.createdAt) log.dim(` created: ${result.createdAt}`)
|
|
42
51
|
} catch (e) {
|
|
43
|
-
|
|
52
|
+
await formatKernelError(e, isMachine(opts), undefined, opts.debug)
|
|
53
|
+
process.exit(1)
|
|
44
54
|
}
|
|
45
55
|
},
|
|
46
56
|
} satisfies CommandDefinition
|
|
57
|
+
|
|
58
|
+
export interface StatusDependencies {
|
|
59
|
+
readonly statusOwnedInstance: typeof statusOwnedInstance
|
|
60
|
+
readonly resolveInstance: typeof resolveInstance
|
|
61
|
+
readonly probeBookmark: typeof probeBookmark
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const defaultStatusDependencies: StatusDependencies = Object.freeze({
|
|
65
|
+
statusOwnedInstance,
|
|
66
|
+
resolveInstance,
|
|
67
|
+
probeBookmark,
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
export async function resolveStatus(
|
|
71
|
+
id: string,
|
|
72
|
+
opts: StatusOpts,
|
|
73
|
+
dependencies: StatusDependencies = defaultStatusDependencies,
|
|
74
|
+
): Promise<InstanceInfo | BookmarkStatus> {
|
|
75
|
+
if (!opts.bookmarked) return dependencies.statusOwnedInstance(opts, id)
|
|
76
|
+
if (opts.admin !== undefined || opts.adminUrl !== undefined || opts.domainIssuer !== undefined) {
|
|
77
|
+
throw new AstraleError(
|
|
78
|
+
'INVALID_FLAG',
|
|
79
|
+
'--bookmarked cannot be combined with Admin target options.',
|
|
80
|
+
'Remove --bookmarked to inspect managed lifecycle, or remove the Admin options to probe a local bookmark.',
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
const bookmark = await dependencies.resolveInstance(id, undefined, { persist: false })
|
|
84
|
+
await dependencies.probeBookmark(bookmark)
|
|
85
|
+
return Object.freeze({
|
|
86
|
+
slug: bookmark.name,
|
|
87
|
+
url: bookmark.url,
|
|
88
|
+
issuer: bookmark.issuer ?? bookmark.url,
|
|
89
|
+
kind: 'bookmark',
|
|
90
|
+
state: 'ready',
|
|
91
|
+
})
|
|
92
|
+
}
|
|
@@ -3,7 +3,7 @@ import type { CommandDefinition } from '../../program/index'
|
|
|
3
3
|
|
|
4
4
|
import { AstraleError } from '../../errors'
|
|
5
5
|
import { getDefault, setDefault } from '../../identity/index'
|
|
6
|
-
import {
|
|
6
|
+
import { listOwnedInstancesWithIdentity } from '../../lib/admin-instance'
|
|
7
7
|
import { ADMIN_TARGET_OPTIONS } from '../../lib/admin-target'
|
|
8
8
|
import { fetchWithCaFile } from '../../lib/ca-fetch'
|
|
9
9
|
import {
|
|
@@ -143,7 +143,7 @@ const defaultBookmarkProbeDependencies: BookmarkProbeDependencies = Object.freez
|
|
|
143
143
|
|
|
144
144
|
async function resolveUseTarget(name: string, opts: UseOpts): Promise<ResolvedInstance> {
|
|
145
145
|
const [store, managed] = await Promise.all([readInstances(), fetchManagedInstances(name, opts)])
|
|
146
|
-
const candidates = collectInstanceCandidates(name, store, managed)
|
|
146
|
+
const candidates = collectInstanceCandidates(name, store, managed.instances)
|
|
147
147
|
|
|
148
148
|
if (candidates.length === 0) {
|
|
149
149
|
throw new AstraleError(
|
|
@@ -168,12 +168,13 @@ async function resolveUseTarget(name: string, opts: UseOpts): Promise<ResolvedIn
|
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
assertManagedReady(chosen.info)
|
|
171
|
-
const { repointedFrom } = await upsertManagedBookmark(
|
|
172
|
-
chosen.key,
|
|
173
|
-
chosen.info.slug,
|
|
174
|
-
chosen.url,
|
|
175
|
-
chosen.info.organizationId,
|
|
176
|
-
|
|
171
|
+
const { repointedFrom } = await upsertManagedBookmark({
|
|
172
|
+
key: chosen.key,
|
|
173
|
+
slug: chosen.info.slug,
|
|
174
|
+
url: chosen.url,
|
|
175
|
+
...(chosen.info.organizationId ? { organizationId: chosen.info.organizationId } : {}),
|
|
176
|
+
...(managed.identity ? { defaultIdentity: managed.identity } : {}),
|
|
177
|
+
})
|
|
177
178
|
if (repointedFrom) {
|
|
178
179
|
log.warn(`Bookmark "${chosen.key}" repointed: ${repointedFrom} → ${chosen.url}`)
|
|
179
180
|
}
|
|
@@ -185,16 +186,19 @@ async function resolveUseTarget(name: string, opts: UseOpts): Promise<ResolvedIn
|
|
|
185
186
|
* Best-effort: an unreachable or unauthenticated admin kernel degrades to
|
|
186
187
|
* bookmark-only resolution.
|
|
187
188
|
*/
|
|
188
|
-
async function fetchManagedInstances(
|
|
189
|
+
async function fetchManagedInstances(
|
|
190
|
+
name: string,
|
|
191
|
+
opts: UseOpts,
|
|
192
|
+
): Promise<{ readonly instances: OwnedInstanceInfo[]; readonly identity?: string }> {
|
|
189
193
|
try {
|
|
190
194
|
validateSlug(name)
|
|
191
195
|
} catch {
|
|
192
|
-
return []
|
|
196
|
+
return { instances: [] }
|
|
193
197
|
}
|
|
194
198
|
try {
|
|
195
|
-
return await
|
|
199
|
+
return await listOwnedInstancesWithIdentity(opts)
|
|
196
200
|
} catch {
|
|
197
|
-
return []
|
|
201
|
+
return { instances: [] }
|
|
198
202
|
}
|
|
199
203
|
}
|
|
200
204
|
|
|
@@ -5,9 +5,9 @@ import type { CommandDefinition } from '../program/index'
|
|
|
5
5
|
|
|
6
6
|
import { runKernelCommand } from '../connection'
|
|
7
7
|
import { AstraleError } from '../errors'
|
|
8
|
-
import {
|
|
8
|
+
import { failInput } from '../lib/log'
|
|
9
9
|
import { output } from '../lib/output'
|
|
10
|
-
import {
|
|
10
|
+
import { describeCallableFromBundle, missingCallableDescription } from './call-describe'
|
|
11
11
|
|
|
12
12
|
type IntrospectOpts = KernelCommandOpts & { bundle?: boolean }
|
|
13
13
|
|
|
@@ -17,7 +17,7 @@ export async function introspectCommand(target: string, opts: IntrospectOpts): P
|
|
|
17
17
|
try {
|
|
18
18
|
;({ origin, path } = parseIntrospectTarget(target))
|
|
19
19
|
} catch (error) {
|
|
20
|
-
|
|
20
|
+
failInput(error, opts)
|
|
21
21
|
}
|
|
22
22
|
const wantsCallable = isCallablePath(path)
|
|
23
23
|
|
|
@@ -44,7 +44,7 @@ export async function introspectCommand(target: string, opts: IntrospectOpts): P
|
|
|
44
44
|
)
|
|
45
45
|
}
|
|
46
46
|
if (wantsCallable) {
|
|
47
|
-
const described =
|
|
47
|
+
const described = describeCallableFromBundle(path, result.bundle)
|
|
48
48
|
if (described === undefined) throw missingCallableDescription(path.raw)
|
|
49
49
|
return described
|
|
50
50
|
}
|
|
@@ -59,7 +59,7 @@ export function parseIntrospectTarget(target: string): { origin: string; path: P
|
|
|
59
59
|
throw new AstraleError(
|
|
60
60
|
'NOT_A_DOMAIN',
|
|
61
61
|
'introspect requires a Domain origin or Path, not an @id.',
|
|
62
|
-
'Example: astrale introspect
|
|
62
|
+
'Example: astrale introspect kernel.astrale.ai or /:kernel.astrale.ai:class.Identity:whois',
|
|
63
63
|
)
|
|
64
64
|
}
|
|
65
65
|
const raw = target.startsWith('/') ? target : `/:${target}`
|
|
@@ -85,28 +85,21 @@ function isCallablePath(path: Path): boolean {
|
|
|
85
85
|
return last.kind === 'projection' && last.projection.kind === 'function'
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
function bundleRoot(bundle: unknown): unknown {
|
|
89
|
-
if (bundle !== null && typeof bundle === 'object' && 'root' in bundle) {
|
|
90
|
-
return (bundle as { root: unknown }).root
|
|
91
|
-
}
|
|
92
|
-
return bundle
|
|
93
|
-
}
|
|
94
|
-
|
|
95
88
|
export default {
|
|
96
89
|
name: 'introspect',
|
|
97
90
|
description: 'Read installed Domain schema from the Kernel Schema syscall',
|
|
98
91
|
afterHelpText: `
|
|
99
92
|
Behavior:
|
|
100
93
|
Calls the public Kernel introspect syscall for one installed Domain.
|
|
101
|
-
A bare origin (
|
|
94
|
+
A bare origin (kernel.astrale.ai or /:kernel.astrale.ai) prints installation
|
|
102
95
|
state, target, source, readiness, and capabilities. --bundle includes the
|
|
103
96
|
schema bundle. A method or Function Path projects that callable's
|
|
104
97
|
input/output from the installed bundle.
|
|
105
98
|
|
|
106
99
|
Examples:
|
|
107
|
-
$ astrale introspect
|
|
108
|
-
$ astrale introspect /:
|
|
109
|
-
$ astrale introspect /:
|
|
100
|
+
$ astrale introspect kernel.astrale.ai
|
|
101
|
+
$ astrale introspect /:kernel.astrale.ai --bundle
|
|
102
|
+
$ astrale introspect /:kernel.astrale.ai:class.Identity:whois
|
|
110
103
|
$ astrale introspect /:kernel.astrale.ai:function.journal
|
|
111
104
|
`,
|
|
112
105
|
arguments: [{ name: 'target', description: 'Domain origin or canonical Path' }],
|
package/src/commands/logs.ts
CHANGED
|
@@ -1,21 +1,16 @@
|
|
|
1
1
|
import { Path } from '@astrale-os/sdk/graph/path'
|
|
2
|
-
import {
|
|
2
|
+
import { K } from '@astrale-os/sdk/schema'
|
|
3
3
|
import chalk from 'chalk'
|
|
4
4
|
|
|
5
5
|
import type { ConnectionContext, KernelCommandOpts } from '../connection'
|
|
6
6
|
import type { Column, ListProjection } from '../lib/output'
|
|
7
7
|
import type { CommandDefinition } from '../program/index'
|
|
8
8
|
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
expandSelfInPath,
|
|
12
|
-
runKernelCommand,
|
|
13
|
-
withClientSession,
|
|
14
|
-
} from '../connection'
|
|
15
|
-
import { failClosed } from '../lib/log'
|
|
9
|
+
import { createPathCall, expandSelfInPath, runKernelCommand } from '../connection'
|
|
10
|
+
import { failInput } from '../lib/log'
|
|
16
11
|
import { isMachine, output, presentList } from '../lib/output'
|
|
17
12
|
|
|
18
|
-
const JOURNAL_PATH = Path.project(
|
|
13
|
+
const JOURNAL_PATH = Path.project(K.functions.journal.ref).raw
|
|
19
14
|
const DEFAULT_LIMIT = 200
|
|
20
15
|
const FOLLOW_INTERVAL_MS = 2_000
|
|
21
16
|
|
|
@@ -127,7 +122,7 @@ async function runOnce(opts: LogsOpts): Promise<void> {
|
|
|
127
122
|
await runKernelCommand({
|
|
128
123
|
opts,
|
|
129
124
|
label: 'Kernel journal',
|
|
130
|
-
fn: (context) => fetchPage(context, opts),
|
|
125
|
+
fn: async (context) => fetchPage(context, await resolveLogsOpts(opts, context)),
|
|
131
126
|
format: (page, format) => {
|
|
132
127
|
if (isMachine(format) || format.format !== undefined) output(page, format)
|
|
133
128
|
else {
|
|
@@ -139,14 +134,19 @@ async function runOnce(opts: LogsOpts): Promise<void> {
|
|
|
139
134
|
}
|
|
140
135
|
|
|
141
136
|
async function follow(opts: LogsOpts): Promise<void> {
|
|
142
|
-
await
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
cursor =
|
|
148
|
-
|
|
149
|
-
|
|
137
|
+
await runKernelCommand({
|
|
138
|
+
opts,
|
|
139
|
+
label: 'Kernel journal',
|
|
140
|
+
fn: async (context): Promise<never> => {
|
|
141
|
+
const resolved = await resolveLogsOpts(opts, context)
|
|
142
|
+
let cursor = resolved.cursor
|
|
143
|
+
for (;;) {
|
|
144
|
+
const page = await fetchPage(context, { ...resolved, cursor })
|
|
145
|
+
for (const record of page.records) printRecord(record)
|
|
146
|
+
cursor = page.cursor ?? cursor
|
|
147
|
+
await new Promise((resolve) => setTimeout(resolve, FOLLOW_INTERVAL_MS))
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
150
|
})
|
|
151
151
|
}
|
|
152
152
|
|
|
@@ -227,11 +227,10 @@ function positiveInteger(flag: string, raw: string): number {
|
|
|
227
227
|
return value
|
|
228
228
|
}
|
|
229
229
|
|
|
230
|
-
async function
|
|
231
|
-
buildJournalInput(opts)
|
|
230
|
+
async function resolveLogsOpts(opts: LogsOpts, context: ConnectionContext): Promise<LogsOpts> {
|
|
232
231
|
const principal = nonEmpty(opts.principal)
|
|
233
232
|
if (principal !== '@self') return opts
|
|
234
|
-
const { path } = await expandSelfInPath('@self',
|
|
233
|
+
const { path } = await expandSelfInPath('@self', context)
|
|
235
234
|
return { ...opts, principal: path.startsWith('@') ? path.slice(1) : path }
|
|
236
235
|
}
|
|
237
236
|
|
|
@@ -274,11 +273,11 @@ Examples:
|
|
|
274
273
|
],
|
|
275
274
|
action: async (opts: LogsOpts) => {
|
|
276
275
|
try {
|
|
277
|
-
|
|
278
|
-
if (prepared.follow) await follow(prepared)
|
|
279
|
-
else await runOnce(prepared)
|
|
276
|
+
buildJournalInput(opts)
|
|
280
277
|
} catch (error) {
|
|
281
|
-
|
|
278
|
+
failInput(error, opts)
|
|
282
279
|
}
|
|
280
|
+
if (opts.follow) await follow(opts)
|
|
281
|
+
else await runOnce(opts)
|
|
283
282
|
},
|
|
284
283
|
} satisfies CommandDefinition
|
package/src/commands/mutate.ts
CHANGED
|
@@ -7,8 +7,9 @@ import type { KernelCommandOpts } from '../connection'
|
|
|
7
7
|
import type { CommandDefinition } from '../program/index'
|
|
8
8
|
|
|
9
9
|
import { runKernelCommand } from '../connection'
|
|
10
|
+
import { AstraleError } from '../errors'
|
|
10
11
|
import { prepareMutation } from '../graph/index'
|
|
11
|
-
import {
|
|
12
|
+
import { failInput } from '../lib/log'
|
|
12
13
|
import { output } from '../lib/output'
|
|
13
14
|
import { renderTable } from '../lib/table'
|
|
14
15
|
|
|
@@ -23,7 +24,7 @@ export async function mutateCommand(opts: MutateOpts): Promise<void> {
|
|
|
23
24
|
try {
|
|
24
25
|
mutation = prepareMutation(await readDocument(opts))
|
|
25
26
|
} catch (error) {
|
|
26
|
-
|
|
27
|
+
failInput(error, opts)
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
if (opts.dry) {
|
|
@@ -51,9 +52,9 @@ async function readDocument(opts: MutateOpts): Promise<unknown> {
|
|
|
51
52
|
try {
|
|
52
53
|
raw = await readFile(opts.file, 'utf8')
|
|
53
54
|
} catch (error) {
|
|
54
|
-
throw new
|
|
55
|
-
|
|
56
|
-
)
|
|
55
|
+
throw new AstraleError('FILE_READ_FAILED', `Cannot read --file ${opts.file}.`, undefined, {
|
|
56
|
+
cause: error,
|
|
57
|
+
})
|
|
57
58
|
}
|
|
58
59
|
return parseJson(raw, opts.file)
|
|
59
60
|
}
|
package/src/commands/query.ts
CHANGED
|
@@ -6,8 +6,9 @@ import type { KernelCommandOpts, SelfExpansionMeta } from '../connection'
|
|
|
6
6
|
import type { CommandDefinition } from '../program/index'
|
|
7
7
|
|
|
8
8
|
import { expandSelfInPath, runKernelCommand, withSelfHint } from '../connection'
|
|
9
|
+
import { AstraleError } from '../errors'
|
|
9
10
|
import { prepareQuery, type QueryCommandInput } from '../graph/index'
|
|
10
|
-
import {
|
|
11
|
+
import { failInput } from '../lib/log'
|
|
11
12
|
import { isMachine, output } from '../lib/output'
|
|
12
13
|
|
|
13
14
|
type QueryOpts = KernelCommandOpts & {
|
|
@@ -22,46 +23,42 @@ type QueryOpts = KernelCommandOpts & {
|
|
|
22
23
|
|
|
23
24
|
export async function queryCommand(sources: string[], opts: QueryOpts): Promise<void> {
|
|
24
25
|
let input: QueryCommandInput
|
|
25
|
-
let meta: SelfExpansionMeta | undefined
|
|
26
26
|
try {
|
|
27
27
|
const ast = await readAst(opts)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
cursor: opts.cursor,
|
|
37
|
-
}
|
|
38
|
-
meta = expanded.find((entry) => entry.meta !== undefined)?.meta
|
|
39
|
-
} else {
|
|
40
|
-
input = {
|
|
41
|
-
sources,
|
|
42
|
-
ast,
|
|
43
|
-
definition: opts.definition,
|
|
44
|
-
edge: opts.edge,
|
|
45
|
-
direction: opts.direction,
|
|
46
|
-
limit: opts.limit,
|
|
47
|
-
cursor: opts.cursor,
|
|
48
|
-
}
|
|
28
|
+
input = {
|
|
29
|
+
sources,
|
|
30
|
+
...(ast === undefined ? {} : { ast }),
|
|
31
|
+
definition: opts.definition,
|
|
32
|
+
edge: opts.edge,
|
|
33
|
+
direction: opts.direction,
|
|
34
|
+
limit: opts.limit,
|
|
35
|
+
cursor: opts.cursor,
|
|
49
36
|
}
|
|
50
37
|
} catch (error) {
|
|
51
|
-
|
|
38
|
+
failInput(error, opts)
|
|
52
39
|
}
|
|
53
40
|
|
|
54
41
|
let prepared
|
|
55
42
|
try {
|
|
56
43
|
prepared = prepareQuery(input)
|
|
57
44
|
} catch (error) {
|
|
58
|
-
|
|
45
|
+
failInput(error, opts)
|
|
59
46
|
}
|
|
60
47
|
|
|
61
48
|
await runKernelCommand({
|
|
62
49
|
opts,
|
|
63
50
|
label: 'Query',
|
|
64
|
-
fn:
|
|
51
|
+
fn: async (context) => {
|
|
52
|
+
const expanded = await Promise.all(sources.map((source) => expandSelfInPath(source, context)))
|
|
53
|
+
const meta: SelfExpansionMeta | undefined = expanded.find(
|
|
54
|
+
(entry) => entry.meta !== undefined,
|
|
55
|
+
)?.meta
|
|
56
|
+
const resolved =
|
|
57
|
+
meta === undefined
|
|
58
|
+
? prepared
|
|
59
|
+
: prepareQuery({ ...input, sources: expanded.map(({ path }) => path) })
|
|
60
|
+
return withSelfHint(() => context.graph.query(resolved.ast, { page: resolved.page }), meta)
|
|
61
|
+
},
|
|
65
62
|
format: (response, format) => {
|
|
66
63
|
output(response.result, format)
|
|
67
64
|
if (response.page.next && !isMachine(format)) {
|
|
@@ -81,9 +78,9 @@ async function readAst(opts: QueryOpts): Promise<unknown | undefined> {
|
|
|
81
78
|
try {
|
|
82
79
|
raw = await readFile(opts.file, 'utf8')
|
|
83
80
|
} catch (error) {
|
|
84
|
-
throw new
|
|
85
|
-
|
|
86
|
-
)
|
|
81
|
+
throw new AstraleError('FILE_READ_FAILED', `Cannot read --file ${opts.file}.`, undefined, {
|
|
82
|
+
cause: error,
|
|
83
|
+
})
|
|
87
84
|
}
|
|
88
85
|
return parseJson(raw, opts.file)
|
|
89
86
|
}
|
|
@@ -122,7 +119,7 @@ Examples:
|
|
|
122
119
|
{ flags: '-f, --file <path>', description: 'Read a canonical Query V6 document from a file' },
|
|
123
120
|
{
|
|
124
121
|
flags: '--definition <path>',
|
|
125
|
-
description: 'Select Nodes
|
|
122
|
+
description: 'Select Nodes satisfying one exact Class',
|
|
126
123
|
},
|
|
127
124
|
{ flags: '--edge <class>', description: 'Expand one exact Edge Class' },
|
|
128
125
|
{
|