naro-cli 0.13.0 → 0.15.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 +53 -2
- package/dist/{chunk-O4NJRDJE.js → chunk-6WJ3QQ5Y.js} +98 -26
- package/dist/deploy.js +1 -1
- package/dist/index.js +531 -333
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -69,9 +69,13 @@ naro logs <deployment-id> Build logs of a deployment
|
|
|
69
69
|
naro logs --type build --follow Stream build logs until READY/FAILED
|
|
70
70
|
naro logs --env preview Preview-surface runtime logs
|
|
71
71
|
|
|
72
|
-
naro
|
|
72
|
+
naro analytics Web Analytics: visitors, page views, top pages, referrers, countries, devices, browsers, operating systems (--range 7d)
|
|
73
|
+
naro analytics --country KR --os ios Narrow it: --path, --referrer, --country, --device, --browser, --os (one value each, all must match)
|
|
74
|
+
|
|
75
|
+
naro insights Speed Insights: Web Vitals p75, and the page load's p75 and the mean of each step (--metric lcp, --range 7d)
|
|
73
76
|
naro insights --route '/posts/[id]' The paths under one route
|
|
74
77
|
naro insights --env preview The same for the preview worker
|
|
78
|
+
naro insights --country KR --device mobile Narrow it: --path, --country, --device, --browser, --os (no --referrer: Speed Insights has none)
|
|
75
79
|
naro insights enable | disable Turn measuring on or off
|
|
76
80
|
|
|
77
81
|
naro protection Preview protection: on or off, and whether a bypass secret is set
|
|
@@ -169,7 +173,7 @@ naro policy set posts --from-file policy.json
|
|
|
169
173
|
Shorthand: writes the policies naro_select … naro_delete
|
|
170
174
|
naro policy remove todos Drop every policy on the table: back to deny (asks first)
|
|
171
175
|
|
|
172
|
-
naro storage Naro Storage: on or off, limits, usage, buckets
|
|
176
|
+
naro storage Naro Storage: on or off, limits, usage, today's operations, buckets
|
|
173
177
|
naro storage enable Turn it on: the project's R2 bucket, bound to the backend
|
|
174
178
|
naro storage bucket create avatars --public --file-size-limit 5MiB --allowed-mime-types image/png,image/jpeg
|
|
175
179
|
naro storage bucket update avatars --private | --file-size-limit none | --allowed-mime-types any
|
|
@@ -789,6 +793,53 @@ An `--update-check` you give replaces the default: without
|
|
|
789
793
|
|
|
790
794
|
## Release notes
|
|
791
795
|
|
|
796
|
+
### 0.15.0
|
|
797
|
+
|
|
798
|
+
- `naro storage` shows the Storage meter's day between `Used:` and `Buckets:`:
|
|
799
|
+
`Today (UTC):` has the write operations (R2 Class A) against the daily limit
|
|
800
|
+
and the reads, `Measured:` the bucket size R2 reported and when R2 measured
|
|
801
|
+
it (R2 reports the size 30–45 minutes late, and the meter reads it every 15
|
|
802
|
+
minutes). A `✗` line
|
|
803
|
+
says uploads are stopped, over the storage limit until objects are deleted
|
|
804
|
+
or over the day's write operations until 00:00 UTC (downloads still work);
|
|
805
|
+
a `⚠` line warns from 80% of the storage limit or of the day's write
|
|
806
|
+
operations. Before the meter has run for the UTC day nothing is added, and
|
|
807
|
+
`--json` prints `storage.today` and `storage.limits.dailyOps` as the
|
|
808
|
+
control plane answered.
|
|
809
|
+
|
|
810
|
+
### 0.14.0
|
|
811
|
+
|
|
812
|
+
- `naro analytics` shows the project's Web Analytics from the terminal: the
|
|
813
|
+
range's visitors and page views (`--range 24h|7d|30d`, 7d by default), then
|
|
814
|
+
the top pages, referrers, countries, devices, browsers and operating systems
|
|
815
|
+
by page views, and `--json` prints the whole report, trend included. The
|
|
816
|
+
same six filters as on the dashboard narrow it, one value each, all of them
|
|
817
|
+
at once: `naro analytics --country KR --os ios`. The first line names the
|
|
818
|
+
filters that applied; filters that leave no visit print one line under it,
|
|
819
|
+
`No visits match these filters. Drop a filter to see more.`, instead of six
|
|
820
|
+
empty tables. The CLI does not check the values; the server answers
|
|
821
|
+
`400 VALIDATION_FAILED` with the rule the value broke (`--country` is an
|
|
822
|
+
uppercase two-letter code like `KR`, `--referrer` a lowercase host like
|
|
823
|
+
`t.co`; `kr` and `T.co` are refused). It reads the
|
|
824
|
+
production worker only, so `--env` is refused with `VALIDATION_FAILED` and
|
|
825
|
+
nothing is sent. An API token (`--token`, `NARO_TOKEN`) can read it.
|
|
826
|
+
- `naro insights` takes the same filters: `--path`, `--country`, `--device`,
|
|
827
|
+
`--browser` and `--os` narrow it to one value each (`--referrer` is refused
|
|
828
|
+
with `VALIDATION_FAILED` and nothing is sent: a vitals row has no referrer).
|
|
829
|
+
The first line names the filters that applied
|
|
830
|
+
(`· filtered by country=KR, os=ios`); filters that leave no measurement print
|
|
831
|
+
`No measurements match these filters. Drop a filter to see more.` instead of
|
|
832
|
+
waiting advice.
|
|
833
|
+
The filters narrow a report only: `naro insights enable | disable` refuses
|
|
834
|
+
them (`Filters only narrow a report; drop --country.`) and sends nothing, and
|
|
835
|
+
an empty value (`--referrer=`) is no filter.
|
|
836
|
+
- `naro insights` prints a `Page load p75 … · mean per step: …` line under the
|
|
837
|
+
metrics table: the p75 of how long visits took to load the page, to the end
|
|
838
|
+
of the load event, then the mean of each step (wait, DNS, connect, server,
|
|
839
|
+
download, processing, onload), so the steps need not add up to the p75. It is
|
|
840
|
+
left out until a visit has sent a page load. The dashboard's Speed Insights
|
|
841
|
+
tab has the same Page load card.
|
|
842
|
+
|
|
792
843
|
### 0.13.0
|
|
793
844
|
|
|
794
845
|
- `naro insights` shows the project's Speed Insights from the terminal: each
|
|
@@ -294,9 +294,6 @@ function pathnameOf(url2) {
|
|
|
294
294
|
}
|
|
295
295
|
}
|
|
296
296
|
|
|
297
|
-
// ../../packages/core/src/internal-auth.ts
|
|
298
|
-
import { Buffer as Buffer2 } from "buffer";
|
|
299
|
-
|
|
300
297
|
// ../../packages/core/src/migration-names.ts
|
|
301
298
|
function normalizeMigrationName(name) {
|
|
302
299
|
return name.trim().toLowerCase().replace(/\.sql$/, "").replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
@@ -15253,6 +15250,20 @@ function classifyNextVersion(raw, now) {
|
|
|
15253
15250
|
// ../../packages/build/src/package-manager.ts
|
|
15254
15251
|
import { access, readFile as readFile2 } from "fs/promises";
|
|
15255
15252
|
import { join as join2 } from "path";
|
|
15253
|
+
function cacheEnv(dir) {
|
|
15254
|
+
return {
|
|
15255
|
+
npm_config_store_dir: dir,
|
|
15256
|
+
npm_config_cache: dir,
|
|
15257
|
+
YARN_CACHE_FOLDER: dir
|
|
15258
|
+
};
|
|
15259
|
+
}
|
|
15260
|
+
function withSharedCache(spec, dir) {
|
|
15261
|
+
return {
|
|
15262
|
+
...spec,
|
|
15263
|
+
addArgs: (specs) => [...spec.addArgs(specs), ...spec.cacheArgs(dir)],
|
|
15264
|
+
addEnv: { ...spec.addEnv, ...cacheEnv(dir) }
|
|
15265
|
+
};
|
|
15266
|
+
}
|
|
15256
15267
|
async function exists(path) {
|
|
15257
15268
|
try {
|
|
15258
15269
|
await access(path);
|
|
@@ -15706,7 +15717,7 @@ export default defineCloudflareConfig({});
|
|
|
15706
15717
|
|
|
15707
15718
|
// ../../packages/build/src/vinext.ts
|
|
15708
15719
|
var VINEXT_TOOLCHAIN = [
|
|
15709
|
-
"vinext@1.
|
|
15720
|
+
"vinext@1.1.0",
|
|
15710
15721
|
"@cloudflare/vite-plugin@1.54.7",
|
|
15711
15722
|
"@vitejs/plugin-react@6.1.1",
|
|
15712
15723
|
"@vitejs/plugin-rsc@0.5.34",
|
|
@@ -15722,7 +15733,7 @@ var VITE_CONFIG_NAMES = [
|
|
|
15722
15733
|
"vite.config.mts",
|
|
15723
15734
|
"vite.config.cts"
|
|
15724
15735
|
];
|
|
15725
|
-
var GENERATED_VITE_CONFIG = "vite.config.
|
|
15736
|
+
var GENERATED_VITE_CONFIG = "vite.config.js";
|
|
15726
15737
|
var OUTPUT_DIR = "dist";
|
|
15727
15738
|
var SERVER_DIR = "server";
|
|
15728
15739
|
var CLIENT_DIR = "client";
|
|
@@ -15787,6 +15798,8 @@ async function createVinextBuildConfig(appRoot, deploymentId, writer = async (pa
|
|
|
15787
15798
|
}
|
|
15788
15799
|
var AUTO_FIXED_ISSUES = [/Missing "type": "module"/i];
|
|
15789
15800
|
var ISSUE_LINE = /^\s*✗\s+(.+)$/;
|
|
15801
|
+
var PARTIAL_LINE = /^\s*~\s+(.+)$/;
|
|
15802
|
+
var BLOCKING_PARTIALS = [/^webpack\b/i];
|
|
15790
15803
|
var ANSI_ESCAPE = /\u001B\[[0-9;]*m/g;
|
|
15791
15804
|
var SUMMARY_LINE = /Overall:\s*(\d+)%\s*compatible\s*\(\s*(\d+)\s+supported,\s*(\d+)\s+partial,\s*(\d+)\s+issues?\s*\)/i;
|
|
15792
15805
|
function parseVinextCheckReport(output) {
|
|
@@ -15798,12 +15811,18 @@ function parseVinextCheckReport(output) {
|
|
|
15798
15811
|
plain.split("\n").map((line) => ISSUE_LINE.exec(line)?.[1]?.trim()).filter((line) => Boolean(line))
|
|
15799
15812
|
)
|
|
15800
15813
|
];
|
|
15814
|
+
const partialLines = [
|
|
15815
|
+
...new Set(
|
|
15816
|
+
plain.split("\n").map((line) => PARTIAL_LINE.exec(line)?.[1]?.trim()).filter((line) => Boolean(line))
|
|
15817
|
+
)
|
|
15818
|
+
];
|
|
15801
15819
|
return {
|
|
15802
15820
|
percent: Number(match[1]),
|
|
15803
15821
|
supported: Number(match[2]),
|
|
15804
15822
|
partial: Number(match[3]),
|
|
15805
15823
|
issues: Number(match[4]),
|
|
15806
|
-
issueLines
|
|
15824
|
+
issueLines,
|
|
15825
|
+
partialLines
|
|
15807
15826
|
};
|
|
15808
15827
|
}
|
|
15809
15828
|
function vinextRouteFromCheck(report) {
|
|
@@ -15815,7 +15834,10 @@ function vinextRouteFromCheck(report) {
|
|
|
15815
15834
|
const autoFixed = report.issueLines.filter(
|
|
15816
15835
|
(line) => AUTO_FIXED_ISSUES.some((pattern) => pattern.test(line))
|
|
15817
15836
|
);
|
|
15818
|
-
const
|
|
15837
|
+
const blockingPartials = report.partialLines.filter(
|
|
15838
|
+
(line) => BLOCKING_PARTIALS.some((pattern) => pattern.test(line))
|
|
15839
|
+
);
|
|
15840
|
+
const blocking = Math.max(0, report.issues - autoFixed.length) + blockingPartials.length;
|
|
15819
15841
|
if (blocking > 0)
|
|
15820
15842
|
return {
|
|
15821
15843
|
eligible: false,
|
|
@@ -17836,6 +17858,7 @@ function createVinextCloudflareStrategy(options) {
|
|
|
17836
17858
|
// Not production: npm and classic Yarn read that as omit=dev and
|
|
17837
17859
|
// would prune the project's devDependencies while adding ours.
|
|
17838
17860
|
env: {
|
|
17861
|
+
...context.packageManager.addEnv,
|
|
17839
17862
|
NODE_ENV: "development",
|
|
17840
17863
|
NPM_CONFIG_USERCONFIG: context.packageManagerConfigPath
|
|
17841
17864
|
},
|
|
@@ -18217,11 +18240,7 @@ var LocalBuildExecutor = class {
|
|
|
18217
18240
|
env: {
|
|
18218
18241
|
NODE_ENV: "development",
|
|
18219
18242
|
NPM_CONFIG_USERCONFIG: packageManagerConfigPath,
|
|
18220
|
-
...cachePorts ? {
|
|
18221
|
-
npm_config_store_dir: pmCacheDir,
|
|
18222
|
-
npm_config_cache: pmCacheDir,
|
|
18223
|
-
YARN_CACHE_FOLDER: pmCacheDir
|
|
18224
|
-
} : {}
|
|
18243
|
+
...cachePorts ? cacheEnv(pmCacheDir) : {}
|
|
18225
18244
|
},
|
|
18226
18245
|
timeoutMs: 10 * 6e4,
|
|
18227
18246
|
stage: "INSTALLING",
|
|
@@ -18305,7 +18324,9 @@ var LocalBuildExecutor = class {
|
|
|
18305
18324
|
identity,
|
|
18306
18325
|
branch: input.branch,
|
|
18307
18326
|
env: input.env ?? {},
|
|
18308
|
-
|
|
18327
|
+
// The toolchain add has to use the store the install linked
|
|
18328
|
+
// node_modules from (withSharedCache).
|
|
18329
|
+
packageManager: cachePorts ? withSharedCache(packageManager, pmCacheDir) : packageManager,
|
|
18309
18330
|
packageManagerConfigPath,
|
|
18310
18331
|
buildScript: resolved.buildScript,
|
|
18311
18332
|
nextVersion: nextVersion ? `${String(nextVersion.major)}.${String(nextVersion.minor)}.${String(nextVersion.patch)}` : "unknown",
|
|
@@ -18488,6 +18509,16 @@ function createLogSender(ports) {
|
|
|
18488
18509
|
};
|
|
18489
18510
|
}
|
|
18490
18511
|
|
|
18512
|
+
// ../../packages/sdk/src/analytics.ts
|
|
18513
|
+
var ANALYTICS_FILTER_KEYS = [
|
|
18514
|
+
"path",
|
|
18515
|
+
"referrer",
|
|
18516
|
+
"country",
|
|
18517
|
+
"device",
|
|
18518
|
+
"browser",
|
|
18519
|
+
"os"
|
|
18520
|
+
];
|
|
18521
|
+
|
|
18491
18522
|
// ../../packages/sdk/src/auth.ts
|
|
18492
18523
|
import { homedir as homedir2 } from "os";
|
|
18493
18524
|
|
|
@@ -18960,6 +18991,23 @@ function openBrowser(url2) {
|
|
|
18960
18991
|
child.unref();
|
|
18961
18992
|
}
|
|
18962
18993
|
|
|
18994
|
+
// ../../packages/sdk/src/insights.ts
|
|
18995
|
+
var SPEED_INSIGHTS_METRICS = [
|
|
18996
|
+
"lcp",
|
|
18997
|
+
"inp",
|
|
18998
|
+
"cls",
|
|
18999
|
+
"fcp",
|
|
19000
|
+
"ttfb"
|
|
19001
|
+
];
|
|
19002
|
+
var SPEED_INSIGHTS_FILTER_KEYS = [
|
|
19003
|
+
"path",
|
|
19004
|
+
"country",
|
|
19005
|
+
"device",
|
|
19006
|
+
"browser",
|
|
19007
|
+
"os"
|
|
19008
|
+
];
|
|
19009
|
+
var SPEED_INSIGHTS_MIN_DEPLOYMENT_SAMPLES = 20;
|
|
19010
|
+
|
|
18963
19011
|
// ../../packages/sdk/src/types.ts
|
|
18964
19012
|
var TERMINAL_DEPLOYMENT_STATUSES = [
|
|
18965
19013
|
"READY",
|
|
@@ -19052,6 +19100,7 @@ var NaroClient = class {
|
|
|
19052
19100
|
backend;
|
|
19053
19101
|
storage;
|
|
19054
19102
|
insights;
|
|
19103
|
+
analytics;
|
|
19055
19104
|
protection;
|
|
19056
19105
|
constructor(options) {
|
|
19057
19106
|
this.baseUrl = (options.baseUrl ?? controlPlaneUrl()).replace(/\/$/, "");
|
|
@@ -19069,6 +19118,7 @@ var NaroClient = class {
|
|
|
19069
19118
|
this.backend = new BackendApi(this);
|
|
19070
19119
|
this.storage = new StorageApi(this);
|
|
19071
19120
|
this.insights = new InsightsApi(this);
|
|
19121
|
+
this.analytics = new AnalyticsApi(this);
|
|
19072
19122
|
this.protection = new ProtectionApi(this);
|
|
19073
19123
|
}
|
|
19074
19124
|
async request(path, options) {
|
|
@@ -19477,12 +19527,20 @@ var LogsApi = class {
|
|
|
19477
19527
|
return body.entries;
|
|
19478
19528
|
}
|
|
19479
19529
|
};
|
|
19530
|
+
function appendFilters(params, keys, filters) {
|
|
19531
|
+
if (!filters) return;
|
|
19532
|
+
for (const key of keys) {
|
|
19533
|
+
const value = filters[key];
|
|
19534
|
+
if (value) params.set(key, value);
|
|
19535
|
+
}
|
|
19536
|
+
}
|
|
19480
19537
|
function insightsQuery(options) {
|
|
19481
19538
|
const params = new URLSearchParams();
|
|
19482
19539
|
if (options.range !== void 0) params.set("range", options.range);
|
|
19483
19540
|
if (options.metric !== void 0) params.set("metric", options.metric);
|
|
19484
19541
|
if (options.environment !== void 0) params.set("env", options.environment);
|
|
19485
19542
|
if (options.route !== void 0) params.set("route", options.route);
|
|
19543
|
+
appendFilters(params, SPEED_INSIGHTS_FILTER_KEYS, options.filters);
|
|
19486
19544
|
const text2 = params.toString();
|
|
19487
19545
|
return text2 ? `?${text2}` : "";
|
|
19488
19546
|
}
|
|
@@ -19493,7 +19551,7 @@ var InsightsApi = class {
|
|
|
19493
19551
|
base(projectId) {
|
|
19494
19552
|
return `/api/projects/${encodeURIComponent(projectId)}/speed-insights`;
|
|
19495
19553
|
}
|
|
19496
|
-
/** The five metrics' summary, and the trend, pages, devices and elements of one. */
|
|
19554
|
+
/** The five metrics' summary, and the trend, pages, devices, browsers, operating systems, countries and elements of one. */
|
|
19497
19555
|
async report(projectId, options = {}) {
|
|
19498
19556
|
return this.client.request(
|
|
19499
19557
|
`${this.base(projectId)}${insightsQuery(options)}`,
|
|
@@ -19553,6 +19611,22 @@ var InsightsApi = class {
|
|
|
19553
19611
|
});
|
|
19554
19612
|
}
|
|
19555
19613
|
};
|
|
19614
|
+
var AnalyticsApi = class {
|
|
19615
|
+
constructor(client) {
|
|
19616
|
+
this.client = client;
|
|
19617
|
+
}
|
|
19618
|
+
/** Visitors, page views, the trend, and the pages, referrers, countries, devices, browsers and operating systems behind them. */
|
|
19619
|
+
async report(projectId, options = {}) {
|
|
19620
|
+
const params = new URLSearchParams();
|
|
19621
|
+
if (options.range !== void 0) params.set("range", options.range);
|
|
19622
|
+
appendFilters(params, ANALYTICS_FILTER_KEYS, options.filters);
|
|
19623
|
+
const text2 = params.toString();
|
|
19624
|
+
return this.client.request(
|
|
19625
|
+
`/api/projects/${encodeURIComponent(projectId)}/analytics${text2 ? `?${text2}` : ""}`,
|
|
19626
|
+
{ context: "Read Analytics" }
|
|
19627
|
+
);
|
|
19628
|
+
}
|
|
19629
|
+
};
|
|
19556
19630
|
var ProtectionApi = class {
|
|
19557
19631
|
constructor(client) {
|
|
19558
19632
|
this.client = client;
|
|
@@ -21056,6 +21130,12 @@ var CATALOG = {
|
|
|
21056
21130
|
status: 507,
|
|
21057
21131
|
message: () => "This project has used all of its storage. Delete objects to free space; uploads fail until then."
|
|
21058
21132
|
},
|
|
21133
|
+
// Storage 3-1d (design §6.4): like WRITE_QUOTA_EXCEEDED, a 429 that clears
|
|
21134
|
+
// by itself at midnight; downloads, deletes and listings are not refused.
|
|
21135
|
+
STORAGE_OPS_QUOTA_EXCEEDED: {
|
|
21136
|
+
status: 429,
|
|
21137
|
+
message: () => "This project has reached its daily storage operation limit. Downloads still work; uploads resume at 00:00 UTC."
|
|
21138
|
+
},
|
|
21059
21139
|
// R2 or its binding did not answer; the original error is logged, never sent.
|
|
21060
21140
|
STORAGE_UNAVAILABLE: {
|
|
21061
21141
|
status: 503,
|
|
@@ -27333,16 +27413,6 @@ function generateTypes(tables, options = {}) {
|
|
|
27333
27413
|
`;
|
|
27334
27414
|
}
|
|
27335
27415
|
|
|
27336
|
-
// ../../packages/sdk/src/insights.ts
|
|
27337
|
-
var SPEED_INSIGHTS_METRICS = [
|
|
27338
|
-
"lcp",
|
|
27339
|
-
"inp",
|
|
27340
|
-
"cls",
|
|
27341
|
-
"fcp",
|
|
27342
|
-
"ttfb"
|
|
27343
|
-
];
|
|
27344
|
-
var SPEED_INSIGHTS_MIN_DEPLOYMENT_SAMPLES = 20;
|
|
27345
|
-
|
|
27346
27416
|
// ../../packages/sdk/src/link.ts
|
|
27347
27417
|
import {
|
|
27348
27418
|
existsSync as existsSync4,
|
|
@@ -28464,6 +28534,7 @@ export {
|
|
|
28464
28534
|
schemaMigrationTitle,
|
|
28465
28535
|
projectPath,
|
|
28466
28536
|
splitStatements,
|
|
28537
|
+
ANALYTICS_FILTER_KEYS,
|
|
28467
28538
|
NaroError,
|
|
28468
28539
|
isNaroError,
|
|
28469
28540
|
toNaroError,
|
|
@@ -28477,6 +28548,9 @@ export {
|
|
|
28477
28548
|
login,
|
|
28478
28549
|
resolveAuth,
|
|
28479
28550
|
openBrowser,
|
|
28551
|
+
SPEED_INSIGHTS_METRICS,
|
|
28552
|
+
SPEED_INSIGHTS_FILTER_KEYS,
|
|
28553
|
+
SPEED_INSIGHTS_MIN_DEPLOYMENT_SAMPLES,
|
|
28480
28554
|
isTerminalStatus,
|
|
28481
28555
|
BACKEND_STEPS,
|
|
28482
28556
|
isStalledBackend,
|
|
@@ -28515,8 +28589,6 @@ export {
|
|
|
28515
28589
|
formatRedirectEntry,
|
|
28516
28590
|
policiesForTypes,
|
|
28517
28591
|
generateTypes,
|
|
28518
|
-
SPEED_INSIGHTS_METRICS,
|
|
28519
|
-
SPEED_INSIGHTS_MIN_DEPLOYMENT_SAMPLES,
|
|
28520
28592
|
readProjectLink,
|
|
28521
28593
|
writeProjectLink,
|
|
28522
28594
|
removeProjectLink,
|