naro-cli 0.5.3 → 0.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.
@@ -9,7 +9,7 @@ var __export = (target, all) => {
9
9
  import { existsSync as existsSync6 } from "fs";
10
10
  import { cp, mkdtemp as mkdtemp2, readFile as readFile7, rm as rm2 } from "fs/promises";
11
11
  import { tmpdir as tmpdir2 } from "os";
12
- import { basename, dirname, join as join15 } from "path";
12
+ import { basename, dirname, join as join15, resolve as resolve4 } from "path";
13
13
  import { fileURLToPath } from "url";
14
14
 
15
15
  // ../../packages/build/src/artifact-upload.ts
@@ -173,6 +173,16 @@ import { join as join8 } from "path";
173
173
  var MAX_FILE_BYTES = 25 * 1024 * 1024;
174
174
  var MAX_ARTIFACT_BYTES = 64 * 1024 * 1024;
175
175
 
176
+ // ../../packages/core/src/deployment.ts
177
+ var PHASES = [
178
+ "QUEUED",
179
+ "CLONING",
180
+ "INSTALLING",
181
+ "BUILDING",
182
+ "DEPLOYING"
183
+ ];
184
+ var ACTIVE_STATUSES = new Set(PHASES);
185
+
176
186
  // ../../packages/core/src/errors.ts
177
187
  var DeploymentError = class extends Error {
178
188
  code;
@@ -15178,21 +15188,39 @@ function contentType(path) {
15178
15188
  return "application/javascript";
15179
15189
  case ".json":
15180
15190
  return "application/json";
15191
+ case ".map":
15192
+ return "application/json";
15193
+ case ".webmanifest":
15194
+ return "application/manifest+json";
15195
+ case ".txt":
15196
+ return "text/plain; charset=utf-8";
15197
+ case ".xml":
15198
+ return "application/xml";
15181
15199
  case ".svg":
15182
15200
  return "image/svg+xml";
15183
15201
  case ".wasm":
15184
15202
  return "application/wasm";
15203
+ case ".ico":
15204
+ return "image/x-icon";
15185
15205
  case ".png":
15186
15206
  return "image/png";
15187
15207
  case ".jpg":
15188
15208
  case ".jpeg":
15189
15209
  return "image/jpeg";
15210
+ case ".gif":
15211
+ return "image/gif";
15190
15212
  case ".webp":
15191
15213
  return "image/webp";
15214
+ case ".avif":
15215
+ return "image/avif";
15192
15216
  case ".woff":
15193
15217
  return "font/woff";
15194
15218
  case ".woff2":
15195
15219
  return "font/woff2";
15220
+ case ".ttf":
15221
+ return "font/ttf";
15222
+ case ".otf":
15223
+ return "font/otf";
15196
15224
  default:
15197
15225
  return "application/octet-stream";
15198
15226
  }
@@ -15961,8 +15989,8 @@ var FAIL_HTML = "<html><body><p>Login failed. You can close this tab and return
15961
15989
  async function startCallbackServer() {
15962
15990
  let resolveCode;
15963
15991
  let rejectCode;
15964
- const codePromise = new Promise((resolve4, reject) => {
15965
- resolveCode = resolve4;
15992
+ const codePromise = new Promise((resolve5, reject) => {
15993
+ resolveCode = resolve5;
15966
15994
  rejectCode = reject;
15967
15995
  });
15968
15996
  const server = createServer((req, res) => {
@@ -15989,7 +16017,7 @@ async function startCallbackServer() {
15989
16017
  res.end(DONE_HTML);
15990
16018
  resolveCode(code);
15991
16019
  });
15992
- await new Promise((resolve4) => server.listen(0, "127.0.0.1", resolve4));
16020
+ await new Promise((resolve5) => server.listen(0, "127.0.0.1", resolve5));
15993
16021
  const port = server.address().port;
15994
16022
  return {
15995
16023
  port,
@@ -16421,7 +16449,7 @@ var DeploymentsApi = class {
16421
16449
  async wait(deploymentId, options = {}) {
16422
16450
  const intervalMs = options.intervalMs ?? 2500;
16423
16451
  const timeoutMs = options.timeoutMs ?? 15 * 6e4;
16424
- const sleep = options.sleep ?? ((ms) => new Promise((resolve4) => setTimeout(resolve4, ms)));
16452
+ const sleep = options.sleep ?? ((ms) => new Promise((resolve5) => setTimeout(resolve5, ms)));
16425
16453
  const startedAt = Date.now();
16426
16454
  let lastStatus = null;
16427
16455
  let lastSequence = -1;
@@ -16930,10 +16958,10 @@ var SUPPORTED_REMOTE = [
16930
16958
  /^ssh:\/\/[^\s]+$/,
16931
16959
  /^git@[A-Za-z0-9.-]+:[A-Za-z0-9._/-]+(\.git)?$/
16932
16960
  ];
16933
- var defaultExec = (args, cwd) => new Promise((resolve4, reject) => {
16961
+ var defaultExec = (args, cwd) => new Promise((resolve5, reject) => {
16934
16962
  execFile("git", args, { cwd }, (error51, stdout) => {
16935
16963
  if (error51) reject(error51);
16936
- else resolve4(stdout);
16964
+ else resolve5(stdout);
16937
16965
  });
16938
16966
  });
16939
16967
  async function tryExec(exec, args, cwd) {
@@ -16951,9 +16979,11 @@ async function detectGitInfo(dir, exec = defaultExec) {
16951
16979
  ["rev-parse", "--abbrev-ref", "HEAD"],
16952
16980
  dir
16953
16981
  );
16982
+ const prefix = await tryExec(exec, ["rev-parse", "--show-prefix"], dir);
16954
16983
  return {
16955
16984
  repositoryUrl: remote !== null && SUPPORTED_REMOTE.some((re) => re.test(remote)) ? remote : null,
16956
- branch: branch !== null && branch !== "HEAD" ? branch : null
16985
+ branch: branch !== null && branch !== "HEAD" ? branch : null,
16986
+ prefix: prefix === null ? null : prefix.replace(/\/+$/, "") || null
16957
16987
  };
16958
16988
  }
16959
16989
 
@@ -17081,7 +17111,7 @@ function eventsObserver(cp2, deploymentId, token, fetchImpl = fetch) {
17081
17111
  } catch (error51) {
17082
17112
  lastError = error51;
17083
17113
  await new Promise(
17084
- (resolve4) => setTimeout(resolve4, 500 * (attempt + 1))
17114
+ (resolve5) => setTimeout(resolve5, 500 * (attempt + 1))
17085
17115
  );
17086
17116
  }
17087
17117
  }
@@ -17172,11 +17202,12 @@ function localDependencies(sourceDir) {
17172
17202
  async function deployDirectory(sourceDir, options, log2) {
17173
17203
  const cpUrl = controlPlaneUrl();
17174
17204
  const production = options.production ?? false;
17175
- const framework = detectFramework2(sourceDir);
17205
+ const appRoot = options.rootDirectory ? resolve4(sourceDir, options.rootDirectory) : sourceDir;
17206
+ const framework = detectFramework2(appRoot);
17176
17207
  if (!framework.deployable && !options.force) {
17177
17208
  throw new NaroError(
17178
17209
  "FRAMEWORK_UNSUPPORTED",
17179
- framework.framework === "unknown" ? "No supported framework detected here. Naro deploys Next.js, Vite, Create React App, and static sites \u2014 run this inside one of those projects." : `${framework.name} projects are not deployable on Naro yet.`,
17210
+ framework.framework === "unknown" ? `No supported framework detected in ${appRoot}. Naro deploys Next.js, Vite, Create React App, and static sites \u2014 run this inside one of those projects, or point at it with --root <dir>.` : `${framework.name} projects are not deployable on Naro yet.`,
17180
17211
  { details: { framework: framework.framework } }
17181
17212
  );
17182
17213
  }
@@ -17193,9 +17224,10 @@ async function deployDirectory(sourceDir, options, log2) {
17193
17224
  getAccessToken: () => auth.getAccessToken(),
17194
17225
  ...options.fetch ? { fetch: options.fetch } : {}
17195
17226
  });
17196
- const name = slugify2(options.name ?? await projectName(sourceDir));
17197
- const git = await detectGitInfo(sourceDir);
17227
+ const name = slugify2(options.name ?? await projectName(appRoot));
17228
+ const git = await (options.gitInfo ?? detectGitInfo)(sourceDir);
17198
17229
  const branch = options.branch ?? git.branch;
17230
+ const repositoryRoot = [git.prefix, options.rootDirectory].filter(Boolean).join("/") || null;
17199
17231
  if (options.projectId) log2(`\u25B8 linked project ${options.projectId}`);
17200
17232
  else if (git.repositoryUrl) log2(`\u25B8 linking ${git.repositoryUrl}`);
17201
17233
  if (options.env && Object.keys(options.env).length > 0)
@@ -17233,9 +17265,7 @@ async function deployDirectory(sourceDir, options, log2) {
17233
17265
  production,
17234
17266
  ...git.repositoryUrl != null && { repositoryUrl: git.repositoryUrl },
17235
17267
  ...branch != null && { branch },
17236
- ...options.rootDirectory != null && {
17237
- rootDirectory: options.rootDirectory
17238
- },
17268
+ ...repositoryRoot != null && { rootDirectory: repositoryRoot },
17239
17269
  ...Object.keys(envToSend).length > 0 && { env: envToSend }
17240
17270
  });
17241
17271
  if (ctx.envSkipped?.length)
@@ -17255,7 +17285,7 @@ async function deployDirectory(sourceDir, options, log2) {
17255
17285
  projectId: ctx.projectId,
17256
17286
  repositoryUrl: sourceDir,
17257
17287
  branch: ctx.branch,
17258
- rootDirectory: options.rootDirectory ?? ctx.rootDirectory,
17288
+ rootDirectory: options.rootDirectory ?? null,
17259
17289
  env: { ...ctx.env, ...envToSend }
17260
17290
  },
17261
17291
  observer
package/dist/deploy.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { type CliGitConnection } from "@next-deploy/sdk";
2
2
  import type { BuildObserver, DeploymentArtifact, DeploymentStatus } from "./artifact-types";
3
+ import { type GitInfo } from "./git-info";
3
4
  /** The slice of LocalBuildExecutor the deploy flow needs — injectable in tests. */
4
5
  export interface DeployBuildExecutor {
5
6
  build(input: {
@@ -38,6 +39,8 @@ export interface DeployOptions {
38
39
  fetch?: typeof fetch;
39
40
  /** Test seam: replaces the local OpenNext build. */
40
41
  executor?: DeployBuildExecutor;
42
+ /** Test seam: replaces the `git` calls that read the repository. */
43
+ gitInfo?: (dir: string) => Promise<GitInfo>;
41
44
  /**
42
45
  * 소스가 참조하지만 프로젝트에 없는 env 키를 받아, 등록할 값을 돌려준다.
43
46
  * 대화형 CLI만 전달한다 — MCP·CI는 생략하고 안내만 받는다.
package/dist/deploy.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  parseDotenv,
6
6
  readProjectEnv,
7
7
  slugify
8
- } from "./chunk-ZHVBIQBE.js";
8
+ } from "./chunk-TYBC3YSK.js";
9
9
  export {
10
10
  deployDirectory,
11
11
  eventsObserver,
@@ -1,6 +1,16 @@
1
1
  export interface GitInfo {
2
2
  repositoryUrl: string | null;
3
3
  branch: string | null;
4
+ /**
5
+ * Path from the repository root to this directory ("apps/web"), or null at
6
+ * the root / outside a repository.
7
+ *
8
+ * A monorepo app deployed from its own directory builds locally from that
9
+ * directory, so nothing here needs it. A git-triggered build clones the
10
+ * whole repository and has to be told where the app lives — this is that
11
+ * answer, recorded without anyone having to know to pass it.
12
+ */
13
+ prefix: string | null;
4
14
  }
5
15
  export type GitExec = (args: string[], cwd: string) => Promise<string>;
6
16
  /** Reads local git metadata for the deploy: origin remote URL + current branch. */
package/dist/index.js CHANGED
@@ -26,7 +26,7 @@ import {
26
26
  slugify,
27
27
  toNaroError,
28
28
  writeProjectLink
29
- } from "./chunk-ZHVBIQBE.js";
29
+ } from "./chunk-TYBC3YSK.js";
30
30
 
31
31
  // src/args.ts
32
32
  var BOOLEAN_FLAGS = {
@@ -1364,6 +1364,7 @@ Usage:
1364
1364
  naro project inspect Show the linked project
1365
1365
 
1366
1366
  naro deploy [--prod] Build locally and deploy (preview by default)
1367
+ [--root <dir>] [--name <name>] --root points at the app in a monorepo
1367
1368
  naro deployments List deployments of the linked project
1368
1369
  naro inspect <deployment-id> Show one deployment + build logs
1369
1370
 
@@ -1388,6 +1389,8 @@ Global options:
1388
1389
  --yes, -y Never prompt; assume yes (CI / agents)
1389
1390
  --token <t> Access token (or set NARO_TOKEN)
1390
1391
  --project <id> Target project (overrides .naro/project.json)
1392
+ --root <dir> App directory inside the repo (monorepos), e.g. apps/web
1393
+ --name <name> Project name for a first deploy (defaults to package.json)
1391
1394
  --team <slug> Team scope for project listing/linking
1392
1395
  --cwd <dir> Run as if started in <dir>
1393
1396
  --prod Deploy/target production
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "naro-cli",
3
- "version": "0.5.3",
3
+ "version": "0.6.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "naro": "./dist/index.js"
@@ -28,10 +28,10 @@
28
28
  "tsx": "4.23.12",
29
29
  "typescript": "7.0.2",
30
30
  "vitest": "3.2.7",
31
- "@next-deploy/core": "0.1.0",
32
31
  "@next-deploy/build": "0.1.0",
33
32
  "@next-deploy/config": "0.1.0",
34
- "@next-deploy/sdk": "0.1.0"
33
+ "@next-deploy/sdk": "0.1.0",
34
+ "@next-deploy/core": "0.1.0"
35
35
  },
36
36
  "scripts": {
37
37
  "build": "tsup && pnpm build:types",