@toa.io/operations 1.0.0-alpha.291 → 1.0.0-alpha.292

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/CHANGELOG.md CHANGED
@@ -3,6 +3,14 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [1.0.0-alpha.292](https://github.com/toa-io/toa/compare/v1.0.0-alpha.291...v1.0.0-alpha.292) (2026-09-07)
7
+
8
+ ### Features
9
+
10
+ * **cli:** the deployment library is a peer, and the binary is the CLI's ([a923f81](https://github.com/toa-io/toa/commit/a923f8173a55ed1c091213a7c7db1863ca1d0ba6))
11
+ * **norm:** a package's definition is read by one resolver ([bffd41c](https://github.com/toa-io/toa/commit/bffd41c8d18c42786b0bf321623088b9dabc4724))
12
+
13
+
6
14
  # [1.0.0-alpha.291](https://github.com/toa-io/toa/compare/v1.0.0-alpha.290...v1.0.0-alpha.291) (2026-09-07)
7
15
 
8
16
  **Note:** Version bump only for package @toa.io/operations
@@ -1,4 +1,9 @@
1
1
  FROM node:24.14.0-alpine3.22
2
2
 
3
3
  ARG VERSION
4
- RUN npm i -g @toa.io/runtime@${VERSION} --omit=dev
4
+
5
+ # installed locally rather than globally: the binary is @toa.io/cli's, which the runtime depends
6
+ # on, and npm links a dependency's binaries only into a local `node_modules/.bin`
7
+ WORKDIR /toa
8
+ RUN npm i @toa.io/runtime@${VERSION} --omit=dev
9
+ ENV PATH=/toa/node_modules/.bin:$PATH
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toa.io/operations",
3
- "version": "1.0.0-alpha.291",
3
+ "version": "1.0.0-alpha.292",
4
4
  "type": "module",
5
5
  "description": "Toa Deployment",
6
6
  "homepage": "https://toa.io",
@@ -28,9 +28,10 @@
28
28
  "test": "echo \"Error: run tests from root\" && exit 1"
29
29
  },
30
30
  "dependencies": {
31
- "@toa.io/generic": "1.0.0-alpha.291",
32
- "@toa.io/norm": "1.0.0-alpha.291",
31
+ "@toa.io/generic": "1.0.0-alpha.292",
32
+ "@toa.io/kubernetes": "1.0.0-alpha.286",
33
+ "@toa.io/norm": "1.0.0-alpha.292",
33
34
  "js-yaml": "5.4.1"
34
35
  },
35
- "gitHead": "bcd8d8d07bd3e64fc826af8719472404662cc37f"
36
+ "gitHead": "0f6aa3ad9dbec86bb632a7975ea61d1dde1d8fc5"
36
37
  }
package/readme.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # Toa Operations
2
2
 
3
+ ## Installing
4
+
5
+ `toa deploy`, `toa build`, `toa push`, `toa env`, `toa export` and `toa conceal` need this package
6
+ beside the CLI; the runtime does not carry it, and a container that runs a composition cannot
7
+ deploy one. An application that deploys lists it with the runtime:
8
+
9
+ ```shell
10
+ $ npm i -D @toa.io/runtime @toa.io/operations
11
+ ```
12
+
13
+ A machine that only deploys needs no runtime and no extension:
14
+
15
+ ```shell
16
+ $ npm i @toa.io/cli @toa.io/operations
17
+ $ npx toa deploy production -p application
18
+ ```
19
+
20
+ What the extensions declare is read from `@toa.io/definitions`, which the CLI brings; what they run
21
+ is not needed to render a chart. `registry.services: build` is the exception: it builds an
22
+ extension's service image from the installed package, so it needs the runtime installed beside
23
+ this one. `published` does not.
24
+
3
25
  ## Compositions
4
26
 
5
27
  A composition is deployed as one pod. Beside its components it may run extension services,
@@ -27,7 +49,8 @@ Deploy images default to `FROM ghcr.io/toa-io/runtime:<runtime.version>`
27
49
  installed; composition/service Dockerfiles only install component dependencies.
28
50
 
29
51
  To use a custom base image, set `registry.build.image` (or `composition.image`).
30
- That image must provide the `toa` CLI, or install it via `registry.build.run`:
52
+ That image must provide the `toa` CLI, or install it via `registry.build.run`. The binary is
53
+ `@toa.io/cli`'s, which the runtime depends on, so a local install puts it on the `PATH`:
31
54
 
32
55
  ```yaml
33
56
  # context.toa.yaml
@@ -35,7 +58,9 @@ That image must provide the `toa` CLI, or install it via `registry.build.run`:
35
58
  registry:
36
59
  build:
37
60
  image: node:24.14.0-alpine3.22
38
- run: npm i -g @toa.io/runtime --omit=dev
61
+ run: |
62
+ npm i --prefix /toa @toa.io/runtime --omit=dev
63
+ ln -s /toa/node_modules/.bin/toa /usr/local/bin/toa
39
64
  ```
40
65
 
41
66
  #### Composition Images
@@ -1,15 +1,9 @@
1
- import { readFileSync } from 'node:fs'
2
- import { join } from 'node:path'
3
- import { createRequire } from 'node:module'
4
- import { pathToFileURL } from 'node:url'
5
- import { context as load } from '@toa.io/norm'
1
+ import { context as load, definition } from '@toa.io/norm'
6
2
  import { Process } from '../process.js'
7
3
  import { Operator } from './operator.js'
8
4
  import { Factory as ImagesFactory } from './images/index.js'
9
5
  import { Deployment } from './deployment.js'
10
6
 
11
- // a dependency is resolved the way a package is
12
- const require = createRequire(import.meta.url)
13
7
  import { Registry } from './registry.js'
14
8
  import { Composition } from './composition.js'
15
9
  import { Service } from './service.js'
@@ -110,16 +104,11 @@ export class Factory {
110
104
  }
111
105
 
112
106
  async #getDependency(reference, instances) {
113
- // a dependency may be named the way a package is or written as a directory,
114
- // and a module is loaded by file
115
- const module = await import(pathToFileURL(require.resolve(reference)).href)
116
- const pkg = JSON.parse(
117
- readFileSync(require.resolve(join(reference, 'package.json')), 'utf8')
118
- )
107
+ const { name, module } = await definition(reference)
119
108
 
120
109
  if (module.deployment === undefined) return
121
110
 
122
- const annotation = this.#context.annotations?.[pkg.name]
111
+ const annotation = this.#context.annotations?.[name]
123
112
 
124
113
  /** @type {toa.deployment.dependency.Declaration} */
125
114
  const dependency = module.deployment(instances, annotation)
@@ -2,7 +2,7 @@ import { mkdtemp, writeFile } from 'node:fs/promises'
2
2
  import { readFileSync } from 'node:fs'
3
3
  import { tmpdir } from 'node:os'
4
4
  import { join, resolve } from 'node:path'
5
- import { pathToFileURL } from 'node:url'
5
+ import { definition } from '@toa.io/norm'
6
6
 
7
7
  import { run } from '../../process.js'
8
8
  import { Service } from './service.js'
@@ -23,9 +23,7 @@ export async function publish(workspace, runtime, platforms) {
23
23
  const directory = resolve(workspace)
24
24
  const manifest = read(join(directory, 'package.json'))
25
25
 
26
- // read from the workspace, where the extension's own dependencies resolve; what is
27
- // installed below carries the same constant but not everything it takes to load it
28
- const { image } = await import(pathToFileURL(join(directory, manifest.main)).href)
26
+ const { image } = (await definition(manifest.name)).module
29
27
 
30
28
  if (image === undefined)
31
29
  throw new Error(
@@ -66,9 +66,22 @@ export class Service extends Image {
66
66
  }
67
67
 
68
68
  /**
69
+ * Where the extension is installed, which is what its image is built from. A deploy install
70
+ * carries what an extension declares and not the extension, so a service is built only where
71
+ * the runtime is installed beside the deployment library; elsewhere its image is published.
72
+ *
69
73
  * @param {string} reference
70
74
  * @returns {string}
71
75
  */
72
76
  const find = (reference) => {
73
- return dirname(require.resolve(join(reference, 'package.json')))
77
+ try {
78
+ return dirname(require.resolve(join(reference, 'package.json')))
79
+ } catch (error) {
80
+ throw new Error(
81
+ `'${reference}' is not installed, and \`registry.services: build\` builds its image ` +
82
+ 'from where it is: install the runtime beside @toa.io/operations, or take the ' +
83
+ 'image the release publishes with `registry.services: published`',
84
+ { cause: error }
85
+ )
86
+ }
74
87
  }
package/src/index.js CHANGED
@@ -1 +1,4 @@
1
1
  export * as deployment from './deployment/index.js'
2
+
3
+ // what conceals a secret in the cluster a deployment goes to; the CLI needs no package of its own for it
4
+ export * as kubernetes from '@toa.io/kubernetes'