naro-cli 0.1.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/README.md +8 -0
- package/dist/artifact-types.d.ts +38 -0
- package/dist/callback-server.d.ts +10 -0
- package/dist/chunk-63SYN66G.js +15864 -0
- package/dist/deploy.d.ts +32 -0
- package/dist/deploy.js +19 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +158 -0
- package/dist/login.d.ts +10 -0
- package/dist/session.d.ts +16 -0
- package/dist/supabase-auth.d.ts +11 -0
- package/dist/upload.d.ts +11 -0
- package/package.json +42 -0
package/dist/deploy.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { BuildObserver } from "./artifact-types";
|
|
2
|
+
export interface CliDeploymentContext {
|
|
3
|
+
deploymentId: string;
|
|
4
|
+
projectId: string;
|
|
5
|
+
callbackToken: string;
|
|
6
|
+
branch: string;
|
|
7
|
+
rootDirectory: string | null;
|
|
8
|
+
env: Record<string, string>;
|
|
9
|
+
controlPlaneUrl: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function startCliDeployment(accessToken: string, opts: {
|
|
12
|
+
name: string;
|
|
13
|
+
production: boolean;
|
|
14
|
+
controlPlaneUrl: string;
|
|
15
|
+
fetch?: typeof fetch;
|
|
16
|
+
}): Promise<CliDeploymentContext>;
|
|
17
|
+
export declare function controlPlaneUrl(env?: NodeJS.ProcessEnv): string;
|
|
18
|
+
export declare function eventsObserver(cp: string, deploymentId: string, token: string, fetchImpl?: typeof fetch): BuildObserver;
|
|
19
|
+
export declare function parseDotenv(text: string): Record<string, string>;
|
|
20
|
+
export declare function readProjectEnv(dir: string): Record<string, string>;
|
|
21
|
+
export declare function slugify(value: string): string;
|
|
22
|
+
export interface DeployOptions {
|
|
23
|
+
name?: string | undefined;
|
|
24
|
+
rootDirectory?: string | null;
|
|
25
|
+
production?: boolean;
|
|
26
|
+
env?: Record<string, string> | undefined;
|
|
27
|
+
}
|
|
28
|
+
export interface DeployResult {
|
|
29
|
+
workerName: string;
|
|
30
|
+
url: string;
|
|
31
|
+
}
|
|
32
|
+
export declare function deployDirectory(sourceDir: string, options: DeployOptions, log: (message: string) => void): Promise<DeployResult>;
|
package/dist/deploy.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
controlPlaneUrl,
|
|
4
|
+
deployDirectory,
|
|
5
|
+
eventsObserver,
|
|
6
|
+
parseDotenv,
|
|
7
|
+
readProjectEnv,
|
|
8
|
+
slugify,
|
|
9
|
+
startCliDeployment
|
|
10
|
+
} from "./chunk-63SYN66G.js";
|
|
11
|
+
export {
|
|
12
|
+
controlPlaneUrl,
|
|
13
|
+
deployDirectory,
|
|
14
|
+
eventsObserver,
|
|
15
|
+
parseDotenv,
|
|
16
|
+
readProjectEnv,
|
|
17
|
+
slugify,
|
|
18
|
+
startCliDeployment
|
|
19
|
+
};
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
clearSession,
|
|
4
|
+
createAuthClient,
|
|
5
|
+
deployDirectory,
|
|
6
|
+
isExpired,
|
|
7
|
+
loadStoredSession,
|
|
8
|
+
login,
|
|
9
|
+
readProjectEnv,
|
|
10
|
+
refreshStoredSession,
|
|
11
|
+
saveSession
|
|
12
|
+
} from "./chunk-63SYN66G.js";
|
|
13
|
+
|
|
14
|
+
// src/login.ts
|
|
15
|
+
import { spawn } from "child_process";
|
|
16
|
+
import { homedir } from "os";
|
|
17
|
+
var stdio = {
|
|
18
|
+
out: (m) => process.stdout.write(`${m}
|
|
19
|
+
`),
|
|
20
|
+
err: (m) => process.stderr.write(`${m}
|
|
21
|
+
`)
|
|
22
|
+
};
|
|
23
|
+
function openBrowser(url) {
|
|
24
|
+
const platform = process.platform;
|
|
25
|
+
const command = platform === "darwin" ? "open" : platform === "win32" ? "cmd" : "xdg-open";
|
|
26
|
+
const args = platform === "win32" ? ["/c", "start", "", url] : [url];
|
|
27
|
+
spawn(command, args, { stdio: "ignore", detached: true }).unref();
|
|
28
|
+
}
|
|
29
|
+
async function runLogin(io = stdio) {
|
|
30
|
+
io.out("Opening your browser to sign in with GitHub...");
|
|
31
|
+
const session = await login({
|
|
32
|
+
openBrowser: (url) => {
|
|
33
|
+
io.out(`If your browser did not open, visit:
|
|
34
|
+
${url}`);
|
|
35
|
+
openBrowser(url);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
saveSession(session);
|
|
39
|
+
io.out(`\u2705 Logged in as ${session.user.email ?? session.user.id}`);
|
|
40
|
+
}
|
|
41
|
+
async function runWhoami(io = stdio, home = homedir(), refresh = refreshStoredSession) {
|
|
42
|
+
let session = loadStoredSession(home);
|
|
43
|
+
if (!session) {
|
|
44
|
+
io.err("Not logged in. Run `naro login`.");
|
|
45
|
+
process.exitCode = 1;
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (isExpired(session)) {
|
|
49
|
+
try {
|
|
50
|
+
session = await refresh(session.refresh_token);
|
|
51
|
+
saveSession(session, home);
|
|
52
|
+
} catch {
|
|
53
|
+
io.err("Session expired. Run `naro login`.");
|
|
54
|
+
process.exitCode = 1;
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const handle = session.user.github ? ` (${session.user.github})` : "";
|
|
59
|
+
io.out(`Logged in as ${session.user.email ?? session.user.id}${handle}`);
|
|
60
|
+
}
|
|
61
|
+
async function defaultSignOut(session) {
|
|
62
|
+
const client = createAuthClient();
|
|
63
|
+
await client.auth.setSession({
|
|
64
|
+
access_token: session.access_token,
|
|
65
|
+
refresh_token: session.refresh_token
|
|
66
|
+
});
|
|
67
|
+
await client.auth.signOut();
|
|
68
|
+
}
|
|
69
|
+
async function runLogout(io = stdio, home = homedir(), signOut = defaultSignOut) {
|
|
70
|
+
const session = loadStoredSession(home);
|
|
71
|
+
if (session) {
|
|
72
|
+
try {
|
|
73
|
+
await signOut(session);
|
|
74
|
+
} catch {
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
clearSession(home);
|
|
78
|
+
io.out("Logged out.");
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// src/index.ts
|
|
82
|
+
function parseFlags(argv) {
|
|
83
|
+
const flags = { production: false };
|
|
84
|
+
for (let i = 0; i < argv.length; i++) {
|
|
85
|
+
const arg = argv[i];
|
|
86
|
+
if (arg === "--prod" || arg === "--production") flags.production = true;
|
|
87
|
+
else if (arg === "--name") flags.name = argv[++i];
|
|
88
|
+
else if (arg === "--root") flags.root = argv[++i];
|
|
89
|
+
}
|
|
90
|
+
return flags;
|
|
91
|
+
}
|
|
92
|
+
var HELP = `naro \u2014 deploy the current app to naro
|
|
93
|
+
|
|
94
|
+
Usage:
|
|
95
|
+
naro login
|
|
96
|
+
naro whoami
|
|
97
|
+
naro logout
|
|
98
|
+
naro deploy [--name <name>] [--root <dir>] [--prod]
|
|
99
|
+
|
|
100
|
+
Options:
|
|
101
|
+
--name Override the deployment name (defaults to package.json name)
|
|
102
|
+
--root Sub-directory that contains the Next.js app (where package.json is)
|
|
103
|
+
--prod Publish to production ({name}.naro.sh) instead of preview
|
|
104
|
+
|
|
105
|
+
Credentials:
|
|
106
|
+
Run \`naro login\` to authenticate via GitHub.
|
|
107
|
+
Set NARO_CONTROL_PLANE_URL to use a custom control plane (defaults to https://naro.sh).
|
|
108
|
+
`;
|
|
109
|
+
async function main() {
|
|
110
|
+
const [command, ...rest] = process.argv.slice(2);
|
|
111
|
+
if (!command || command === "help" || command === "--help") {
|
|
112
|
+
process.stdout.write(HELP);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (command === "login") return runLogin();
|
|
116
|
+
if (command === "whoami") return runWhoami();
|
|
117
|
+
if (command === "logout") return runLogout();
|
|
118
|
+
if (command !== "deploy") {
|
|
119
|
+
process.stderr.write(`Unknown command: ${command}
|
|
120
|
+
|
|
121
|
+
${HELP}`);
|
|
122
|
+
process.exitCode = 1;
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const flags = parseFlags(rest);
|
|
126
|
+
const cwd = process.cwd();
|
|
127
|
+
const env = readProjectEnv(cwd);
|
|
128
|
+
process.stdout.write(`
|
|
129
|
+
\u{1F680} Deploying ${cwd}
|
|
130
|
+
|
|
131
|
+
`);
|
|
132
|
+
const result = await deployDirectory(
|
|
133
|
+
cwd,
|
|
134
|
+
{
|
|
135
|
+
name: flags.name,
|
|
136
|
+
rootDirectory: flags.root ?? null,
|
|
137
|
+
production: flags.production,
|
|
138
|
+
env
|
|
139
|
+
},
|
|
140
|
+
(message) => process.stdout.write(`${message}
|
|
141
|
+
`)
|
|
142
|
+
);
|
|
143
|
+
process.stdout.write(`
|
|
144
|
+
\u2705 Live at ${result.url}
|
|
145
|
+
|
|
146
|
+
`);
|
|
147
|
+
}
|
|
148
|
+
void main().catch((error) => {
|
|
149
|
+
process.stderr.write(
|
|
150
|
+
`
|
|
151
|
+
\u2717 ${error instanceof Error ? error.message : String(error)}
|
|
152
|
+
`
|
|
153
|
+
);
|
|
154
|
+
process.exitCode = 1;
|
|
155
|
+
});
|
|
156
|
+
export {
|
|
157
|
+
parseFlags
|
|
158
|
+
};
|
package/dist/login.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type StoredSession } from "./session";
|
|
2
|
+
export interface CliIo {
|
|
3
|
+
out(msg: string): void;
|
|
4
|
+
err(msg: string): void;
|
|
5
|
+
}
|
|
6
|
+
export declare const stdio: CliIo;
|
|
7
|
+
export declare function openBrowser(url: string): void;
|
|
8
|
+
export declare function runLogin(io?: CliIo): Promise<void>;
|
|
9
|
+
export declare function runWhoami(io?: CliIo, home?: string, refresh?: (refreshToken: string) => Promise<StoredSession>): Promise<void>;
|
|
10
|
+
export declare function runLogout(io?: CliIo, home?: string, signOut?: (session: StoredSession) => Promise<void>): Promise<void>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface StoredSession {
|
|
2
|
+
access_token: string;
|
|
3
|
+
refresh_token: string;
|
|
4
|
+
expires_at: number;
|
|
5
|
+
user: {
|
|
6
|
+
id: string;
|
|
7
|
+
email: string | null;
|
|
8
|
+
github: string | null;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export declare function credentialsDir(home?: string): string;
|
|
12
|
+
export declare function credentialsFile(home?: string): string;
|
|
13
|
+
export declare function saveSession(session: StoredSession, home?: string): void;
|
|
14
|
+
export declare function loadStoredSession(home?: string): StoredSession | null;
|
|
15
|
+
export declare function clearSession(home?: string): void;
|
|
16
|
+
export declare function isExpired(session: StoredSession, skewSeconds?: number): boolean;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type Session, type SupabaseClient } from "@supabase/supabase-js";
|
|
2
|
+
import type { StoredSession } from "./session";
|
|
3
|
+
export declare function createAuthClient(env?: NodeJS.ProcessEnv): SupabaseClient;
|
|
4
|
+
export declare function toStoredSession(session: Session): StoredSession;
|
|
5
|
+
export declare function refreshStoredSession(refreshToken: string, client?: SupabaseClient): Promise<StoredSession>;
|
|
6
|
+
export interface LoginDeps {
|
|
7
|
+
openBrowser: (url: string) => void;
|
|
8
|
+
client?: SupabaseClient;
|
|
9
|
+
timeoutMs?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function login(deps: LoginDeps): Promise<StoredSession>;
|
package/dist/upload.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { DeploymentArtifact } from "./artifact-types";
|
|
2
|
+
export interface UploadOptions {
|
|
3
|
+
controlPlaneUrl: string;
|
|
4
|
+
deploymentId: string;
|
|
5
|
+
callbackToken: string;
|
|
6
|
+
fetch?: typeof fetch;
|
|
7
|
+
}
|
|
8
|
+
export declare function uploadArtifact(artifact: DeploymentArtifact, opts: UploadOptions): Promise<{
|
|
9
|
+
artifactKey: string;
|
|
10
|
+
previewUrl: string | null;
|
|
11
|
+
}>;
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "naro-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"bin": {
|
|
6
|
+
"naro": "./dist/index.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"README.md"
|
|
11
|
+
],
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"access": "public"
|
|
14
|
+
},
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/deploy.d.ts",
|
|
18
|
+
"default": "./dist/deploy.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@opennextjs/cloudflare": "1.20.2",
|
|
23
|
+
"@supabase/supabase-js": "2.112.3",
|
|
24
|
+
"wrangler": "4.124.0"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"tsup": "8.5.0",
|
|
28
|
+
"tsx": "4.23.12",
|
|
29
|
+
"typescript": "7.0.2",
|
|
30
|
+
"vitest": "3.2.7",
|
|
31
|
+
"@next-deploy/build": "0.1.0",
|
|
32
|
+
"@next-deploy/config": "0.1.0",
|
|
33
|
+
"@next-deploy/core": "0.1.0"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "tsup && pnpm build:types",
|
|
37
|
+
"build:types": "tsc --project tsconfig.build.json",
|
|
38
|
+
"test": "vitest run",
|
|
39
|
+
"typecheck": "tsc --noEmit",
|
|
40
|
+
"lint": "tsc --noEmit"
|
|
41
|
+
}
|
|
42
|
+
}
|