nylorun 0.3.0-beta → 0.4.0-beta
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 +42 -0
- package/README.md +136 -60
- package/dist/cli.js +13 -11
- package/dist/doctor.d.ts +3 -1
- package/dist/doctor.js +42 -13
- package/dist/project/derived-key.d.ts +8 -0
- package/dist/project/derived-key.js +18 -0
- package/dist/project/link.d.ts +32 -4
- package/dist/project/link.js +83 -14
- package/dist/project/seed.d.ts +27 -0
- package/dist/project/seed.js +111 -0
- package/dist/stack/commands.d.ts +38 -15
- package/dist/stack/commands.js +517 -144
- package/dist/stack/compose-file.d.ts +30 -11
- package/dist/stack/compose-file.js +84 -16
- package/dist/stack/env-file.d.ts +19 -3
- package/dist/stack/env-file.js +44 -4
- package/dist/stack/host-files.d.ts +9 -0
- package/dist/stack/host-files.js +24 -1
- package/dist/stack/index.d.ts +3 -3
- package/dist/stack/index.js +8 -3
- package/dist/stack/paths.d.ts +11 -3
- package/dist/stack/paths.js +9 -6
- package/dist/stack/prepare.d.ts +10 -3
- package/dist/stack/prepare.js +23 -12
- package/dist/stack/restate-identity.d.ts +1 -1
- package/dist/stack/restate-identity.js +1 -1
- package/dist/stack/stacks.d.ts +47 -0
- package/dist/stack/stacks.js +116 -0
- package/package.json +4 -4
|
@@ -6,7 +6,7 @@ import { CliError } from "../errors.js";
|
|
|
6
6
|
* every request to the Worker endpoint with an Ed25519 private key; the
|
|
7
7
|
* Runtime accepts only requests that verify against the public key.
|
|
8
8
|
*
|
|
9
|
-
* - The private key is a PKCS#8 PEM at `
|
|
9
|
+
* - The private key is a PKCS#8 PEM at `docker/restate-identity.pem` (mode
|
|
10
10
|
* 0600), mounted read-only into the restate service as
|
|
11
11
|
* `RESTATE_WORKER__INVOKER__REQUEST_IDENTITY_PRIVATE_KEY_PEM_FILE`.
|
|
12
12
|
* - The public key goes to the Runtime as `NYLORUN_RESTATE_IDENTITY_KEY`, in
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The machine's local stacks (tenancy.md §6): one installation per stack, each with its own
|
|
3
|
+
* Host root `~/.nylorun/stacks/<name>/`, Compose project `nylorun-<name>`, ports and volumes.
|
|
4
|
+
* `~/.nylorun` itself held the single stack of older releases (the legacy stack).
|
|
5
|
+
*/
|
|
6
|
+
/** A stack name: also part of its Compose project, so Compose's rules apply. */
|
|
7
|
+
export declare const STACK_NAME: RegExp;
|
|
8
|
+
/** `~/.nylorun`: the stacks, and the legacy stack's files. Tests pass another directory. */
|
|
9
|
+
export declare function defaultNylorunRoot(): string;
|
|
10
|
+
export declare function stacksDir(base: string): string;
|
|
11
|
+
export declare function stackRoot(base: string, name: string): string;
|
|
12
|
+
export declare function assertStackName(name: string, source: string): string;
|
|
13
|
+
/** A directory name as a stack name: lowercased, other characters as `-`, trimmed. */
|
|
14
|
+
export declare function sanitizeStackName(raw: string): string;
|
|
15
|
+
/** `stack.json` in a Host root: the stack's name and the project it was created for. */
|
|
16
|
+
export interface StackRecord {
|
|
17
|
+
format: 1;
|
|
18
|
+
name: string;
|
|
19
|
+
/** The project directory `nylorun start` created the stack in; absent outside a project. */
|
|
20
|
+
project?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function stackRecordPath(root: string): string;
|
|
23
|
+
export declare function readStackRecord(root: string): Promise<StackRecord | undefined>;
|
|
24
|
+
export declare function writeStackRecord(root: string, record: Omit<StackRecord, "format">): Promise<void>;
|
|
25
|
+
export interface StackEntry {
|
|
26
|
+
name: string;
|
|
27
|
+
root: string;
|
|
28
|
+
record?: StackRecord;
|
|
29
|
+
}
|
|
30
|
+
/** The stacks under `<base>/stacks`, by name. */
|
|
31
|
+
export declare function listStacks(base: string): Promise<StackEntry[]>;
|
|
32
|
+
/**
|
|
33
|
+
* The stack name for a project without a link: the directory's name, or the first `-2`,
|
|
34
|
+
* `-3`, … suffix that no stack of another project directory holds. A stack this project
|
|
35
|
+
* directory created keeps its name.
|
|
36
|
+
*/
|
|
37
|
+
export declare function chooseStackName(base: string, projectDir: string): Promise<string>;
|
|
38
|
+
/** The single stack of older releases: Compose project `nylorun`, Host root `~/.nylorun`. */
|
|
39
|
+
export interface LegacyStack {
|
|
40
|
+
root: string;
|
|
41
|
+
project: "nylorun";
|
|
42
|
+
compose: string;
|
|
43
|
+
env: string;
|
|
44
|
+
}
|
|
45
|
+
export declare function legacyStack(base: string): LegacyStack | undefined;
|
|
46
|
+
/** What `nylorun legacy delete` removes from `~/.nylorun`: the old layout only, never `stacks/`. */
|
|
47
|
+
export declare const LEGACY_ENTRIES: readonly ["host.json", "host-credentials.json", "host-state.json", "stack", "tenants", "home", "tmp", "trash"];
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { readdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
3
|
+
import { randomBytes } from "node:crypto";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
import { basename, join, resolve } from "node:path";
|
|
6
|
+
import { CliError } from "../errors.js";
|
|
7
|
+
/**
|
|
8
|
+
* The machine's local stacks (tenancy.md §6): one installation per stack, each with its own
|
|
9
|
+
* Host root `~/.nylorun/stacks/<name>/`, Compose project `nylorun-<name>`, ports and volumes.
|
|
10
|
+
* `~/.nylorun` itself held the single stack of older releases (the legacy stack).
|
|
11
|
+
*/
|
|
12
|
+
/** A stack name: also part of its Compose project, so Compose's rules apply. */
|
|
13
|
+
export const STACK_NAME = /^[a-z0-9][a-z0-9_-]*$/;
|
|
14
|
+
/** `~/.nylorun`: the stacks, and the legacy stack's files. Tests pass another directory. */
|
|
15
|
+
export function defaultNylorunRoot() {
|
|
16
|
+
return resolve(join(homedir(), ".nylorun"));
|
|
17
|
+
}
|
|
18
|
+
export function stacksDir(base) {
|
|
19
|
+
return join(base, "stacks");
|
|
20
|
+
}
|
|
21
|
+
export function stackRoot(base, name) {
|
|
22
|
+
return join(stacksDir(base), name);
|
|
23
|
+
}
|
|
24
|
+
export function assertStackName(name, source) {
|
|
25
|
+
if (!STACK_NAME.test(name))
|
|
26
|
+
throw new CliError(`${source} must be lowercase letters, digits, "-" or "_", starting with a letter or digit: ${name}`, 2);
|
|
27
|
+
return name;
|
|
28
|
+
}
|
|
29
|
+
/** A directory name as a stack name: lowercased, other characters as `-`, trimmed. */
|
|
30
|
+
export function sanitizeStackName(raw) {
|
|
31
|
+
const name = raw
|
|
32
|
+
.toLowerCase()
|
|
33
|
+
.replace(/[^a-z0-9_-]+/g, "-")
|
|
34
|
+
.replace(/-{2,}/g, "-")
|
|
35
|
+
.replace(/^[-_]+|[-_]+$/g, "");
|
|
36
|
+
return name === "" ? "stack" : name;
|
|
37
|
+
}
|
|
38
|
+
export function stackRecordPath(root) {
|
|
39
|
+
return join(root, "stack.json");
|
|
40
|
+
}
|
|
41
|
+
export async function readStackRecord(root) {
|
|
42
|
+
try {
|
|
43
|
+
const value = JSON.parse(await readFile(stackRecordPath(root), "utf8"));
|
|
44
|
+
if (typeof value?.name !== "string" || !STACK_NAME.test(value.name))
|
|
45
|
+
return undefined;
|
|
46
|
+
return {
|
|
47
|
+
format: 1,
|
|
48
|
+
name: value.name,
|
|
49
|
+
...(typeof value.project === "string" ? { project: value.project } : {}),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export async function writeStackRecord(root, record) {
|
|
57
|
+
const path = stackRecordPath(root);
|
|
58
|
+
const temporary = `${path}.${randomBytes(8).toString("hex")}.tmp`;
|
|
59
|
+
const body = { format: 1, name: record.name, ...(record.project ? { project: record.project } : {}) };
|
|
60
|
+
await writeFile(temporary, `${JSON.stringify(body, null, 2)}\n`, { mode: 0o600 });
|
|
61
|
+
await rename(temporary, path);
|
|
62
|
+
}
|
|
63
|
+
/** The stacks under `<base>/stacks`, by name. */
|
|
64
|
+
export async function listStacks(base) {
|
|
65
|
+
let entries;
|
|
66
|
+
try {
|
|
67
|
+
entries = await readdir(stacksDir(base), { withFileTypes: true });
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
const stacks = [];
|
|
73
|
+
for (const entry of entries) {
|
|
74
|
+
if (!entry.isDirectory() || !STACK_NAME.test(entry.name))
|
|
75
|
+
continue;
|
|
76
|
+
const root = stackRoot(base, entry.name);
|
|
77
|
+
const record = await readStackRecord(root);
|
|
78
|
+
stacks.push({ name: entry.name, root, ...(record ? { record } : {}) });
|
|
79
|
+
}
|
|
80
|
+
return stacks.sort((a, b) => a.name.localeCompare(b.name));
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* The stack name for a project without a link: the directory's name, or the first `-2`,
|
|
84
|
+
* `-3`, … suffix that no stack of another project directory holds. A stack this project
|
|
85
|
+
* directory created keeps its name.
|
|
86
|
+
*/
|
|
87
|
+
export async function chooseStackName(base, projectDir) {
|
|
88
|
+
const name = sanitizeStackName(basename(projectDir));
|
|
89
|
+
const stacks = await listStacks(base);
|
|
90
|
+
const candidate = new RegExp(`^${name}(?:-[0-9]+)?$`);
|
|
91
|
+
const own = stacks.find((stack) => candidate.test(stack.name) && stack.record?.project === projectDir);
|
|
92
|
+
if (own)
|
|
93
|
+
return own.name;
|
|
94
|
+
for (let suffix = 1;; suffix += 1) {
|
|
95
|
+
const next = suffix === 1 ? name : `${name}-${suffix}`;
|
|
96
|
+
if (!existsSync(stackRoot(base, next)))
|
|
97
|
+
return next;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
export function legacyStack(base) {
|
|
101
|
+
const compose = join(base, "stack", "compose.yaml");
|
|
102
|
+
if (!existsSync(compose))
|
|
103
|
+
return undefined;
|
|
104
|
+
return { root: base, project: "nylorun", compose, env: join(base, "stack", ".env") };
|
|
105
|
+
}
|
|
106
|
+
/** What `nylorun legacy delete` removes from `~/.nylorun`: the old layout only, never `stacks/`. */
|
|
107
|
+
export const LEGACY_ENTRIES = [
|
|
108
|
+
"host.json",
|
|
109
|
+
"host-credentials.json",
|
|
110
|
+
"host-state.json",
|
|
111
|
+
"stack",
|
|
112
|
+
"tenants",
|
|
113
|
+
"home",
|
|
114
|
+
"tmp",
|
|
115
|
+
"trash",
|
|
116
|
+
];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nylorun",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0-beta",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"description": "Set up and run the local Nylorun stack (Runtime and Studio) with Docker Compose",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"prepack": "npm run build"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@nylorun/core": "0.
|
|
33
|
+
"@nylorun/core": "0.10.0-beta"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"typescript": "npm:@typescript/typescript6@^6.0.2",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"nylorun": "dist/cli.js"
|
|
42
42
|
},
|
|
43
43
|
"nylorun": {
|
|
44
|
-
"runtime": "0.
|
|
45
|
-
"studio": "0.
|
|
44
|
+
"runtime": "0.15.0-beta",
|
|
45
|
+
"studio": "0.15.0-beta"
|
|
46
46
|
}
|
|
47
47
|
}
|