@kitsy/cnos-docs 1.5.0 → 1.6.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.
- package/docs/api/browser.mdx +2 -0
- package/docs/api/runtime.mdx +20 -0
- package/docs/cli/build.mdx +13 -11
- package/docs/getting-started/quick-start.mdx +7 -0
- package/docs/guides/backend.mdx +17 -2
- package/docs/guides/frontend-next.mdx +13 -0
- package/docs/guides/frontend-vite.mdx +14 -0
- package/docs/guides/frontend-webpack.mdx +95 -1
- package/docs/guides/migration.mdx +108 -7
- package/docs/guides/workspaces.mdx +77 -7
- package/package.json +1 -1
package/docs/api/browser.mdx
CHANGED
|
@@ -14,3 +14,5 @@ console.log(cnos('public.app.apiBaseUrl'));
|
|
|
14
14
|
Only promoted browser-safe values are available here.
|
|
15
15
|
|
|
16
16
|
Framework integrations such as `@kitsy/cnos-vite`, `@kitsy/cnos-next`, and `@kitsy/cnos-webpack` are responsible for embedding that browser payload during the build.
|
|
17
|
+
|
|
18
|
+
The browser runtime does not fetch config over the network. It reads from data already embedded into the bundle/runtime globals by the framework integration, so it follows the same bundle and service-worker caching behavior as the rest of your frontend assets.
|
package/docs/api/runtime.mdx
CHANGED
|
@@ -32,6 +32,12 @@ The runtime currently exposes:
|
|
|
32
32
|
- `cnos.toNamespace(namespace)`
|
|
33
33
|
- `cnos.toEnv()`
|
|
34
34
|
- `cnos.toPublicEnv()`
|
|
35
|
+
- `cnos.toServerProjection()`
|
|
36
|
+
- `cnos.format(message)`
|
|
37
|
+
- `cnos.log(message)`
|
|
38
|
+
- `cnos.loadProjection(path)`
|
|
39
|
+
- `cnos.refreshSecrets()`
|
|
40
|
+
- `cnos.refreshSecret(key)`
|
|
35
41
|
|
|
36
42
|
Example:
|
|
37
43
|
|
|
@@ -45,6 +51,20 @@ const dbPassword = cnos.secret('db.password');
|
|
|
45
51
|
const profile = cnos.meta('profile');
|
|
46
52
|
const port = cnos.readOr('value.server.port', 3000);
|
|
47
53
|
const flags = cnos.toNamespace('flags');
|
|
54
|
+
const line = cnos.format('Starting server at ${value.server.port}');
|
|
55
|
+
|
|
56
|
+
cnos.log('Starting server at ${value.server.port}');
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`cnos.format(...)` and `cnos.log(...)` interpolate `${logical.key}` placeholders through the active runtime. Missing keys are left unchanged.
|
|
60
|
+
|
|
61
|
+
For server packaging, the runtime can also bootstrap from a projection artifact:
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
import cnos from '@kitsy/cnos';
|
|
65
|
+
|
|
66
|
+
await cnos.loadProjection('./.cnos-server.json');
|
|
67
|
+
await cnos.ready();
|
|
48
68
|
```
|
|
49
69
|
|
|
50
70
|
## Typed values
|
package/docs/cli/build.mdx
CHANGED
|
@@ -1,23 +1,25 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: cnos build
|
|
3
|
-
description: Build
|
|
2
|
+
title: cnos build
|
|
3
|
+
description: Build derived CNOS projection artifacts for server, browser, env, and public surfaces.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# cnos build
|
|
6
|
+
# cnos build
|
|
7
7
|
|
|
8
|
-
Use `build
|
|
8
|
+
Use `build` when a repo needs a deterministic artifact derived from CNOS.
|
|
9
9
|
|
|
10
10
|
```bash
|
|
11
|
+
cnos build server --to .cnos-server.json
|
|
12
|
+
cnos build browser --to .cnos-browser.json
|
|
11
13
|
cnos build env --profile local --to .env.local
|
|
12
14
|
cnos build env --profile stage --to .env.stage
|
|
13
|
-
cnos build
|
|
15
|
+
cnos build public --framework vite --to .env.production
|
|
14
16
|
```
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
Targets:
|
|
17
19
|
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
- writes
|
|
21
|
-
-
|
|
20
|
+
- `build server` writes a server runtime projection with resolved values plus secret refs
|
|
21
|
+
- `build browser` writes a public-only browser projection
|
|
22
|
+
- `build env` writes explicit env mappings in formats like `dotenv`, `shell`, `json`, `yaml`, `docker-env`, or `toml`
|
|
23
|
+
- `build public` writes promoted public env with optional framework prefixes like Vite and Next
|
|
22
24
|
|
|
23
|
-
|
|
25
|
+
All build artifacts are derived output. `.cnos` remains the source of truth.
|
|
@@ -45,3 +45,10 @@ For frontend builds:
|
|
|
45
45
|
- Vite: `@kitsy/cnos-vite`
|
|
46
46
|
- Webpack/static bundles: `@kitsy/cnos-webpack`
|
|
47
47
|
- Next.js: `@kitsy/cnos-next`
|
|
48
|
+
|
|
49
|
+
For webpack/static bundles, build-time settings can come from CNOS too:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
cnos set value dev.server.port 8800
|
|
53
|
+
npm run dev
|
|
54
|
+
```
|
package/docs/guides/backend.mdx
CHANGED
|
@@ -10,6 +10,15 @@ Backend projects usually use one of two patterns:
|
|
|
10
10
|
- `cnos run -- <command>` for zero-code-change adoption
|
|
11
11
|
- `import cnos from '@kitsy/cnos'` for direct runtime reads
|
|
12
12
|
|
|
13
|
+
For an existing Express or Node service that already uses `.env`, start with the env bridge:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
cnos build env --profile local --to .env.local
|
|
17
|
+
cnos build env --profile stage --to .env.stage
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Then keep your current `dotenv` setup while moving runtime reads to CNOS.
|
|
21
|
+
|
|
13
22
|
Example:
|
|
14
23
|
|
|
15
24
|
```ts
|
|
@@ -24,6 +33,12 @@ const token = cnos.secret('app.token');
|
|
|
24
33
|
Env export bridge:
|
|
25
34
|
|
|
26
35
|
```bash
|
|
27
|
-
cnos
|
|
28
|
-
cnos
|
|
36
|
+
cnos build env --to .env.local
|
|
37
|
+
cnos build env --profile stage --to .env.stage
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Projection-first packaging:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
cnos build server --profile prod --to .cnos-server.json
|
|
29
44
|
```
|
|
@@ -5,6 +5,12 @@ description: Use CNOS public projection with Next.js builds and browser-safe run
|
|
|
5
5
|
|
|
6
6
|
# Frontend with Next.js
|
|
7
7
|
|
|
8
|
+
If the app already depends on `NEXT_PUBLIC_*`, keep that contract while CNOS becomes the source of truth:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
cnos build public --framework next --profile prod --to .env.production
|
|
12
|
+
```
|
|
13
|
+
|
|
8
14
|
```ts
|
|
9
15
|
import { withCnosNext } from '@kitsy/cnos-next';
|
|
10
16
|
|
|
@@ -12,3 +18,10 @@ export default withCnosNext({});
|
|
|
12
18
|
```
|
|
13
19
|
|
|
14
20
|
Browser-safe values remain under `public.promote` and are exposed as `NEXT_PUBLIC_*` plus browser-runtime data for `@kitsy/cnos/browser`.
|
|
21
|
+
|
|
22
|
+
Migration path:
|
|
23
|
+
|
|
24
|
+
1. keep `NEXT_PUBLIC_*` via generated env or Next env injection
|
|
25
|
+
2. add `withCnosNext()`
|
|
26
|
+
3. move browser-safe reads to `@kitsy/cnos/browser`
|
|
27
|
+
4. move server-only reads to `@kitsy/cnos` or `@kitsy/cnos/configure`
|
|
@@ -5,6 +5,13 @@ description: Project browser-safe CNOS values into Vite and use the browser runt
|
|
|
5
5
|
|
|
6
6
|
# Frontend with Vite
|
|
7
7
|
|
|
8
|
+
If your app already uses `VITE_*`, keep that shape first and let CNOS generate it.
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
cnos build public --framework vite --profile local --to .env.local
|
|
12
|
+
cnos dev env --public --framework vite --profile local --to .env.local -- pnpm dev
|
|
13
|
+
```
|
|
14
|
+
|
|
8
15
|
Promote browser-safe values:
|
|
9
16
|
|
|
10
17
|
```yaml
|
|
@@ -32,3 +39,10 @@ import cnos from '@kitsy/cnos/browser';
|
|
|
32
39
|
console.log(cnos('public.app.apiBaseUrl'));
|
|
33
40
|
console.log(import.meta.env.VITE_APP_API_BASE_URL);
|
|
34
41
|
```
|
|
42
|
+
|
|
43
|
+
Migration path:
|
|
44
|
+
|
|
45
|
+
1. keep `VITE_*` working through generated env files
|
|
46
|
+
2. add `createCnosVitePlugin()`
|
|
47
|
+
3. move browser reads to `@kitsy/cnos/browser`
|
|
48
|
+
4. stop treating handwritten `.env.local` as the source of truth
|
|
@@ -7,6 +7,26 @@ description: Use CNOS public projection with webpack builds, webpack-dev-server,
|
|
|
7
7
|
|
|
8
8
|
CNOS integrates with webpack through `@kitsy/cnos-webpack`. This covers the common static-bundle case where webpack produces a browser build that is then deployed as static assets.
|
|
9
9
|
|
|
10
|
+
## Highlight: change webpack dev-server config from CNOS
|
|
11
|
+
|
|
12
|
+
Once webpack reads build-time config through `createCnos()`, changing a setting such as the dev-server port is just a config write:
|
|
13
|
+
|
|
14
|
+
```powershell
|
|
15
|
+
cnos set value dev.server.port 8800
|
|
16
|
+
npm run dev
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Typical result:
|
|
20
|
+
|
|
21
|
+
```text
|
|
22
|
+
set value.dev.server.port in .cnos\values\dev.yml
|
|
23
|
+
Cnos value.dev.server.port: 8800
|
|
24
|
+
[webpack-dev-server] Project is running at:
|
|
25
|
+
[webpack-dev-server] Loopback: http://localhost:8800/
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
This is the main benefit of the CNOS webpack path: you change config in `.cnos`, not scattered build scripts or ad hoc env files.
|
|
29
|
+
|
|
10
30
|
Promote browser-safe values:
|
|
11
31
|
|
|
12
32
|
```yaml
|
|
@@ -16,7 +36,7 @@ public:
|
|
|
16
36
|
- flags.upi_enabled
|
|
17
37
|
```
|
|
18
38
|
|
|
19
|
-
Use an async webpack config:
|
|
39
|
+
Use an async webpack config. If your repo already uses ESM webpack config, this is the cleanest shape:
|
|
20
40
|
|
|
21
41
|
```ts
|
|
22
42
|
import { createCnos } from '@kitsy/cnos/configure';
|
|
@@ -40,6 +60,38 @@ export default async () => {
|
|
|
40
60
|
};
|
|
41
61
|
```
|
|
42
62
|
|
|
63
|
+
If your project uses CommonJS-style webpack config, keep `module.exports = async () => ...` and load CNOS with dynamic `import()` inside the async factory:
|
|
64
|
+
|
|
65
|
+
```js
|
|
66
|
+
const ESLintPlugin = require('eslint-webpack-plugin');
|
|
67
|
+
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
68
|
+
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
|
69
|
+
|
|
70
|
+
module.exports = async () => {
|
|
71
|
+
const { createCnos } = await import('@kitsy/cnos/configure');
|
|
72
|
+
const { CnosWebpackPlugin } = await import('@kitsy/cnos-webpack');
|
|
73
|
+
|
|
74
|
+
const profile = process.env.NODE_ENV === 'production' ? 'prod' : 'local';
|
|
75
|
+
const cnos = await createCnos({ profile });
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
devServer: {
|
|
79
|
+
port: Number(cnos.readOr('value.devServer.port', 3000)),
|
|
80
|
+
},
|
|
81
|
+
plugins: [
|
|
82
|
+
new CnosWebpackPlugin({ profile }),
|
|
83
|
+
new HtmlWebpackPlugin({
|
|
84
|
+
templateParameters: {
|
|
85
|
+
appName: cnos.read('public.app.name'),
|
|
86
|
+
},
|
|
87
|
+
}),
|
|
88
|
+
new MiniCssExtractPlugin(),
|
|
89
|
+
new ESLintPlugin(),
|
|
90
|
+
],
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
```
|
|
94
|
+
|
|
43
95
|
Read in browser code:
|
|
44
96
|
|
|
45
97
|
```ts
|
|
@@ -54,5 +106,47 @@ The webpack plugin:
|
|
|
54
106
|
- injects `process.env.*` define replacements for promoted public values
|
|
55
107
|
- embeds `globalThis.__CNOS_BROWSER_DATA__` for `@kitsy/cnos/browser`
|
|
56
108
|
- keeps server-only `value.*` and `secret.*` out of the browser bundle
|
|
109
|
+
- uses no prefix by default for webpack public env unless you configure `public.frameworks.webpack` or pass `prefix`
|
|
110
|
+
|
|
111
|
+
## Bundle and cache behavior
|
|
112
|
+
|
|
113
|
+
CNOS does not add a runtime fetch layer to the browser bundle.
|
|
114
|
+
|
|
115
|
+
- `@kitsy/cnos-webpack` resolves public config at build time
|
|
116
|
+
- browser-safe values are embedded into the existing webpack bundle through `DefinePlugin` and `globalThis.__CNOS_BROWSER_DATA__`
|
|
117
|
+
- `@kitsy/cnos/browser` is a small reader over that embedded payload
|
|
118
|
+
- if your app does not import `@kitsy/cnos/browser`, webpack can leave it out of the browser bundle
|
|
119
|
+
- if your app does import `@kitsy/cnos/browser`, it is bundled like any other app dependency and follows your existing webpack and service-worker caching strategy
|
|
120
|
+
|
|
121
|
+
So if your site already uses `sw.js` for offline behavior, CNOS does not disable or bypass that. CNOS becomes part of the same built assets your service worker already caches.
|
|
57
122
|
|
|
58
123
|
If you need build-time server config such as `devServer.port`, read it in the webpack config through `createCnos()` so dev and production builds use the same CNOS source of truth.
|
|
124
|
+
|
|
125
|
+
## Plugin order
|
|
126
|
+
|
|
127
|
+
Recommended order:
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
plugins: [
|
|
131
|
+
new CnosWebpackPlugin({ profile }),
|
|
132
|
+
new HtmlWebpackPlugin(...),
|
|
133
|
+
new MiniCssExtractPlugin(...),
|
|
134
|
+
new CopyPlugin(...),
|
|
135
|
+
new ESLintPlugin(...),
|
|
136
|
+
]
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Guidance:
|
|
140
|
+
- Put `CnosWebpackPlugin` early in the plugin list.
|
|
141
|
+
- `HtmlWebpackPlugin`, `MiniCssExtractPlugin`, `CopyPlugin`, and `ESLintPlugin` can follow it.
|
|
142
|
+
- If you need CNOS values in HTML templates, read them with `createCnos()` in the webpack config and pass them through `templateParameters`. `DefinePlugin` replacements do not automatically populate HTML templates.
|
|
143
|
+
|
|
144
|
+
## Why `require is not defined` happens
|
|
145
|
+
|
|
146
|
+
If webpack-cli logs a path like `file:///.../webpack.config.js`, it loaded your config as ESM. In that mode, `require(...)` is not available.
|
|
147
|
+
|
|
148
|
+
Choose one style and stay consistent:
|
|
149
|
+
- ESM: `webpack.config.mjs` or a package with `"type": "module"` and `import ...`
|
|
150
|
+
- CommonJS: `webpack.config.cjs` or CommonJS `module.exports = async () => ...`, using dynamic `import()` for CNOS ESM packages
|
|
151
|
+
|
|
152
|
+
Do not mix top-level `await` plus `require(...)` in a config file that webpack treats as ESM.
|
|
@@ -5,7 +5,16 @@ description: Move existing env-based projects onto CNOS without losing current w
|
|
|
5
5
|
|
|
6
6
|
# Migrating from .env
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
CNOS migration works best as a bridge, not a flag day.
|
|
9
|
+
|
|
10
|
+
The pattern is:
|
|
11
|
+
|
|
12
|
+
1. Keep `.cnos` as the new source of truth.
|
|
13
|
+
2. Keep your current app/build/runtime working.
|
|
14
|
+
3. Generate whatever bridge artifact the existing stack needs.
|
|
15
|
+
4. Migrate direct env reads to CNOS app by app.
|
|
16
|
+
|
|
17
|
+
Use the migration assistant when you want help mapping existing env usage:
|
|
9
18
|
|
|
10
19
|
```bash
|
|
11
20
|
cnos migrate --scan src --dry-run
|
|
@@ -13,20 +22,112 @@ cnos migrate --apply
|
|
|
13
22
|
cnos migrate --apply --rewrite
|
|
14
23
|
```
|
|
15
24
|
|
|
16
|
-
|
|
25
|
+
## Plain Node or Express with `.env`
|
|
26
|
+
|
|
27
|
+
If your service currently starts with `dotenv`, keep that flow first.
|
|
17
28
|
|
|
18
29
|
```bash
|
|
19
|
-
cnos build env --to .env.local
|
|
30
|
+
cnos build env --profile local --to .env.local
|
|
20
31
|
cnos build env --profile stage --to .env.stage
|
|
21
|
-
cnos dev env --profile local --to .env.local -- pnpm dev
|
|
22
32
|
```
|
|
23
33
|
|
|
24
|
-
|
|
34
|
+
Then your existing `dotenv` bootstrap keeps working.
|
|
35
|
+
|
|
36
|
+
Move server code gradually:
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
import cnos from '@kitsy/cnos';
|
|
40
|
+
|
|
41
|
+
await cnos.ready();
|
|
42
|
+
|
|
43
|
+
const port = cnos.readOr('value.server.port', 3000);
|
|
44
|
+
const token = cnos.secret('app.token');
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
For runtime packaging instead of env files:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
cnos build server --profile prod --to .cnos-server.json
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Vite Frontend
|
|
54
|
+
|
|
55
|
+
If you already use `VITE_*` env variables, keep that contract first.
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
cnos build public --framework vite --profile local --to .env.local
|
|
59
|
+
cnos dev env --public --framework vite --profile local --to .env.local -- pnpm dev
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Then add `@kitsy/cnos-vite` and migrate browser reads to:
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
import cnos from '@kitsy/cnos/browser';
|
|
66
|
+
|
|
67
|
+
cnos('public.app.apiBaseUrl');
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Next.js
|
|
71
|
+
|
|
72
|
+
If you already use `NEXT_PUBLIC_*`, keep that contract while adopting CNOS.
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
cnos build public --framework next --profile prod --to .env.production
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Then wire `@kitsy/cnos-next` so Next gets public data from CNOS directly and browser code can read `public.*` through `@kitsy/cnos/browser`.
|
|
79
|
+
|
|
80
|
+
## Webpack Static Frontend
|
|
81
|
+
|
|
82
|
+
If you already have a `webpack.config.js`, you do not need to invent a new runtime.
|
|
83
|
+
|
|
84
|
+
- read build-time settings such as dev-server port through `createCnos()`
|
|
85
|
+
- inject browser-safe config through `@kitsy/cnos-webpack`
|
|
86
|
+
- keep generated `.env.*` files only if your repo still expects them
|
|
87
|
+
|
|
88
|
+
Example bridge:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
cnos build public --profile local --to .env.local
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Longer-term path:
|
|
95
|
+
|
|
96
|
+
- `CnosWebpackPlugin` for browser-safe values
|
|
97
|
+
- `createCnos()` inside webpack config for build-time settings
|
|
98
|
+
|
|
99
|
+
## pnpm Monorepo
|
|
100
|
+
|
|
101
|
+
For monorepos, do not copy `.cnos` into every package.
|
|
102
|
+
|
|
103
|
+
- keep one repo-root `.cnos/`
|
|
104
|
+
- add `.cnosrc.yml` to each consuming app/package
|
|
105
|
+
- optionally add a repo-root `.cnosrc.yml` if the root also consumes CNOS
|
|
106
|
+
|
|
107
|
+
Example:
|
|
108
|
+
|
|
109
|
+
```yaml
|
|
110
|
+
# apps/travel/.cnosrc.yml
|
|
111
|
+
root: ../../.cnos
|
|
112
|
+
workspace: travel
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Server-side packages can use projections:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
cnos build server --workspace travel --profile prod --to apps/travel/.cnos-server.json
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Legacy env-based packages can still use:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
cnos build env --workspace travel --profile local --to apps/travel/.env.local
|
|
125
|
+
```
|
|
25
126
|
|
|
26
127
|
Recommended migration sequence:
|
|
27
128
|
|
|
28
129
|
1. Keep `.cnos` as the source of truth.
|
|
29
|
-
2. Generate `.env
|
|
130
|
+
2. Generate `.env.*`, browser, or server projection artifacts for legacy tools.
|
|
30
131
|
3. Migrate server code to `@kitsy/cnos`.
|
|
31
132
|
4. Migrate browser code to `@kitsy/cnos/browser`.
|
|
32
|
-
5. Remove env-file dependencies app by app.
|
|
133
|
+
5. Remove handwritten env-file dependencies app by app.
|
|
@@ -5,18 +5,88 @@ description: Use CNOS workspaces to model multiple apps inside one repo.
|
|
|
5
5
|
|
|
6
6
|
# Workspaces and Monorepos
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
For monorepos, keep one authoritative `.cnos/` tree at the repo root and put a `.cnosrc.yml` anchor in each consuming app or package.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Repo root as both author and consumer:
|
|
11
11
|
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
cnos
|
|
15
|
-
|
|
12
|
+
```yaml
|
|
13
|
+
# .cnosrc.yml
|
|
14
|
+
root: ./.cnos
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Child app:
|
|
18
|
+
|
|
19
|
+
```yaml
|
|
20
|
+
# apps/travel/.cnosrc.yml
|
|
21
|
+
root: ../../.cnos
|
|
22
|
+
workspace: travel
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`.cnosrc.yml` is the only discovery anchor. CNOS does not walk upward looking for `.cnos` directories. It looks for `.cnosrc.yml` within a bounded package-root search window, then resolves the real `.cnos` root from there.
|
|
26
|
+
|
|
27
|
+
Typical manifest shape:
|
|
28
|
+
|
|
29
|
+
```yaml
|
|
30
|
+
workspaces:
|
|
31
|
+
default: root
|
|
32
|
+
items:
|
|
33
|
+
root: {}
|
|
34
|
+
travel:
|
|
35
|
+
extends: [root]
|
|
36
|
+
food:
|
|
37
|
+
extends: [root]
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
This lets you keep shared values in `root` and override only what each app needs in `travel`, `food`, or other child workspaces.
|
|
41
|
+
|
|
42
|
+
Read from an app package without passing a root manually:
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import cnos from '@kitsy/cnos';
|
|
46
|
+
|
|
47
|
+
await cnos.ready();
|
|
48
|
+
console.log(cnos('value.app.name'));
|
|
16
49
|
```
|
|
17
50
|
|
|
18
51
|
Override per command when needed:
|
|
19
52
|
|
|
20
53
|
```bash
|
|
21
|
-
cnos list values --workspace
|
|
54
|
+
cnos list values --workspace travel
|
|
55
|
+
cnos build server --workspace travel --profile prod --to apps/travel/.cnos-server.json
|
|
22
56
|
```
|
|
57
|
+
|
|
58
|
+
## Runtime Projection
|
|
59
|
+
|
|
60
|
+
The authoring tree stays at repo root. Runtime consumers do not need the full `.cnos/` layout.
|
|
61
|
+
|
|
62
|
+
For server packaging:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
cnos build server --workspace api-gateway --profile prod --to apps/api-gateway/.cnos-server.json
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`@kitsy/cnos` then auto-loads in this order:
|
|
69
|
+
|
|
70
|
+
1. `__CNOS_PROJECTION__`
|
|
71
|
+
2. `.cnos-server.json`
|
|
72
|
+
3. full authoring resolution through `.cnosrc.yml`
|
|
73
|
+
|
|
74
|
+
Browser packages keep using public projection through Vite, Next, webpack, or `@kitsy/cnos/build`.
|
|
75
|
+
|
|
76
|
+
## Detach and Reattach
|
|
77
|
+
|
|
78
|
+
Detach a child package into a standalone CNOS root:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
cnos workspace detach --package-root apps/travel
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
This materializes the effective config into `apps/travel/.cnos`, rewrites `apps/travel/.cnosrc.yml` to point to that local root, and stops inheriting from the parent repo.
|
|
85
|
+
|
|
86
|
+
Reattach it later:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
cnos workspace attach --package-root apps/travel
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
This imports the standalone child config back into the parent workspace model, archives the detached `.cnos`, and restores the package anchor.
|