naro-cli 0.14.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 +15 -1
- package/dist/{chunk-U7AZSAFS.js → chunk-6WJ3QQ5Y.js} +40 -13
- package/dist/deploy.js +1 -1
- package/dist/index.js +50 -4
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -173,7 +173,7 @@ naro policy set posts --from-file policy.json
|
|
|
173
173
|
Shorthand: writes the policies naro_select … naro_delete
|
|
174
174
|
naro policy remove todos Drop every policy on the table: back to deny (asks first)
|
|
175
175
|
|
|
176
|
-
naro storage Naro Storage: on or off, limits, usage, buckets
|
|
176
|
+
naro storage Naro Storage: on or off, limits, usage, today's operations, buckets
|
|
177
177
|
naro storage enable Turn it on: the project's R2 bucket, bound to the backend
|
|
178
178
|
naro storage bucket create avatars --public --file-size-limit 5MiB --allowed-mime-types image/png,image/jpeg
|
|
179
179
|
naro storage bucket update avatars --private | --file-size-limit none | --allowed-mime-types any
|
|
@@ -793,6 +793,20 @@ An `--update-check` you give replaces the default: without
|
|
|
793
793
|
|
|
794
794
|
## Release notes
|
|
795
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
|
+
|
|
796
810
|
### 0.14.0
|
|
797
811
|
|
|
798
812
|
- `naro analytics` shows the project's Web Analytics from the terminal: the
|
|
@@ -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",
|
|
@@ -21109,6 +21130,12 @@ var CATALOG = {
|
|
|
21109
21130
|
status: 507,
|
|
21110
21131
|
message: () => "This project has used all of its storage. Delete objects to free space; uploads fail until then."
|
|
21111
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
|
+
},
|
|
21112
21139
|
// R2 or its binding did not answer; the original error is logged, never sent.
|
|
21113
21140
|
STORAGE_UNAVAILABLE: {
|
|
21114
21141
|
status: 503,
|
package/dist/deploy.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -83,7 +83,7 @@ import {
|
|
|
83
83
|
toNaroError,
|
|
84
84
|
unreadablePolicyComment,
|
|
85
85
|
writeProjectLink
|
|
86
|
-
} from "./chunk-
|
|
86
|
+
} from "./chunk-6WJ3QQ5Y.js";
|
|
87
87
|
import "./chunk-K3NQKI34.js";
|
|
88
88
|
|
|
89
89
|
// src/args.ts
|
|
@@ -5272,7 +5272,7 @@ function parseSize(text) {
|
|
|
5272
5272
|
throw new NaroError("VALIDATION_FAILED", SIZE_MESSAGE);
|
|
5273
5273
|
return bytes;
|
|
5274
5274
|
}
|
|
5275
|
-
function binarySize(bytes) {
|
|
5275
|
+
function binarySize(bytes, decimals = 1) {
|
|
5276
5276
|
const units = ["B", "KiB", "MiB", "GiB", "TiB"];
|
|
5277
5277
|
let value = bytes;
|
|
5278
5278
|
let unit = 0;
|
|
@@ -5280,7 +5280,7 @@ function binarySize(bytes) {
|
|
|
5280
5280
|
value /= 1024;
|
|
5281
5281
|
unit += 1;
|
|
5282
5282
|
}
|
|
5283
|
-
const shown = unit === 0 ? String(value) : String(Number(value.toFixed(
|
|
5283
|
+
const shown = unit === 0 ? String(value) : String(Number(value.toFixed(decimals)));
|
|
5284
5284
|
return `${shown} ${units[unit] ?? "B"}`;
|
|
5285
5285
|
}
|
|
5286
5286
|
function count(n, noun) {
|
|
@@ -5308,6 +5308,51 @@ function bucketLine(bucket) {
|
|
|
5308
5308
|
const line = ` ${cells.join(" ")}`;
|
|
5309
5309
|
return bucket.deletingAt === null ? line : `${line} (being removed: \`naro storage bucket remove ${name} --empty\` finishes it)`;
|
|
5310
5310
|
}
|
|
5311
|
+
var WARN_PERCENT = 80;
|
|
5312
|
+
function utcClock(iso) {
|
|
5313
|
+
const at = new Date(iso);
|
|
5314
|
+
return Number.isNaN(at.getTime()) ? null : at.toISOString().slice(11, 16);
|
|
5315
|
+
}
|
|
5316
|
+
function warnedPercent(value, limit) {
|
|
5317
|
+
if (limit === null || !(limit > 0)) return null;
|
|
5318
|
+
const percent2 = Math.floor(value * 100 / limit);
|
|
5319
|
+
return percent2 >= WARN_PERCENT ? percent2 : null;
|
|
5320
|
+
}
|
|
5321
|
+
function meterLines(info) {
|
|
5322
|
+
const { today, limits } = info;
|
|
5323
|
+
if (today === null) return [];
|
|
5324
|
+
const reads = count(today.classBOps, "read");
|
|
5325
|
+
const writes = today.classAOps.toLocaleString("en-US");
|
|
5326
|
+
const dailyOps = limits.dailyOps?.toLocaleString("en-US") ?? null;
|
|
5327
|
+
const lines = [
|
|
5328
|
+
dailyOps === null ? `Today (UTC): ${writes} write operations, ${reads}` : `Today (UTC): ${writes} of ${dailyOps} write operations, ${reads}`
|
|
5329
|
+
];
|
|
5330
|
+
if (today.measuredBytes === null)
|
|
5331
|
+
lines.push("Measured: not yet (the meter reads R2 every 15 minutes)");
|
|
5332
|
+
else {
|
|
5333
|
+
const time = today.measuredAt === null ? null : utcClock(today.measuredAt);
|
|
5334
|
+
lines.push(
|
|
5335
|
+
`Measured: ${binarySize(today.measuredBytes, 2)} in R2${time === null ? "" : ` at ${time} UTC`}`
|
|
5336
|
+
);
|
|
5337
|
+
}
|
|
5338
|
+
if (today.bytesBlocked)
|
|
5339
|
+
lines.push(
|
|
5340
|
+
today.measuredBytes === null ? `\u2717 Uploads are stopped: the bucket is at the storage limit of ${binarySize(limits.bytes)}. Delete objects; uploads reopen after the next measurement (usually within an hour).` : `\u2717 Uploads are stopped: R2 holds ${binarySize(today.measuredBytes, 2)} of ${binarySize(limits.bytes)}. Delete objects; uploads reopen after the next measurement (usually within an hour).`
|
|
5341
|
+
);
|
|
5342
|
+
if (today.opsBlocked)
|
|
5343
|
+
lines.push(
|
|
5344
|
+
dailyOps === null ? "\u2717 Uploads are stopped until 00:00 UTC: today's write operations are used. Downloads still work." : `\u2717 Uploads are stopped until 00:00 UTC: today's ${dailyOps} write operations are used. Downloads still work.`
|
|
5345
|
+
);
|
|
5346
|
+
const storage = today.bytesBlocked || today.measuredBytes === null ? null : warnedPercent(today.measuredBytes, limits.bytes);
|
|
5347
|
+
if (storage !== null)
|
|
5348
|
+
lines.push(`\u26A0 ${String(storage)}% of the storage limit is used.`);
|
|
5349
|
+
const operations = today.opsBlocked ? null : warnedPercent(today.classAOps, limits.dailyOps);
|
|
5350
|
+
if (operations !== null)
|
|
5351
|
+
lines.push(
|
|
5352
|
+
`\u26A0 ${String(operations)}% of today's write operations are used.`
|
|
5353
|
+
);
|
|
5354
|
+
return lines;
|
|
5355
|
+
}
|
|
5311
5356
|
function storageLines(info) {
|
|
5312
5357
|
if (!info.enabled)
|
|
5313
5358
|
return [
|
|
@@ -5319,6 +5364,7 @@ function storageLines(info) {
|
|
|
5319
5364
|
`Storage: on (R2 bucket ${printable(info.bucket ?? "unknown")})`,
|
|
5320
5365
|
`Limits: ${binarySize(limits.bytes)} in all, ${binarySize(limits.objectBytes)} per object, ${binarySize(limits.singleUploadBytes)} per upload`,
|
|
5321
5366
|
usage === null ? "Used: not known yet: the backend is not ready (`naro backend` shows where it got to)" : `Used: ${binarySize(usage.bytes)} in ${count(usage.objects, "object")}`,
|
|
5367
|
+
...meterLines(info),
|
|
5322
5368
|
info.buckets.length === 0 ? "Buckets: none yet (`naro storage bucket create <name>` makes one)" : `Buckets: ${String(info.buckets.length)}`,
|
|
5323
5369
|
...info.buckets.map(bucketLine)
|
|
5324
5370
|
];
|
|
@@ -8328,7 +8374,7 @@ Usage:
|
|
|
8328
8374
|
naro_insert, naro_update, naro_delete (shorthand for CREATE POLICY)
|
|
8329
8375
|
naro policy remove <table> Drop every policy on it: back to deny (asks first)
|
|
8330
8376
|
|
|
8331
|
-
naro storage [status] Naro Storage: on or off, limits, what is stored, the buckets
|
|
8377
|
+
naro storage [status] Naro Storage: on or off, limits, what is stored, today's operations, the buckets
|
|
8332
8378
|
naro storage enable Turn Storage on: the project's R2 bucket, bound to its backend
|
|
8333
8379
|
(safe to re-run; applies a plan change's limits)
|
|
8334
8380
|
naro storage bucket list The buckets: public or private, objects, bytes, limits
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "naro-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"naro": "./dist/index.js"
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"@opennextjs/cloudflare": "1.20.2",
|
|
26
26
|
"@supabase/supabase-js": "2.112.3",
|
|
27
27
|
"@vercel/frameworks": "3.34.0",
|
|
28
|
-
"vinext": "1.
|
|
28
|
+
"vinext": "1.1.0",
|
|
29
29
|
"wrangler": "4.124.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
@@ -34,11 +34,11 @@
|
|
|
34
34
|
"typescript": "7.0.2",
|
|
35
35
|
"vitest": "3.2.7",
|
|
36
36
|
"naro-js": "0.3.0",
|
|
37
|
-
"@next-deploy/build": "0.1.0",
|
|
38
|
-
"@next-deploy/config": "0.1.0",
|
|
39
37
|
"@next-deploy/core": "0.1.0",
|
|
38
|
+
"@next-deploy/data-core": "0.1.0",
|
|
40
39
|
"@next-deploy/sdk": "0.1.0",
|
|
41
|
-
"@next-deploy/
|
|
40
|
+
"@next-deploy/config": "0.1.0",
|
|
41
|
+
"@next-deploy/build": "0.1.0"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"build": "tsup && pnpm build:types",
|