@nylorun/cli 0.14.0-beta → 0.14.2-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 +33 -0
- package/dist/access/commands.js +1 -1
- package/dist/cli.js +1 -1
- package/dist/doctor.js +1 -1
- package/dist/installation/commands.js +1 -1
- package/dist/model/configure.js +2 -2
- package/dist/project/credentials.d.ts +3 -8
- package/dist/project/credentials.js +14 -33
- package/dist/project/env.js +1 -1
- package/dist/project/link.d.ts +5 -12
- package/dist/project/link.js +13 -43
- package/package.json +3 -3
- package/dist/home.d.ts +0 -6
- package/dist/home.js +0 -15
- package/dist/project/root.d.ts +0 -9
- package/dist/project/root.js +0 -52
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# @nylorun/cli
|
|
2
2
|
|
|
3
|
+
## 0.14.2-beta
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Pin agents to the tested release.
|
|
8
|
+
- Pin admin to the tested release.
|
|
9
|
+
- Updated dependencies
|
|
10
|
+
- Updated dependencies
|
|
11
|
+
- @nylorun/agents@0.19.1-beta
|
|
12
|
+
- @nylorun/admin@0.14.1-beta
|
|
13
|
+
|
|
14
|
+
## 0.14.1-beta
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- 7780b2f: **One client and connection layer.** The Project link and credentials are read one way, and every Runtime client shares one `/health` probe.
|
|
19
|
+
|
|
20
|
+
- `@nylorun/core`: `@nylorun/core/project` (Node only, the one Core subpath that imports Node modules) reads the Nylorun home, a local Tenant's Host root (`tenantHostRoot`), the Project root (`findProjectRoot`) and the Project link and credentials (`findLinkedProject`, `readProjectLink`, `readCredentialsFile`), validated with `ProjectLinkFileSchema` and `ProjectCredentialsFileSchema`; a broken or newer file throws `ProjectFileError`. `@nylorun/core/transport` (browser-safe) holds the `/health` compatibility probe (`checkHealth`), `parseProtocolRange` (on `ProtocolRangeSchema`, ignoring fields a newer Host adds), `describeIncompatibility`, `requestHeaders` and `readBody`.
|
|
21
|
+
- `@nylorun/agents`: `resolveConnection` and `createClient()` find the Project as every reader does: the nearest directory with `.nylorun/` from `cwd` upwards, never the home directory or above it (they used to walk to the filesystem root, and past a `.nylorun/` without a link). A link without `credentials.json`, or a link or credentials file that does not validate, is now `connection_missing` naming the file and `npx nylorun start`, instead of a raw file-system or parse error. `@nylorun/agents/client` loads the link reader only when `createClient()` resolves a connection, so it imports no Node module. The root entry re-exports `checkHealth`, `describeIncompatibility` and `parseProtocolRange`.
|
|
22
|
+
- `@nylorun/admin`: `createAdmin` reads the Project link with the same reader. A link that does not validate is now refused like one from an older nylorun (when nothing else names the Host root), and a linked Project's `credentials.json` that does not validate is `connection_missing` instead of being skipped. `@nylorun/admin/project` re-exports `@nylorun/core/project` for tools that depend on this package. The `/health` check and request headers come from `@nylorun/core/transport`.
|
|
23
|
+
- `nylorun`: reads the Project link and credentials with `@nylorun/core/project`; a credentials file whose keys are not 64 hex characters is replaced by `start`, as an unreadable one was. No command changes.
|
|
24
|
+
- `@nylorun/cli`: `nylo` reads the Project root, link and credentials through `@nylorun/admin/project` instead of its own copies, with the same messages. No command changes.
|
|
25
|
+
- `@nylorun/studio`: the server's Runtime compatibility probe is `checkHealth` from `@nylorun/agents`.
|
|
26
|
+
|
|
27
|
+
- Pin agents to the tested release.
|
|
28
|
+
- Pin admin to the tested release.
|
|
29
|
+
- Updated dependencies [7780b2f]
|
|
30
|
+
- Updated dependencies [070674d]
|
|
31
|
+
- Updated dependencies
|
|
32
|
+
- Updated dependencies
|
|
33
|
+
- @nylorun/agents@0.19.0-beta
|
|
34
|
+
- @nylorun/admin@0.14.0-beta
|
|
35
|
+
|
|
3
36
|
## 0.14.0-beta
|
|
4
37
|
|
|
5
38
|
### Major Changes
|
package/dist/access/commands.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { findProjectRoot } from "@nylorun/admin/project";
|
|
1
2
|
import { CliError } from "../errors.js";
|
|
2
3
|
import { linkedConnection, managementClient } from "../project/connection.js";
|
|
3
|
-
import { findProjectRoot } from "../project/root.js";
|
|
4
4
|
export const accessUsage = `nylo access signing-keys <list|rotate|revoke>
|
|
5
5
|
|
|
6
6
|
signing-keys list list the signing keys
|
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@ import "./baseline.js";
|
|
|
3
3
|
import { ConfigurationCancelled, configureProvider, fetchModelCatalog, } from "./model/configure.js";
|
|
4
4
|
import { putHostModel } from "./model/host-model.js";
|
|
5
5
|
import { CliError } from "./errors.js";
|
|
6
|
-
import { findProjectRoot } from "
|
|
6
|
+
import { findProjectRoot } from "@nylorun/admin/project";
|
|
7
7
|
import { printLinkedEnvExports } from "./project/env.js";
|
|
8
8
|
import { linkedConnection, managementClient } from "./project/connection.js";
|
|
9
9
|
import { accessCommand } from "./access/commands.js";
|
package/dist/doctor.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { release } from "node:os";
|
|
2
|
+
import { findProjectRoot } from "@nylorun/admin/project";
|
|
2
3
|
import { CliError } from "./errors.js";
|
|
3
4
|
import { linkedConnection, managementClient } from "./project/connection.js";
|
|
4
|
-
import { findProjectRoot } from "./project/root.js";
|
|
5
5
|
function platformLine() {
|
|
6
6
|
const os = process.platform === "darwin"
|
|
7
7
|
? "macOS"
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* API (the Project's management key).
|
|
4
4
|
*/
|
|
5
5
|
import { createInterface } from "node:readline/promises";
|
|
6
|
+
import { findProjectRoot } from "@nylorun/admin/project";
|
|
6
7
|
import { CliError } from "../errors.js";
|
|
7
8
|
import { linkedConnection, managementClient } from "../project/connection.js";
|
|
8
|
-
import { findProjectRoot } from "../project/root.js";
|
|
9
9
|
const projectRoot = () => findProjectRoot() ?? process.cwd();
|
|
10
10
|
/**
|
|
11
11
|
* `nylo status [--json]`: the Tenant, its checks and counts. A Tenant that is not open does not
|
package/dist/model/configure.js
CHANGED
|
@@ -5,7 +5,7 @@ import { join } from "node:path";
|
|
|
5
5
|
import { builtinModels } from "@earendil-works/pi-ai/providers/all";
|
|
6
6
|
import { createProvider, } from "@earendil-works/pi-ai";
|
|
7
7
|
import { stream, streamSimple, } from "@earendil-works/pi-ai/api/openai-completions";
|
|
8
|
-
import {
|
|
8
|
+
import { nylorunHome } from "@nylorun/admin/project";
|
|
9
9
|
export class ConfigurationCancelled extends Error {
|
|
10
10
|
signal;
|
|
11
11
|
exitCode;
|
|
@@ -276,7 +276,7 @@ export async function configureProvider(options = {}) {
|
|
|
276
276
|
* A stable id for this CLI installation, created on first use under the Host root.
|
|
277
277
|
* OpenAI's "Sign in with ChatGPT" sends it as the agent host id.
|
|
278
278
|
*/
|
|
279
|
-
export function installationId(home =
|
|
279
|
+
export function installationId(home = nylorunHome()) {
|
|
280
280
|
const file = join(home, "cli-installation-id");
|
|
281
281
|
try {
|
|
282
282
|
const existing = readFileSync(file, "utf8").trim();
|
|
@@ -1,14 +1,9 @@
|
|
|
1
|
+
import { type ProjectCredentials } from "@nylorun/admin/project";
|
|
1
2
|
/**
|
|
2
3
|
* Project-local credentials (mode 0600): the application key and its principal, and the
|
|
3
4
|
* management key and its principal when `nylorun start` issued one. A format 0 file may still
|
|
4
5
|
* carry a legacy `executors` map from before protocol 3; it is ignored.
|
|
5
6
|
*/
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
applicationKey: string;
|
|
9
|
-
principalId: string;
|
|
10
|
-
managementKey?: string;
|
|
11
|
-
managementPrincipalId?: string;
|
|
12
|
-
}
|
|
13
|
-
/** The Project's credentials, which `nylorun start` writes beside the link. */
|
|
7
|
+
export type { ProjectCredentials };
|
|
8
|
+
/** The Project's credentials, which `nylorun start` writes beside the link; kept 0600. */
|
|
14
9
|
export declare function readCredentials(projectRoot: string): Promise<ProjectCredentials | undefined>;
|
|
@@ -1,40 +1,21 @@
|
|
|
1
|
-
import { chmod
|
|
1
|
+
import { chmod } from "node:fs/promises";
|
|
2
|
+
import { ProjectFileError, projectCredentialsPath, readProjectCredentials, } from "@nylorun/admin/project";
|
|
2
3
|
import { CliError } from "../errors.js";
|
|
3
|
-
|
|
4
|
-
/** The Project's credentials, which `nylorun start` writes beside the link. */
|
|
4
|
+
/** The Project's credentials, which `nylorun start` writes beside the link; kept 0600. */
|
|
5
5
|
export async function readCredentials(projectRoot) {
|
|
6
|
-
const path =
|
|
6
|
+
const path = projectCredentialsPath(projectRoot);
|
|
7
|
+
let credentials;
|
|
7
8
|
try {
|
|
8
|
-
|
|
9
|
-
if (typeof value?.applicationKey !== "string" ||
|
|
10
|
-
!/^[0-9a-f]{64}$/.test(value.applicationKey) ||
|
|
11
|
-
typeof value?.principalId !== "string" ||
|
|
12
|
-
value.principalId.length === 0) {
|
|
13
|
-
throw new CliError(`Invalid Project credentials at ${path}. Remove .nylorun/credentials.json and run "npx nylorun start".`, 1);
|
|
14
|
-
}
|
|
15
|
-
const format = value.format === undefined || value.format === 0
|
|
16
|
-
? 0
|
|
17
|
-
: value.format === 1
|
|
18
|
-
? 1
|
|
19
|
-
: undefined;
|
|
20
|
-
if (format === undefined) {
|
|
21
|
-
throw new CliError(`Project credentials at ${path} have an unsupported format. Upgrade the CLI.`, 1);
|
|
22
|
-
}
|
|
23
|
-
await chmod(path, 0o600);
|
|
24
|
-
return {
|
|
25
|
-
format,
|
|
26
|
-
applicationKey: value.applicationKey,
|
|
27
|
-
principalId: value.principalId,
|
|
28
|
-
...(typeof value.managementKey === "string" &&
|
|
29
|
-
/^[0-9a-f]{64}$/.test(value.managementKey) &&
|
|
30
|
-
typeof value.managementPrincipalId === "string"
|
|
31
|
-
? { managementKey: value.managementKey, managementPrincipalId: value.managementPrincipalId }
|
|
32
|
-
: {}),
|
|
33
|
-
};
|
|
9
|
+
credentials = readProjectCredentials(projectRoot);
|
|
34
10
|
}
|
|
35
11
|
catch (error) {
|
|
36
|
-
if (error
|
|
37
|
-
|
|
38
|
-
throw error
|
|
12
|
+
if (!(error instanceof ProjectFileError))
|
|
13
|
+
throw error;
|
|
14
|
+
throw new CliError(error.reason === "newer"
|
|
15
|
+
? `Project credentials at ${path} have an unsupported format. Upgrade the CLI.`
|
|
16
|
+
: `Invalid Project credentials at ${path}. Remove .nylorun/credentials.json and run "npx nylorun start".`, 1);
|
|
39
17
|
}
|
|
18
|
+
if (credentials)
|
|
19
|
+
await chmod(path, 0o600);
|
|
20
|
+
return credentials;
|
|
40
21
|
}
|
package/dist/project/env.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { findProjectRoot } from "@nylorun/admin/project";
|
|
1
2
|
import { readCredentials } from "./credentials.js";
|
|
2
3
|
import { readLink } from "./link.js";
|
|
3
|
-
import { findProjectRoot } from "./root.js";
|
|
4
4
|
/** Two `export` lines for `nylo env` (was `nylorun status --env`, F2-7). */
|
|
5
5
|
export async function printLinkedEnvExports(projectRoot = process.cwd()) {
|
|
6
6
|
const root = findProjectRoot(projectRoot) ?? projectRoot;
|
package/dist/project/link.d.ts
CHANGED
|
@@ -1,17 +1,10 @@
|
|
|
1
|
+
import { type ProjectLink as LinkFile } from "@nylorun/admin/project";
|
|
1
2
|
/**
|
|
2
3
|
* Project-local link to an installation (format 3). `nylorun start` writes it; `nylo` only
|
|
3
|
-
* reads it
|
|
4
|
+
* reads it, with `@nylorun/core/project`'s reader (through `@nylorun/admin/project`).
|
|
5
|
+
* `tenantId` is information: the installation serves one Tenant, so nothing selects it.
|
|
4
6
|
*/
|
|
5
|
-
export
|
|
7
|
+
export type ProjectLink = LinkFile & {
|
|
6
8
|
format: 3;
|
|
7
|
-
|
|
8
|
-
tenant?: string;
|
|
9
|
-
hostUrl: string;
|
|
10
|
-
hostId: string;
|
|
11
|
-
tenantId?: string;
|
|
12
|
-
}
|
|
13
|
-
export declare function nylorunDir(projectRoot: string): string;
|
|
14
|
-
export declare function linkPath(projectRoot: string): string;
|
|
15
|
-
/** `.nylorun/credentials.json`. */
|
|
16
|
-
export declare function credentialsPath(projectRoot: string): string;
|
|
9
|
+
};
|
|
17
10
|
export declare function readLink(projectRoot: string): Promise<ProjectLink | undefined>;
|
package/dist/project/link.js
CHANGED
|
@@ -1,52 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { join } from "node:path";
|
|
1
|
+
import { ProjectFileError, projectLinkPath, readProjectLink, } from "@nylorun/admin/project";
|
|
3
2
|
import { CliError } from "../errors.js";
|
|
4
|
-
export function nylorunDir(projectRoot) {
|
|
5
|
-
return join(projectRoot, ".nylorun");
|
|
6
|
-
}
|
|
7
|
-
export function linkPath(projectRoot) {
|
|
8
|
-
return join(nylorunDir(projectRoot), "link.json");
|
|
9
|
-
}
|
|
10
|
-
/** `.nylorun/credentials.json`. */
|
|
11
|
-
export function credentialsPath(projectRoot) {
|
|
12
|
-
return join(nylorunDir(projectRoot), "credentials.json");
|
|
13
|
-
}
|
|
14
3
|
export async function readLink(projectRoot) {
|
|
15
|
-
const path =
|
|
16
|
-
let
|
|
17
|
-
let raw;
|
|
4
|
+
const path = projectLinkPath(projectRoot);
|
|
5
|
+
let link;
|
|
18
6
|
try {
|
|
19
|
-
|
|
7
|
+
link = readProjectLink(projectRoot);
|
|
20
8
|
}
|
|
21
9
|
catch (error) {
|
|
22
|
-
if (error
|
|
23
|
-
|
|
24
|
-
throw error
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
value = JSON.parse(raw);
|
|
28
|
-
}
|
|
29
|
-
catch {
|
|
30
|
-
throw new CliError(`Invalid Project link at ${path}. Remove .nylorun/link.json and run "npx nylorun start".`, 1);
|
|
10
|
+
if (!(error instanceof ProjectFileError))
|
|
11
|
+
throw error;
|
|
12
|
+
throw new CliError(error.reason === "newer"
|
|
13
|
+
? `Project link at ${path} has an unsupported format. Upgrade the CLI.`
|
|
14
|
+
: `Invalid Project link at ${path}. Remove .nylorun/link.json and run "npx nylorun start".`, 1);
|
|
31
15
|
}
|
|
16
|
+
if (link === undefined)
|
|
17
|
+
return undefined;
|
|
32
18
|
// Formats 0 to 2 are from older releases.
|
|
33
|
-
if (
|
|
34
|
-
value.format === 0 ||
|
|
35
|
-
value.format === 1 ||
|
|
36
|
-
value.format === 2)
|
|
19
|
+
if (link.format !== 3)
|
|
37
20
|
throw new CliError(`The Project link at ${path} is from an older nylorun. Run "npx nylorun start" in this project to link it again.`, 1);
|
|
38
|
-
|
|
39
|
-
throw new CliError(`Project link at ${path} has an unsupported format. Upgrade the CLI.`, 1);
|
|
40
|
-
if (typeof value.hostUrl !== "string" ||
|
|
41
|
-
typeof value.hostId !== "string" ||
|
|
42
|
-
(value.tenant !== undefined && typeof value.tenant !== "string") ||
|
|
43
|
-
(value.tenantId !== undefined && typeof value.tenantId !== "string"))
|
|
44
|
-
throw new CliError(`Invalid Project link at ${path}. Remove .nylorun/link.json and run "npx nylorun start".`, 1);
|
|
45
|
-
return {
|
|
46
|
-
format: 3,
|
|
47
|
-
...(value.tenant ? { tenant: value.tenant } : {}),
|
|
48
|
-
hostUrl: value.hostUrl.replace(/\/$/, ""),
|
|
49
|
-
hostId: value.hostId,
|
|
50
|
-
...(value.tenantId ? { tenantId: value.tenantId } : {}),
|
|
51
|
-
};
|
|
21
|
+
return { ...link, format: 3 };
|
|
52
22
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nylorun/cli",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.2-beta",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"description": "Nylorun Runtime client: the linked installation's Tenant, its access and its model provider",
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"prepack": "npm run build"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@nylorun/agents": "0.
|
|
34
|
-
"@nylorun/admin": "0.
|
|
33
|
+
"@nylorun/agents": "0.19.1-beta",
|
|
34
|
+
"@nylorun/admin": "0.14.1-beta",
|
|
35
35
|
"@earendil-works/pi-ai": "0.99.1"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
package/dist/home.d.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Where `nylo` keeps its own files (the installation id): an explicit home,
|
|
3
|
-
* `NYLORUN_HOME`, or `~/.nylorun`, which holds the local Tenants' Host roots
|
|
4
|
-
* (`tenants/<name>/`). `@nylorun/admin` resolves a Tenant's Host root itself.
|
|
5
|
-
*/
|
|
6
|
-
export declare function resolveHome(home?: string, env?: Readonly<Record<string, string | undefined>>): string;
|
package/dist/home.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { homedir } from "node:os";
|
|
2
|
-
import { join, resolve } from "node:path";
|
|
3
|
-
/**
|
|
4
|
-
* Where `nylo` keeps its own files (the installation id): an explicit home,
|
|
5
|
-
* `NYLORUN_HOME`, or `~/.nylorun`, which holds the local Tenants' Host roots
|
|
6
|
-
* (`tenants/<name>/`). `@nylorun/admin` resolves a Tenant's Host root itself.
|
|
7
|
-
*/
|
|
8
|
-
export function resolveHome(home, env = process.env) {
|
|
9
|
-
if (home !== undefined && home.trim() !== "")
|
|
10
|
-
return resolve(home);
|
|
11
|
-
const fromEnv = env.NYLORUN_HOME?.trim();
|
|
12
|
-
if (fromEnv)
|
|
13
|
-
return resolve(fromEnv);
|
|
14
|
-
return resolve(join(homedir(), ".nylorun"));
|
|
15
|
-
}
|
package/dist/project/root.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The nearest `.nylorun` wins so an initialised Project keeps working from a
|
|
3
|
-
* subdirectory; otherwise the nearest package.json defines the Project. The
|
|
4
|
-
* walk stops at the home directory because `~/.nylorun` is the Host root, never
|
|
5
|
-
* a Project root.
|
|
6
|
-
*/
|
|
7
|
-
export declare function findProjectRoot(cwd?: string): string | undefined;
|
|
8
|
-
/** Require a Project root or throw a usage-oriented error. */
|
|
9
|
-
export declare function requireProjectRoot(cwd?: string): string;
|
package/dist/project/root.js
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { existsSync, realpathSync } from "node:fs";
|
|
2
|
-
import { homedir } from "node:os";
|
|
3
|
-
import { dirname, join, parse, resolve } from "node:path";
|
|
4
|
-
/**
|
|
5
|
-
* The nearest `.nylorun` wins so an initialised Project keeps working from a
|
|
6
|
-
* subdirectory; otherwise the nearest package.json defines the Project. The
|
|
7
|
-
* walk stops at the home directory because `~/.nylorun` is the Host root, never
|
|
8
|
-
* a Project root.
|
|
9
|
-
*/
|
|
10
|
-
export function findProjectRoot(cwd = process.cwd()) {
|
|
11
|
-
const stop = (() => {
|
|
12
|
-
try {
|
|
13
|
-
return realpathSync(homedir());
|
|
14
|
-
}
|
|
15
|
-
catch {
|
|
16
|
-
return homedir();
|
|
17
|
-
}
|
|
18
|
-
})();
|
|
19
|
-
let directory = resolve(cwd);
|
|
20
|
-
try {
|
|
21
|
-
directory = realpathSync(directory);
|
|
22
|
-
}
|
|
23
|
-
catch {
|
|
24
|
-
/* unresolvable cwd falls through */
|
|
25
|
-
}
|
|
26
|
-
const root = parse(directory).root;
|
|
27
|
-
let fallback;
|
|
28
|
-
for (;;) {
|
|
29
|
-
// The home directory is never a Project, but a package.json below it is.
|
|
30
|
-
if (directory === stop)
|
|
31
|
-
return fallback;
|
|
32
|
-
if (existsSync(join(directory, ".nylorun")))
|
|
33
|
-
return directory;
|
|
34
|
-
if (!fallback && existsSync(join(directory, "package.json")))
|
|
35
|
-
fallback = directory;
|
|
36
|
-
if (directory === root)
|
|
37
|
-
break;
|
|
38
|
-
const parent = dirname(directory);
|
|
39
|
-
if (parent === directory)
|
|
40
|
-
break;
|
|
41
|
-
directory = parent;
|
|
42
|
-
}
|
|
43
|
-
return fallback;
|
|
44
|
-
}
|
|
45
|
-
/** Require a Project root or throw a usage-oriented error. */
|
|
46
|
-
export function requireProjectRoot(cwd = process.cwd()) {
|
|
47
|
-
const root = findProjectRoot(cwd);
|
|
48
|
-
if (!root) {
|
|
49
|
-
throw new Error("No Project found (looked for package.json or .nylorun/). Run this from a Project directory.");
|
|
50
|
-
}
|
|
51
|
-
return root;
|
|
52
|
-
}
|