@astrale-os/sdk 0.5.0-beta.98 → 0.6.0-beta.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 (270) hide show
  1. package/README.md +165 -2
  2. package/dist/application/action/action.d.ts +7 -4
  3. package/dist/application/action/authoring.d.ts +2 -1
  4. package/dist/application/action/context.d.ts +18 -13
  5. package/dist/application/action/define.d.ts +5 -1
  6. package/dist/application/action/define.js +6 -1
  7. package/dist/application/action/index.d.ts +2 -1
  8. package/dist/application/dependency/index.d.ts +1 -0
  9. package/dist/application/dependency/invoker.d.ts +26 -0
  10. package/dist/application/error/error.d.ts +23 -0
  11. package/dist/application/error/error.js +87 -0
  12. package/dist/application/error/index.d.ts +2 -0
  13. package/dist/application/error/index.js +1 -0
  14. package/dist/application/index.d.ts +2 -2
  15. package/dist/application/integration/authentication.d.ts +10 -0
  16. package/dist/application/integration/authentication.typecheck.js +18 -0
  17. package/dist/application/integration/client.d.ts +2 -0
  18. package/dist/application/integration/client.js +19 -2
  19. package/dist/application/integration/index.d.ts +1 -0
  20. package/dist/application/integration/operation.d.ts +3 -0
  21. package/dist/application/mutation/authoring/builder.js +2 -2
  22. package/dist/application/mutation/authoring/endpoint.d.ts +3 -3
  23. package/dist/application/mutation/authoring/endpoint.js +9 -0
  24. package/dist/application/mutation/failure.js +13 -7
  25. package/dist/application/mutation/index.d.ts +1 -0
  26. package/dist/application/requirements/{profiles.d.ts → core.d.ts} +5 -3
  27. package/dist/application/requirements/{profiles.js → core.js} +6 -6
  28. package/dist/application/requirements/index.d.ts +4 -4
  29. package/dist/application/requirements/index.js +5 -5
  30. package/dist/application/requirements/requirement.d.ts +3 -2
  31. package/dist/application/runtime/authoring.d.ts +1 -0
  32. package/dist/application/runtime/callables.js +2 -2
  33. package/dist/application/runtime/declarations.d.ts +43 -0
  34. package/dist/application/runtime/define.d.ts +2 -1
  35. package/dist/application/view/index.d.ts +1 -1
  36. package/dist/application/view/route.d.ts +4 -0
  37. package/dist/application/view/route.js +5 -1
  38. package/dist/application/workflow/authoring.d.ts +1 -0
  39. package/dist/application/workflow/context.d.ts +2 -1
  40. package/dist/application/workflow/define.d.ts +5 -1
  41. package/dist/application/workflow/define.js +6 -1
  42. package/dist/application/workflow/index.d.ts +1 -0
  43. package/dist/application/workflow/runner/runner.d.ts +3 -2
  44. package/dist/application/workflow/workflow.d.ts +4 -3
  45. package/dist/deployment/adapter/adapter.d.ts +12 -7
  46. package/dist/deployment/adapter/define.d.ts +5 -2
  47. package/dist/deployment/adapter/define.js +15 -17
  48. package/dist/deployment/adapter/deploy/context.d.ts +6 -0
  49. package/dist/deployment/adapter/deploy/result.d.ts +2 -0
  50. package/dist/deployment/adapter/index.d.ts +2 -3
  51. package/dist/deployment/adapter/index.js +1 -1
  52. package/dist/deployment/adapter/prepare/context.d.ts +13 -5
  53. package/dist/deployment/authoring.d.ts +1 -1
  54. package/dist/deployment/build/compile.js +21 -19
  55. package/dist/deployment/build/frontend/compilation.d.ts +2 -1
  56. package/dist/deployment/build/frontend/compilation.js +1 -0
  57. package/dist/deployment/build/material.js +5 -5
  58. package/dist/deployment/deploy.d.ts +10 -4
  59. package/dist/deployment/deploy.js +5 -5
  60. package/dist/deployment/deployment.d.ts +8 -5
  61. package/dist/deployment/deployment.js +10 -1
  62. package/dist/deployment/index.d.ts +5 -4
  63. package/dist/deployment/index.js +3 -2
  64. package/dist/deployment/release/addressing.d.ts +6 -2
  65. package/dist/deployment/release/addressing.js +9 -4
  66. package/dist/deployment/release/publication/callables.js +1 -1
  67. package/dist/deployment/release/publication/index.d.ts +1 -1
  68. package/dist/deployment/release/publication/index.js +1 -1
  69. package/dist/deployment/release/publication/routes.js +1 -1
  70. package/dist/deployment/release/publication/seal.d.ts +0 -1
  71. package/dist/deployment/release/publication/seal.js +4 -5
  72. package/dist/deployment/release/publication/views.js +2 -1
  73. package/dist/deployment/verify/preflight/artifact.js +1 -1
  74. package/dist/deployment/verify/readiness/deployment.js +7 -3
  75. package/dist/deployment/verify/readiness/identity.js +1 -1
  76. package/dist/deployment/verify/readiness/publication.js +2 -2
  77. package/dist/execution/identity/authentication.js +0 -1
  78. package/dist/execution/identity/exchange.d.ts +1 -0
  79. package/dist/execution/identity/exchange.js +1 -1
  80. package/dist/execution/identity/jwks.js +1 -1
  81. package/dist/execution/invocation/admission/authentication.d.ts +6 -3
  82. package/dist/execution/invocation/admission/authentication.js +16 -6
  83. package/dist/execution/invocation/admission/authority.d.ts +2 -2
  84. package/dist/execution/invocation/dependency/bind.d.ts +5 -0
  85. package/dist/execution/invocation/dependency/bind.js +68 -0
  86. package/dist/execution/invocation/dependency/index.d.ts +1 -0
  87. package/dist/execution/invocation/dependency/index.js +1 -0
  88. package/dist/execution/invocation/dispatch/action.js +19 -2
  89. package/dist/execution/invocation/dispatch/context.d.ts +4 -4
  90. package/dist/execution/invocation/dispatch/context.js +29 -9
  91. package/dist/execution/invocation/dispatch/workflow.js +17 -4
  92. package/dist/execution/invocation/integration/authentication.d.ts +5 -0
  93. package/dist/execution/invocation/integration/authentication.js +53 -0
  94. package/dist/execution/invocation/integration/call.d.ts +7 -1
  95. package/dist/execution/invocation/integration/call.js +8 -3
  96. package/dist/execution/invocation/integration/clients.d.ts +2 -2
  97. package/dist/execution/invocation/integration/clients.js +2 -2
  98. package/dist/execution/invocation/lifecycle/active.js +30 -5
  99. package/dist/execution/invocation/result/errors.d.ts +1 -0
  100. package/dist/execution/invocation/result/errors.js +15 -10
  101. package/dist/execution/service/create.js +3 -1
  102. package/dist/execution/service/service.d.ts +1 -1
  103. package/dist/index.d.ts +3 -1
  104. package/dist/index.js +1 -0
  105. package/dist/platform/auth/index.d.ts +1 -1
  106. package/dist/platform/auth/index.js +0 -1
  107. package/dist/platform/graph/alias.d.ts +6 -0
  108. package/dist/platform/graph/alias.js +6 -0
  109. package/dist/platform/graph/document/index.d.ts +2 -1
  110. package/dist/platform/graph/document/index.js +2 -1
  111. package/dist/platform/graph/index.d.ts +2 -1
  112. package/dist/platform/graph/index.js +2 -1
  113. package/dist/platform/schema/class-authoring.d.ts +37 -0
  114. package/dist/platform/schema/class-authoring.js +20 -0
  115. package/dist/platform/schema/class-icon.d.ts +15 -0
  116. package/dist/platform/schema/class-icon.js +46 -0
  117. package/dist/platform/schema/error.d.ts +11 -0
  118. package/dist/platform/schema/error.js +34 -0
  119. package/dist/platform/schema/errors/index.d.ts +3 -0
  120. package/dist/platform/schema/errors/index.js +2 -0
  121. package/dist/platform/schema/icons/index.d.ts +2 -0
  122. package/dist/platform/schema/icons/index.js +2 -0
  123. package/dist/platform/schema/index.d.ts +20 -13
  124. package/dist/platform/schema/index.js +9 -4
  125. package/dist/platform/schema/kernel.d.ts +22 -0
  126. package/dist/platform/schema/kernel.js +5 -0
  127. package/dist/platform/schema/node-id.d.ts +3 -0
  128. package/dist/platform/schema/node-id.js +6 -0
  129. package/dist/platform/schema/property.d.ts +12 -0
  130. package/dist/platform/schema/property.js +3 -0
  131. package/dist/platform/schema/schema-authoring.d.ts +48 -0
  132. package/dist/platform/schema/schema-authoring.js +3 -0
  133. package/dist/platform/schema/state-property.d.ts +11 -0
  134. package/dist/platform/schema/state-property.js +3 -0
  135. package/dist/project/admit.d.ts +4 -0
  136. package/dist/project/admit.js +22 -0
  137. package/dist/project/define.d.ts +12 -0
  138. package/dist/project/define.js +106 -0
  139. package/dist/project/index.d.ts +4 -0
  140. package/dist/project/index.js +2 -0
  141. package/dist/project/project.d.ts +24 -0
  142. package/dist/project/project.js +1 -0
  143. package/dist/testing/dataset/admission.d.ts +13 -0
  144. package/dist/testing/dataset/admission.js +107 -0
  145. package/dist/testing/dataset/builder.d.ts +42 -0
  146. package/dist/testing/dataset/builder.js +127 -0
  147. package/dist/testing/dataset/codec.d.ts +6 -0
  148. package/dist/testing/dataset/codec.js +113 -0
  149. package/dist/testing/dataset/dataset.d.ts +58 -0
  150. package/dist/testing/dataset/dataset.js +2 -0
  151. package/dist/testing/dataset/define.d.ts +33 -0
  152. package/dist/testing/dataset/define.js +105 -0
  153. package/dist/testing/dataset/index.d.ts +8 -0
  154. package/dist/testing/dataset/index.js +4 -0
  155. package/dist/testing/dataset/references.d.ts +14 -0
  156. package/dist/testing/dataset/references.js +56 -0
  157. package/dist/testing/index.d.ts +9 -0
  158. package/dist/testing/index.js +5 -0
  159. package/dist/testing/load.d.ts +14 -0
  160. package/dist/testing/load.js +44 -0
  161. package/dist/testing/reference.d.ts +11 -0
  162. package/dist/testing/reference.js +19 -0
  163. package/dist/testing/tests.d.ts +12 -0
  164. package/dist/testing/tests.js +31 -0
  165. package/dist/tooling/cli/arguments.d.ts +7 -4
  166. package/dist/tooling/cli/arguments.js +82 -107
  167. package/dist/tooling/cli/astrale/authority.d.ts +5 -0
  168. package/dist/tooling/cli/astrale/authority.js +11 -0
  169. package/dist/tooling/cli/astrale/executable.d.ts +2 -0
  170. package/dist/tooling/cli/astrale/executable.js +47 -0
  171. package/dist/tooling/cli/astrale/failure.d.ts +6 -0
  172. package/dist/tooling/cli/astrale/failure.js +48 -0
  173. package/dist/tooling/cli/astrale/instance.d.ts +11 -0
  174. package/dist/tooling/cli/astrale/instance.js +52 -0
  175. package/dist/tooling/cli/astrale/process.d.ts +13 -0
  176. package/dist/tooling/cli/astrale/process.js +94 -0
  177. package/dist/tooling/cli/astrale/version.d.ts +18 -0
  178. package/dist/tooling/cli/astrale/version.js +55 -0
  179. package/dist/tooling/cli/bun.js +1 -1
  180. package/dist/tooling/cli/credential.d.ts +2 -0
  181. package/dist/tooling/cli/credential.js +57 -0
  182. package/dist/tooling/cli/development/candidate.d.ts +25 -0
  183. package/dist/tooling/cli/development/candidate.js +176 -0
  184. package/dist/tooling/cli/development/deployment.d.ts +16 -0
  185. package/dist/tooling/cli/development/deployment.js +39 -0
  186. package/dist/tooling/cli/development/develop.d.ts +4 -3
  187. package/dist/tooling/cli/development/develop.js +125 -289
  188. package/dist/tooling/cli/development/lease.d.ts +18 -0
  189. package/dist/tooling/cli/development/lease.js +163 -0
  190. package/dist/tooling/cli/development/lifecycle.js +4 -0
  191. package/dist/tooling/cli/development/project-imports.d.ts +22 -0
  192. package/dist/tooling/cli/development/project-imports.js +39 -0
  193. package/dist/tooling/cli/development/project-lock.d.ts +3 -4
  194. package/dist/tooling/cli/development/project-lock.js +14 -166
  195. package/dist/tooling/cli/development/release-evidence.d.ts +4 -0
  196. package/dist/tooling/cli/development/release-evidence.js +10 -0
  197. package/dist/tooling/cli/development/report.d.ts +6 -0
  198. package/dist/tooling/cli/development/report.js +14 -0
  199. package/dist/tooling/cli/development/source-watch.js +53 -5
  200. package/dist/tooling/cli/development/sources.d.ts +7 -0
  201. package/dist/tooling/cli/development/sources.js +48 -0
  202. package/dist/tooling/cli/development/target-lock.d.ts +16 -0
  203. package/dist/tooling/cli/development/target-lock.js +68 -0
  204. package/dist/tooling/cli/development/view.d.ts +28 -0
  205. package/dist/tooling/cli/development/view.js +151 -0
  206. package/dist/tooling/cli/environment-release.d.ts +21 -0
  207. package/dist/tooling/cli/environment-release.js +46 -0
  208. package/dist/tooling/cli/evidence.d.ts +11 -0
  209. package/dist/tooling/cli/evidence.js +53 -0
  210. package/dist/tooling/cli/help.js +78 -34
  211. package/dist/tooling/cli/index.d.ts +1 -1
  212. package/dist/tooling/cli/index.js +1 -1
  213. package/dist/tooling/cli/installation/index.d.ts +2 -0
  214. package/dist/tooling/cli/installation/index.js +1 -0
  215. package/dist/tooling/cli/installation/observation.d.ts +10 -0
  216. package/dist/tooling/cli/installation/observation.js +44 -0
  217. package/dist/tooling/cli/installation/reconcile.d.ts +32 -0
  218. package/dist/tooling/cli/installation/reconcile.js +122 -0
  219. package/dist/tooling/cli/orchestrate.js +84 -44
  220. package/dist/tooling/cli/project.d.ts +17 -0
  221. package/dist/tooling/cli/project.js +18 -0
  222. package/dist/tooling/cli/test.d.ts +12 -0
  223. package/dist/tooling/cli/test.js +47 -0
  224. package/dist/tooling/cli/upgrade/index.d.ts +6 -0
  225. package/dist/tooling/cli/upgrade/index.js +115 -0
  226. package/dist/tooling/cli/upgrade/manifest.d.ts +18 -0
  227. package/dist/tooling/cli/upgrade/manifest.js +77 -0
  228. package/dist/tooling/cli/upgrade/process.d.ts +2 -0
  229. package/dist/tooling/cli/upgrade/process.js +57 -0
  230. package/dist/tooling/linter/adapters/typescript/imports.js +2 -0
  231. package/dist/tooling/linter/adapters/typescript/index.d.ts +1 -0
  232. package/dist/tooling/linter/adapters/typescript/index.js +1 -0
  233. package/dist/tooling/linter/adapters/typescript/query-collection-type.js +4 -51
  234. package/dist/tooling/linter/adapters/typescript/type-analysis.d.ts +9 -0
  235. package/dist/tooling/linter/adapters/typescript/type-analysis.js +55 -0
  236. package/dist/tooling/linter/implementations/source/callable-requirements.d.ts +28 -0
  237. package/dist/tooling/linter/implementations/source/callable-requirements.js +234 -0
  238. package/dist/tooling/linter/implementations/source/dependencies.d.ts +2 -0
  239. package/dist/tooling/linter/implementations/source/dependencies.js +219 -0
  240. package/dist/tooling/linter/implementations/source/global.js +61 -5
  241. package/dist/tooling/linter/implementations/source/mutations.js +520 -38
  242. package/dist/tooling/linter/implementations/source/providers.js +19 -164
  243. package/dist/tooling/linter/implementations/source/schema.js +454 -2
  244. package/dist/tooling/linter/implementations/source/verifiers.js +2 -0
  245. package/dist/tooling/linter/implementations/source/workflows.js +8 -35
  246. package/dist/tooling/linter/policy/generated.js +2 -2
  247. package/dist/tooling/linter/requirements/registry.js +9 -3
  248. package/dist/tooling/packaging/declarations/normalize.js +3 -38
  249. package/dist/tooling/packaging/declarations/paths.d.ts +5 -0
  250. package/dist/tooling/packaging/declarations/paths.js +38 -0
  251. package/dist/tooling/packaging/finalize.d.ts +13 -0
  252. package/dist/tooling/packaging/finalize.js +62 -0
  253. package/dist/tooling/packaging/index.d.ts +2 -0
  254. package/dist/tooling/packaging/index.js +1 -0
  255. package/dist/tooling/packaging/javascript.d.ts +3 -0
  256. package/dist/tooling/packaging/javascript.js +45 -2
  257. package/dist/tooling/packaging/packaging.d.ts +2 -5
  258. package/dist/tooling/packaging/packaging.js +6 -30
  259. package/package.json +42 -12
  260. package/CHANGELOG.md +0 -1499
  261. package/dist/deployment/adapter/development/context.d.ts +0 -18
  262. package/dist/deployment/adapter/development/index.d.ts +0 -4
  263. package/dist/deployment/adapter/development/input.d.ts +0 -6
  264. package/dist/deployment/adapter/development/placement.d.ts +0 -15
  265. package/dist/deployment/adapter/development/session.d.ts +0 -9
  266. /package/dist/{deployment/adapter/development → application/dependency}/index.js +0 -0
  267. /package/dist/{deployment/adapter/development/context.js → application/dependency/invoker.js} +0 -0
  268. /package/dist/{deployment/adapter/development/input.js → application/integration/authentication.js} +0 -0
  269. /package/dist/{deployment/adapter/development/placement.js → application/integration/authentication.typecheck.d.ts} +0 -0
  270. /package/dist/{deployment/adapter/development/session.js → application/runtime/declarations.js} +0 -0
@@ -0,0 +1,56 @@
1
+ import { graph as schemaGraph } from '@astrale-os/kernel-core/schema';
2
+ import { isNodeId } from '../../platform/graph/node/index.js';
3
+ import { Path } from '../../platform/graph/path/index.js';
4
+ import { bundle, schema as schemaApi } from '../../platform/schema/index.js';
5
+ /** Symbolic projection supplies facts; only an explicit Dataset reference supplies identity. */
6
+ export function datasetReferenceNodes(domain) {
7
+ const result = new Map();
8
+ const direct = new Set([
9
+ domain.origin,
10
+ ...Object.values(domain.dependencies).map(({ origin }) => origin),
11
+ ]);
12
+ const sourceBundle = bundle.create(domain.source);
13
+ for (const source of [sourceBundle.root, ...sourceBundle.closure]) {
14
+ if (!direct.has(source.origin))
15
+ continue;
16
+ const owner = schemaApi.resolve(source);
17
+ const projection = schemaGraph.project(owner);
18
+ const allowed = new Set(owner
19
+ .definitions()
20
+ .filter(({ ref }) => ref.origin === owner.origin &&
21
+ ['class', 'function', 'policy', 'view', 'core'].includes(ref.kind))
22
+ .map(({ ref }) => Path.project(ref).raw));
23
+ for (const part of [projection.managed, projection.core]) {
24
+ for (const node of part.graph.nodes) {
25
+ if (!('as' in node))
26
+ continue;
27
+ const path = part.paths.get(node.as);
28
+ if (path !== undefined && allowed.has(path))
29
+ result.set(path, node);
30
+ }
31
+ }
32
+ }
33
+ return result;
34
+ }
35
+ /** Serialized reference associations lose their proof and must match the exact projection again. */
36
+ export function decodeDatasetReferences(input, domain, graph) {
37
+ if (input === null || typeof input !== 'object' || Array.isArray(input)) {
38
+ throw new TypeError('Dataset references must be an object.');
39
+ }
40
+ const entries = Object.entries(input);
41
+ const projected = entries.length === 0 ? new Map() : datasetReferenceNodes(domain);
42
+ const identities = new Set();
43
+ for (const [path, id] of entries) {
44
+ const expected = projected.get(path);
45
+ const actual = isNodeId(id) ? graph.nodes.byId(id) : undefined;
46
+ if (expected === undefined ||
47
+ actual === undefined ||
48
+ identities.has(actual.id) ||
49
+ expected.class !== actual.class ||
50
+ JSON.stringify(expected.props) !== JSON.stringify(actual.props)) {
51
+ throw new TypeError(`Dataset reference ${path} does not identify its projected Node.`);
52
+ }
53
+ identities.add(actual.id);
54
+ }
55
+ return Object.freeze(Object.fromEntries(entries));
56
+ }
@@ -0,0 +1,9 @@
1
+ /** Development and test resources: schema-admitted demo Datasets and their lazy project references. */
2
+ export { DATASET_FORMAT, DATASET_VERSION, DatasetAdmissionError, decodeDataset, defineDataset, encodeDataset, isDataset, } from './dataset/index.js';
3
+ export type { AuthoredDatasetVariables, Dataset, DatasetClasses, DatasetEdgeInput, DatasetEndpoint, DatasetGraph, DatasetInput, DatasetJson, DatasetNode, DatasetNodeInput, DatasetReferences, DatasetReferenceInput, DatasetVariable, DatasetVariableJson, DatasetVariables, DatasetVariablesOf, SchemaOfDataset, } from './dataset/index.js';
4
+ export { loadDataset, loadDatasets } from './load.js';
5
+ export type { DatasetModuleLoader, LoadedDataset } from './load.js';
6
+ export { dataset, isDatasetReference } from './reference.js';
7
+ export type { DatasetReference } from './reference.js';
8
+ export { isTests, tests } from './tests.js';
9
+ export type { Tests, TestsInput } from './tests.js';
@@ -0,0 +1,5 @@
1
+ /** Development and test resources: schema-admitted demo Datasets and their lazy project references. */
2
+ export { DATASET_FORMAT, DATASET_VERSION, DatasetAdmissionError, decodeDataset, defineDataset, encodeDataset, isDataset, } from './dataset/index.js';
3
+ export { loadDataset, loadDatasets } from './load.js';
4
+ export { dataset, isDatasetReference } from './reference.js';
5
+ export { isTests, tests } from './tests.js';
@@ -0,0 +1,14 @@
1
+ import type { schema } from '../platform/schema/index.js';
2
+ import type { Dataset } from './dataset/index.js';
3
+ import type { DatasetReference } from './reference.js';
4
+ import type { Tests } from './tests.js';
5
+ /** Import one referenced module; tooling owns path resolution against `astrale.config.ts`. */
6
+ export type DatasetModuleLoader = (path: string) => unknown | Promise<unknown>;
7
+ export interface LoadedDataset {
8
+ readonly reference: DatasetReference;
9
+ readonly dataset: Dataset;
10
+ }
11
+ /** Load the one default Dataset of a referenced module and prove it targets the exact Schema. */
12
+ export declare function loadDataset(reference: DatasetReference, load: DatasetModuleLoader, source: schema.DomainSchema): Promise<LoadedDataset>;
13
+ /** Load every referenced Dataset of one Tests value in declared order, rejecting duplicate ids. */
14
+ export declare function loadDatasets(value: Tests, load: DatasetModuleLoader, source: schema.DomainSchema): Promise<readonly LoadedDataset[]>;
@@ -0,0 +1,44 @@
1
+ import { isDataset } from './dataset/index.js';
2
+ import { isDatasetReference } from './reference.js';
3
+ import { isTests } from './tests.js';
4
+ /** Load the one default Dataset of a referenced module and prove it targets the exact Schema. */
5
+ export async function loadDataset(reference, load, source) {
6
+ if (!isDatasetReference(reference)) {
7
+ throw new TypeError('Dataset reference must be created by dataset(path).');
8
+ }
9
+ if (typeof load !== 'function')
10
+ throw new TypeError('Dataset module loader must be a function.');
11
+ const loaded = await load(reference.path);
12
+ if (loaded === null ||
13
+ typeof loaded !== 'object' ||
14
+ Array.isArray(loaded) ||
15
+ !Object.hasOwn(loaded, 'default') ||
16
+ Object.keys(loaded).some((key) => key !== 'default')) {
17
+ throw new TypeError(`Dataset module ${reference.path} must export exactly one default Dataset.`);
18
+ }
19
+ const dataset = Reflect.get(loaded, 'default');
20
+ if (!isDataset(dataset)) {
21
+ throw new TypeError(`Dataset module ${reference.path} default export is not an admitted Dataset.`);
22
+ }
23
+ if (dataset.schema !== source) {
24
+ throw new TypeError(`Dataset ${dataset.id} (${reference.path}) targets Schema ${dataset.schema.origin}, not the exact Application Schema.`);
25
+ }
26
+ return Object.freeze({ reference, dataset });
27
+ }
28
+ /** Load every referenced Dataset of one Tests value in declared order, rejecting duplicate ids. */
29
+ export async function loadDatasets(value, load, source) {
30
+ if (!isTests(value))
31
+ throw new TypeError('Tests value must be created by tests().');
32
+ const loaded = [];
33
+ const ids = new Map();
34
+ for (const reference of value.datasets) {
35
+ const entry = await loadDataset(reference, load, source);
36
+ const previous = ids.get(entry.dataset.id);
37
+ if (previous !== undefined) {
38
+ throw new TypeError(`Dataset id ${entry.dataset.id} is defined by both ${previous} and ${reference.path}.`);
39
+ }
40
+ ids.set(entry.dataset.id, reference.path);
41
+ loaded.push(entry);
42
+ }
43
+ return Object.freeze(loaded);
44
+ }
@@ -0,0 +1,11 @@
1
+ /** One stable Dataset module coordinate relative to the project configuration. */
2
+ export interface DatasetReference {
3
+ readonly kind: 'dataset-reference';
4
+ readonly path: string;
5
+ }
6
+ /**
7
+ * Reference one Dataset module lazily. Importing the project configuration never loads the
8
+ * referenced module; tooling resolves the path against `astrale.config.ts` on demand.
9
+ */
10
+ export declare function dataset(path: string): DatasetReference;
11
+ export declare function isDatasetReference(input: unknown): input is DatasetReference;
@@ -0,0 +1,19 @@
1
+ const references = new WeakSet();
2
+ /**
3
+ * Reference one Dataset module lazily. Importing the project configuration never loads the
4
+ * referenced module; tooling resolves the path against `astrale.config.ts` on demand.
5
+ */
6
+ export function dataset(path) {
7
+ if (typeof path !== 'string' ||
8
+ path.length === 0 ||
9
+ path.trim() !== path ||
10
+ path.includes('\0')) {
11
+ throw new TypeError('Dataset path must be a non-empty stable module coordinate.');
12
+ }
13
+ const reference = Object.freeze({ kind: 'dataset-reference', path });
14
+ references.add(reference);
15
+ return reference;
16
+ }
17
+ export function isDatasetReference(input) {
18
+ return input !== null && typeof input === 'object' && references.has(input);
19
+ }
@@ -0,0 +1,12 @@
1
+ import type { DatasetReference } from './reference.js';
2
+ /** Development and test resources of one project. Never part of a Build, Release, or install. */
3
+ export interface Tests {
4
+ readonly kind: 'tests';
5
+ readonly datasets: readonly DatasetReference[];
6
+ }
7
+ export interface TestsInput {
8
+ readonly datasets?: readonly DatasetReference[];
9
+ }
10
+ /** Capture the inert test resources of a project; Dataset modules stay unloaded. */
11
+ export declare function tests(input?: TestsInput): Tests;
12
+ export declare function isTests(input: unknown): input is Tests;
@@ -0,0 +1,31 @@
1
+ import { isDatasetReference } from './reference.js';
2
+ const admittedTests = new WeakSet();
3
+ /** Capture the inert test resources of a project; Dataset modules stay unloaded. */
4
+ export function tests(input = {}) {
5
+ if (input === null || typeof input !== 'object' || Array.isArray(input))
6
+ invalid();
7
+ if (Reflect.ownKeys(input).some((key) => key !== 'datasets'))
8
+ invalid();
9
+ const datasets = input.datasets ?? [];
10
+ if (!Array.isArray(datasets))
11
+ throw new TypeError('Tests datasets must be an array.');
12
+ const paths = new Set();
13
+ for (const reference of datasets) {
14
+ if (!isDatasetReference(reference)) {
15
+ throw new TypeError('Tests datasets must contain only references created by dataset(path).');
16
+ }
17
+ if (paths.has(reference.path)) {
18
+ throw new TypeError(`Dataset ${reference.path} is referenced more than once.`);
19
+ }
20
+ paths.add(reference.path);
21
+ }
22
+ const value = Object.freeze({ kind: 'tests', datasets: Object.freeze([...datasets]) });
23
+ admittedTests.add(value);
24
+ return value;
25
+ }
26
+ export function isTests(input) {
27
+ return input !== null && typeof input === 'object' && admittedTests.has(input);
28
+ }
29
+ function invalid() {
30
+ throw new TypeError('Tests definition may contain only datasets.');
31
+ }
@@ -1,16 +1,19 @@
1
1
  import type { LintReportFormat } from '../linter/index.js';
2
- export declare const COMMANDS: readonly ['dev', 'build', 'deploy', 'lint', 'package'];
2
+ export declare const COMMANDS: readonly ['dev', 'build', 'deploy', 'test', 'lint', 'package', 'upgrade'];
3
3
  export type Command = (typeof COMMANDS)[number];
4
4
  export interface ParsedArgs {
5
5
  readonly command: Command;
6
6
  readonly env: string;
7
7
  readonly fix?: boolean;
8
8
  readonly format?: LintReportFormat;
9
- readonly port?: number;
10
- readonly host?: string;
11
- readonly sessionFile?: string;
9
+ readonly deployOnly?: boolean;
10
+ readonly identity?: string;
12
11
  readonly credentialFile?: string;
12
+ readonly suite?: string;
13
+ readonly sessionFile?: string;
13
14
  readonly secretsFile?: string;
15
+ readonly channel?: string;
16
+ readonly check?: boolean;
14
17
  }
15
18
  /** Parse the frozen `astrale-domain` command grammar without performing effects. */
16
19
  export declare function parseArgs(argv: readonly string[]): ParsedArgs;
@@ -1,44 +1,27 @@
1
- import { isIP } from 'node:net';
2
1
  import { isAbsolute, normalize } from 'node:path';
3
- export const COMMANDS = ['dev', 'build', 'deploy', 'lint', 'package'];
2
+ export const COMMANDS = ['dev', 'build', 'deploy', 'test', 'lint', 'package', 'upgrade'];
4
3
  /** Parse the frozen `astrale-domain` command grammar without performing effects. */
5
4
  export function parseArgs(argv) {
6
5
  const [command, ...rest] = argv;
6
+ if (command === 'upgrade')
7
+ return parseUpgrade(rest);
7
8
  const fix = rest.includes('--fix');
8
- let port;
9
- let host;
9
+ const deployOnly = rest.includes('--deploy-only');
10
10
  let sessionFile;
11
- let credentialFile;
12
11
  let secretsFile;
12
+ let credentialFile;
13
+ let identity;
14
+ let suite;
13
15
  let format;
14
16
  let environment;
15
17
  const cleaned = [];
16
18
  for (let index = 0; index < rest.length; index += 1) {
17
19
  const argument = rest[index];
18
- if (argument === '--port') {
19
- const value = rest[++index];
20
- port = Number(value);
21
- if (!Number.isInteger(port) || port <= 0 || port > 65_535) {
22
- throw new Error(`--port needs a port number, got "${value}"`);
23
- }
24
- }
25
- else if (argument.startsWith('--port=')) {
26
- port = Number(argument.slice('--port='.length));
27
- if (!Number.isInteger(port) || port <= 0 || port > 65_535) {
28
- throw new Error(`--port needs a port number, got "${argument}"`);
29
- }
30
- }
31
- else if (argument === '--host') {
32
- host = normalizeHost(rest[++index]);
33
- }
34
- else if (argument.startsWith('--host=')) {
35
- host = normalizeHost(argument.slice('--host='.length));
36
- }
37
- else if (argument === '--session-file') {
38
- sessionFile = sessionFilePath(rest[++index]);
20
+ if (argument === '--session-file') {
21
+ sessionFile = absoluteFilePath('--session-file', rest[++index]);
39
22
  }
40
23
  else if (argument.startsWith('--session-file=')) {
41
- sessionFile = sessionFilePath(argument.slice('--session-file='.length));
24
+ sessionFile = absoluteFilePath('--session-file', argument.slice('--session-file='.length));
42
25
  }
43
26
  else if (argument === '--credential-file') {
44
27
  credentialFile = absoluteFilePath('--credential-file', rest[++index]);
@@ -52,6 +35,12 @@ export function parseArgs(argv) {
52
35
  else if (argument.startsWith('--secrets-file=')) {
53
36
  secretsFile = absoluteFilePath('--secrets-file', argument.slice('--secrets-file='.length));
54
37
  }
38
+ else if (argument === '--as') {
39
+ identity = requiredValue('--as', rest[++index]);
40
+ }
41
+ else if (argument.startsWith('--as=')) {
42
+ identity = requiredValue('--as', argument.slice('--as='.length));
43
+ }
55
44
  else if (argument === '--format') {
56
45
  format = lintFormat(rest[++index]);
57
46
  }
@@ -64,7 +53,13 @@ export function parseArgs(argv) {
64
53
  else if (argument.startsWith('--environment=')) {
65
54
  environment = requiredValue('--environment', argument.slice('--environment='.length));
66
55
  }
67
- else if (argument === '--fix') {
56
+ else if (argument === '--suite') {
57
+ suite = requiredValue('--suite', rest[++index]);
58
+ }
59
+ else if (argument.startsWith('--suite=')) {
60
+ suite = requiredValue('--suite', argument.slice('--suite='.length));
61
+ }
62
+ else if (argument === '--fix' || argument === '--deploy-only') {
68
63
  continue;
69
64
  }
70
65
  else if (argument.startsWith('-')) {
@@ -79,59 +74,69 @@ export function parseArgs(argv) {
79
74
  if (format !== undefined && command !== 'lint') {
80
75
  throw new Error('`--format` is only valid for `lint`.');
81
76
  }
82
- if ((port !== undefined ||
83
- host !== undefined ||
84
- sessionFile !== undefined ||
85
- credentialFile !== undefined ||
86
- secretsFile !== undefined) &&
77
+ if ((sessionFile !== undefined || credentialFile !== undefined || secretsFile !== undefined) &&
87
78
  command !== 'dev') {
88
- throw new Error('`--port`, `--host`, `--session-file`, `--credential-file`, and `--secrets-file` are only valid for `dev`.');
79
+ throw new Error('`--session-file`, `--credential-file`, and `--secrets-file` are only valid for `dev`.');
80
+ }
81
+ if (identity !== undefined && credentialFile !== undefined) {
82
+ throw new Error('Choose either `--as` or `--credential-file`, not both.');
89
83
  }
90
- if (environment !== undefined && !['dev', 'deploy'].includes(command ?? '')) {
91
- throw new Error('`--environment` is only valid for dev or deploy.');
84
+ if ((deployOnly || identity !== undefined) && command !== 'dev' && command !== 'deploy') {
85
+ throw new Error('`--deploy-only` and `--as` are only valid for `dev` or `deploy`.');
86
+ }
87
+ if (environment !== undefined && command !== 'dev' && command !== 'deploy') {
88
+ if (command !== 'test') {
89
+ throw new Error('`--environment` is only valid for `dev`, `deploy`, or `test`.');
90
+ }
91
+ }
92
+ if (suite !== undefined && command !== 'test') {
93
+ throw new Error('`--suite` is only valid for `test`.');
92
94
  }
93
95
  const positionals = cleaned.filter((argument) => !argument.startsWith('-'));
94
96
  if (environment !== undefined && positionals.length > 0) {
95
- throw new Error('Choose either a positional environment or `--environment`, not both.');
97
+ throw new Error('Choose either a positional Environment or `--environment`, not both.');
96
98
  }
97
99
  switch (command) {
98
100
  case 'dev':
99
- if (positionals.length > 1)
100
- throw new Error('`dev` accepts at most one environment.');
101
- return {
102
- command: 'dev',
103
- env: environment ?? positionals[0] ?? 'dev',
104
- ...(port !== undefined ? { port } : {}),
105
- ...(host !== undefined ? { host } : {}),
106
- ...(sessionFile !== undefined ? { sessionFile } : {}),
107
- ...(credentialFile !== undefined ? { credentialFile } : {}),
108
- ...(secretsFile !== undefined ? { secretsFile } : {}),
109
- };
110
101
  case 'deploy': {
111
- if (positionals.length > 1)
112
- throw new Error('`deploy` accepts exactly one environment.');
113
- const env = environment ?? positionals[0];
114
- if (!env)
115
- throw new Error('`deploy` requires an env key, e.g. `deploy prod`.');
102
+ if (positionals.length > 1) {
103
+ throw new Error(`\`${command}\` accepts exactly one Environment.`);
104
+ }
105
+ const env = environment ?? positionals[0] ?? (command === 'dev' ? 'development' : undefined);
106
+ if (!env) {
107
+ throw new Error(`\`${command}\` requires an Environment, e.g. \`${command} development\`.`);
108
+ }
116
109
  return {
117
- command: 'deploy',
110
+ command,
118
111
  env,
112
+ ...(deployOnly ? { deployOnly: true } : {}),
113
+ ...(identity === undefined ? {} : { identity }),
114
+ ...(credentialFile === undefined ? {} : { credentialFile }),
115
+ ...(sessionFile === undefined ? {} : { sessionFile }),
116
+ ...(secretsFile === undefined ? {} : { secretsFile }),
119
117
  };
120
118
  }
121
119
  case 'build':
122
- if (positionals.length > 0)
123
- throw new Error('`build` does not accept positional arguments.');
124
- return { command: 'build', env: 'dev' };
125
120
  case 'package':
126
- if (positionals.length > 0)
127
- throw new Error('`package` does not accept positional arguments.');
128
- return { command: 'package', env: 'dev' };
121
+ if (positionals.length > 0) {
122
+ throw new Error(`\`${command}\` does not accept positional arguments.`);
123
+ }
124
+ return { command, env: '' };
125
+ case 'test':
126
+ if (positionals.length > 0) {
127
+ throw new Error('`test` does not accept positional arguments; use `--environment`.');
128
+ }
129
+ return {
130
+ command: 'test',
131
+ env: environment ?? '',
132
+ ...(suite === undefined ? {} : { suite }),
133
+ };
129
134
  case 'lint':
130
135
  if (positionals.length > 0)
131
136
  throw new Error('`lint` does not accept positional arguments.');
132
137
  return {
133
138
  command: 'lint',
134
- env: 'dev',
139
+ env: '',
135
140
  ...(fix ? { fix: true } : {}),
136
141
  ...(format ? { format } : {}),
137
142
  };
@@ -139,50 +144,23 @@ export function parseArgs(argv) {
139
144
  throw new Error(command ? `Unknown command "${command}".` : 'Missing command.');
140
145
  }
141
146
  }
142
- function normalizeHost(input) {
143
- if (!input || input.startsWith('-')) {
144
- throw new Error(`--host needs a public URL, got "${input ?? ''}"`);
145
- }
146
- try {
147
- const url = new URL(input);
148
- if ((url.protocol !== 'https:' && url.protocol !== 'http:') ||
149
- url.username !== '' ||
150
- url.password !== '' ||
151
- url.pathname !== '/' ||
152
- url.search !== '' ||
153
- url.hash !== '' ||
154
- privateHostname(url.hostname))
155
- throw new Error('invalid');
156
- return url.origin;
157
- }
158
- catch {
159
- throw new Error(`--host needs a valid URL, got "${input}"`);
160
- }
161
- }
162
- function privateHostname(input) {
163
- const host = input
164
- .toLowerCase()
165
- .replace(/^\[|\]$/gu, '')
166
- .replace(/\.$/u, '');
167
- if (host === 'localhost' || host.endsWith('.localhost'))
168
- return true;
169
- if (isIP(host) === 4) {
170
- const parts = host.split('.').map(Number);
171
- return (parts[0] === 0 ||
172
- parts[0] === 10 ||
173
- parts[0] === 127 ||
174
- (parts[0] === 169 && parts[1] === 254) ||
175
- (parts[0] === 172 && (parts[1] ?? 0) >= 16 && (parts[1] ?? 0) <= 31) ||
176
- (parts[0] === 192 && parts[1] === 168));
147
+ function parseUpgrade(args) {
148
+ let channel = 'beta';
149
+ let check = false;
150
+ for (let index = 0; index < args.length; index++) {
151
+ const argument = args[index];
152
+ if (argument === '--check')
153
+ check = true;
154
+ else if (argument === '--channel' || argument.startsWith('--channel=')) {
155
+ channel = requiredValue('--channel', argument === '--channel' ? args[++index] : argument.slice(10));
156
+ if (!/^[A-Za-z][A-Za-z0-9._-]*$/u.test(channel)) {
157
+ throw new Error('--channel must be a registry dist-tag, such as beta or latest.');
158
+ }
159
+ }
160
+ else
161
+ throw new Error(`Unknown upgrade argument "${argument}".`);
177
162
  }
178
- if (isIP(host) !== 6)
179
- return false;
180
- return (host === '::' ||
181
- host === '::1' ||
182
- host.startsWith('fc') ||
183
- host.startsWith('fd') ||
184
- /^fe[89ab]/u.test(host) ||
185
- /^::ffff:(?:0|10|127|169\.254|172\.(?:1[6-9]|2\d|3[01])|192\.168)\./u.test(host));
163
+ return { command: 'upgrade', env: '', channel, check };
186
164
  }
187
165
  function lintFormat(input) {
188
166
  if (input !== 'stylish' && input !== 'json') {
@@ -195,9 +173,6 @@ function requiredValue(flag, input) {
195
173
  throw new Error(`${flag} needs a value.`);
196
174
  return input;
197
175
  }
198
- function sessionFilePath(input) {
199
- return absoluteFilePath('--session-file', input);
200
- }
201
176
  function absoluteFilePath(flag, input) {
202
177
  const value = requiredValue(flag, input);
203
178
  if (!isAbsolute(value) || normalize(value) !== value) {
@@ -0,0 +1,5 @@
1
+ /** Build one mutually exclusive authority argument set for an Astrale CLI operation. */
2
+ export declare function astraleAuthorityArguments(input: {
3
+ readonly identity?: string;
4
+ readonly credential?: string;
5
+ }): readonly string[];
@@ -0,0 +1,11 @@
1
+ /** Build one mutually exclusive authority argument set for an Astrale CLI operation. */
2
+ export function astraleAuthorityArguments(input) {
3
+ if (input.identity !== undefined && input.credential !== undefined) {
4
+ throw new TypeError('Astrale authority cannot combine an identity and a credential.');
5
+ }
6
+ return input.credential === undefined
7
+ ? input.identity === undefined
8
+ ? Object.freeze([])
9
+ : Object.freeze(['--as', input.identity])
10
+ : Object.freeze(['--creds', input.credential]);
11
+ }
@@ -0,0 +1,2 @@
1
+ /** Resolve one exact executable for a complete sequence of Kernel CLI operations. */
2
+ export declare function resolveAstraleExecutable(input?: string): Promise<string>;
@@ -0,0 +1,47 @@
1
+ import { constants } from 'node:fs';
2
+ import { access, readFile, realpath } from 'node:fs/promises';
3
+ import { homedir } from 'node:os';
4
+ import { delimiter, isAbsolute, join } from 'node:path';
5
+ /** Resolve one exact executable for a complete sequence of Kernel CLI operations. */
6
+ export async function resolveAstraleExecutable(input = 'astrale') {
7
+ const candidates = isAbsolute(input) ? [input] : await executableCandidates(input);
8
+ for (const candidate of candidates) {
9
+ try {
10
+ await access(candidate, constants.X_OK);
11
+ return await realpath(candidate);
12
+ }
13
+ catch {
14
+ // Continue through the bounded recorded-install and PATH candidates.
15
+ }
16
+ }
17
+ throw new TypeError('Astrale CLI is unavailable. Install it with the official Astrale installer.');
18
+ }
19
+ async function executableCandidates(input) {
20
+ const path = (process.env.PATH ?? '')
21
+ .split(delimiter)
22
+ .filter(Boolean)
23
+ .map((directory) => join(directory, input));
24
+ if (input !== 'astrale')
25
+ return path;
26
+ const installed = await recordedInstallation();
27
+ return installed === undefined ? path : [installed, ...path];
28
+ }
29
+ async function recordedInstallation() {
30
+ const home = process.env.ASTRALE_HOME ?? join(homedir(), '.astrale');
31
+ try {
32
+ const decoded = JSON.parse(await readFile(join(home, 'install.json'), 'utf8'));
33
+ if (typeof decoded !== 'object' ||
34
+ decoded === null ||
35
+ !('method' in decoded) ||
36
+ decoded.method !== 'script' ||
37
+ !('bin' in decoded) ||
38
+ typeof decoded.bin !== 'string' ||
39
+ !isAbsolute(decoded.bin)) {
40
+ return undefined;
41
+ }
42
+ return decoded.bin;
43
+ }
44
+ catch {
45
+ return undefined;
46
+ }
47
+ }
@@ -0,0 +1,6 @@
1
+ import type { AstraleProcessResult } from './process.js';
2
+ /** Only sanitized CLI diagnostics may be promoted through installation failures. */
3
+ export declare class AstraleCliError extends Error {
4
+ }
5
+ export declare function astraleFailure(command: string, result: AstraleProcessResult): Error;
6
+ export declare function isDomainNotInstalledFailure(stderr: string): boolean;
@@ -0,0 +1,48 @@
1
+ /** Only sanitized CLI diagnostics may be promoted through installation failures. */
2
+ export class AstraleCliError extends Error {
3
+ }
4
+ export function astraleFailure(command, result) {
5
+ let diagnostic;
6
+ try {
7
+ const failure = record(JSON.parse(result.stderr));
8
+ const error = admittedCode(failure.error);
9
+ const reason = recordOrUndefined(failure.reason);
10
+ const reasonCode = admittedCode(reason?.code);
11
+ diagnostic =
12
+ error === undefined ? undefined : reasonCode === undefined ? error : `${error}/${reasonCode}`;
13
+ }
14
+ catch {
15
+ // Never forward raw stderr because a credential-bearing command owns it.
16
+ }
17
+ return new AstraleCliError(`Astrale CLI ${command} failed${diagnostic === undefined ? '' : ` (${diagnostic})`}.`);
18
+ }
19
+ function admittedCode(input) {
20
+ return typeof input === 'string' && /^[A-Z][A-Z0-9_]{0,63}$/u.test(input) ? input : undefined;
21
+ }
22
+ function recordOrUndefined(input) {
23
+ return input !== null && typeof input === 'object' && !Array.isArray(input)
24
+ ? input
25
+ : undefined;
26
+ }
27
+ export function isDomainNotInstalledFailure(stderr) {
28
+ try {
29
+ const failure = record(JSON.parse(stderr));
30
+ if (failure.error === 'DOMAIN_NOT_INSTALLED')
31
+ return true;
32
+ const reason = failure.reason;
33
+ return (failure.error === 'RESPONSE_ERROR' &&
34
+ reason !== null &&
35
+ typeof reason === 'object' &&
36
+ !Array.isArray(reason) &&
37
+ Reflect.get(reason, 'code') === 'SCHEMA_NOT_FOUND');
38
+ }
39
+ catch {
40
+ return false;
41
+ }
42
+ }
43
+ function record(input) {
44
+ if (input === null || typeof input !== 'object' || Array.isArray(input)) {
45
+ throw new TypeError('Expected an object response.');
46
+ }
47
+ return input;
48
+ }
@@ -0,0 +1,11 @@
1
+ import { runAstrale } from './process.js';
2
+ /** Resolve and probe a bookmark through the pinned CLI, preserving its TLS trust. */
3
+ export declare function resolveAstraleInstanceIssuer(input: {
4
+ readonly executable: string;
5
+ readonly projectDir: string;
6
+ readonly instance: string;
7
+ readonly expectedIssuer?: string;
8
+ readonly signal: AbortSignal;
9
+ }, dependencies?: {
10
+ readonly run: typeof runAstrale;
11
+ }): Promise<string>;