dxfl 0.4.0 → 0.4.2-alpha
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 +9 -0
- package/dist/deploy.js +9 -5
- package/dist/error.js +4 -4
- package/dist/guichet.js +2 -2
- package/dist/index.js +1 -1
- package/dist/inspect.js +12 -11
- package/dist/utils.js +2 -6
- package/dist/vhosts.js +5 -5
- package/dist/website_config.js +18 -15
- package/package.json +4 -3
package/CHANGELOG.md
CHANGED
package/dist/deploy.js
CHANGED
|
@@ -13,7 +13,7 @@ import { PromisePool } from "@supercharge/promise-pool";
|
|
|
13
13
|
import { deleteBucketFile, deleteBucketFiles, getBucketCredentials, getBucket, getBucketFiles, putEmptyObjectRedirect, uploadFile, } from "./bucket.js";
|
|
14
14
|
import { ErrorMsg } from "./error.js";
|
|
15
15
|
import { confirmationPrompt, filterMap, formatBytesHuman, formatCount, getFileMd5, sum, } from "./utils.js";
|
|
16
|
-
import { equalBucketRedirect,
|
|
16
|
+
import { equalBucketRedirect, getBucketConfig, putBucketWebsiteConfig, readConfigFile, } from "./website_config.js";
|
|
17
17
|
// Walks through the local directory at path `dir`, and for each file it contains, returns :
|
|
18
18
|
// - `localPath`: its path on the local filesystem (includes `dir`). On windows, this path
|
|
19
19
|
// will typically use `\` as separator.
|
|
@@ -189,7 +189,11 @@ function printPlan(plan, details) {
|
|
|
189
189
|
const oredirects_updated = plan.redirects.filter(r => r.action == "update");
|
|
190
190
|
const oredirects_deleted = plan.redirects.filter(r => r.action == "delete");
|
|
191
191
|
// check whether CORS rules changed
|
|
192
|
-
const cors_changed = !equalCorsRules(
|
|
192
|
+
// const cors_changed = !equalCorsRules(
|
|
193
|
+
// plan.cors_rules.from,
|
|
194
|
+
// plan.cors_rules.to,
|
|
195
|
+
// );
|
|
196
|
+
const cors_changed = false;
|
|
193
197
|
// print
|
|
194
198
|
if (details == "summary") {
|
|
195
199
|
const sizeRemote = sum([...plan.remoteFiles.values()].map(f => { var _a; return (_a = f.size) !== null && _a !== void 0 ? _a : 0; }));
|
|
@@ -313,9 +317,9 @@ function applyDeployPlan(bucket, plan) {
|
|
|
313
317
|
// Apply bucket redirects & global config
|
|
314
318
|
yield putBucketWebsiteConfig(bucket, plan.index_page.to, plan.error_page.to, plan.bucket_redirects.to);
|
|
315
319
|
// Apply CORS rules
|
|
316
|
-
if (!equalCorsRules(plan.cors_rules.from, plan.cors_rules.to)) {
|
|
317
|
-
|
|
318
|
-
}
|
|
320
|
+
// if (!equalCorsRules(plan.cors_rules.from, plan.cors_rules.to)) {
|
|
321
|
+
// await putCorsRules(bucket, plan.cors_rules.to);
|
|
322
|
+
// }
|
|
319
323
|
});
|
|
320
324
|
}
|
|
321
325
|
export function deploy(website, localFolder, options) {
|
package/dist/error.js
CHANGED
|
@@ -8,7 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import { S3ServiceException } from "@aws-sdk/client-s3";
|
|
11
|
-
import
|
|
11
|
+
import { styleText } from "node:util";
|
|
12
12
|
export class ErrorCtx {
|
|
13
13
|
constructor(ctx, error) {
|
|
14
14
|
this.ctx = ctx;
|
|
@@ -83,10 +83,10 @@ export function wrapS3Call(context, expectedCodes, f) {
|
|
|
83
83
|
// otherwise it is thrown as an exception.
|
|
84
84
|
export function handleError(e) {
|
|
85
85
|
if (e instanceof ErrorMsg) {
|
|
86
|
-
console.error(`${
|
|
86
|
+
console.error(`${styleText("red", "Error:")} ${e.msg}`);
|
|
87
87
|
}
|
|
88
88
|
else if (e instanceof ErrorGuichet) {
|
|
89
|
-
let msg =
|
|
89
|
+
let msg = styleText("red", "Error: ");
|
|
90
90
|
if (e.cause.kind == "Unauthorized") {
|
|
91
91
|
msg +=
|
|
92
92
|
"failed to authenticate with Guichet. Is your password and login correct?";
|
|
@@ -97,7 +97,7 @@ export function handleError(e) {
|
|
|
97
97
|
console.error(msg);
|
|
98
98
|
}
|
|
99
99
|
else {
|
|
100
|
-
console.error(
|
|
100
|
+
console.error(styleText("red", "Unexpected error:") + "\n", e);
|
|
101
101
|
}
|
|
102
102
|
process.exit(1);
|
|
103
103
|
}
|
package/dist/guichet.js
CHANGED
|
@@ -8,7 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import { WebsiteApi, } from "guichet-sdk-ts";
|
|
11
|
-
import {
|
|
11
|
+
import { styleText } from "node:util";
|
|
12
12
|
import { ErrorGuichet } from "./error.js";
|
|
13
13
|
// The GuichetApi class wraps WebsiteApi (from the guichet sdk). It catches
|
|
14
14
|
// errors that can happen in normal use, and it turn them into a dedicated error type
|
|
@@ -45,7 +45,7 @@ export class GuichetApi {
|
|
|
45
45
|
// the migration of websites *.web.deuxfleurs.fr to bucket
|
|
46
46
|
// names with the full domain name.
|
|
47
47
|
// We just warn that this is a working but deprecated name.
|
|
48
|
-
console.log(`${
|
|
48
|
+
console.log(`${styleText("yellow", "Warning")}: the name "${vhost}" is now deprecated for this website,` +
|
|
49
49
|
` you should use "${vhost}.web.deuxfleurs.fr" instead.`);
|
|
50
50
|
}
|
|
51
51
|
return websiteInfo;
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { deploy } from "./deploy.js";
|
|
|
6
6
|
import { empty } from "./empty.js";
|
|
7
7
|
import { vhostsList } from "./vhosts.js";
|
|
8
8
|
import { inspect } from "./inspect.js";
|
|
9
|
-
program.name("dxfl").description("Deuxfleurs CLI tool").version("0.4.
|
|
9
|
+
program.name("dxfl").description("Deuxfleurs CLI tool").version("0.4.2-alpha");
|
|
10
10
|
program
|
|
11
11
|
.command("login")
|
|
12
12
|
.description("Link your Deuxfleurs account with this tool.")
|
package/dist/inspect.js
CHANGED
|
@@ -9,8 +9,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import { WebsiteApi } from "guichet-sdk-ts";
|
|
11
11
|
import { openApiConf } from "./auth.js";
|
|
12
|
-
import { formatBytesHuman, separator
|
|
13
|
-
import
|
|
12
|
+
import { formatBytesHuman, separator } from "./utils.js";
|
|
13
|
+
import { styleText } from "node:util";
|
|
14
14
|
export function inspect(website, options) {
|
|
15
15
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16
16
|
var _a, _b, _c;
|
|
@@ -24,17 +24,18 @@ export function inspect(website, options) {
|
|
|
24
24
|
if (!options.secret) {
|
|
25
25
|
kSecret =
|
|
26
26
|
`**** ` +
|
|
27
|
-
|
|
27
|
+
styleText(["gray", "italic"], `(use \`dxfl inspect ${v === null || v === void 0 ? void 0 : v.name} --secret\` to reveal it)`);
|
|
28
28
|
}
|
|
29
|
-
console.log(
|
|
29
|
+
console.log(styleText(["green", "bold"], `${v === null || v === void 0 ? void 0 : v.name} details`));
|
|
30
30
|
console.log(separator());
|
|
31
|
-
console.log(` ${
|
|
32
|
-
console.log(` ${
|
|
33
|
-
console.log(` ${
|
|
34
|
-
console.log(` ${
|
|
35
|
-
console.log(` ${
|
|
36
|
-
console.log(` ${
|
|
31
|
+
console.log(` ${styleText("bold", "id")}: ${v === null || v === void 0 ? void 0 : v.name}`);
|
|
32
|
+
console.log(` ${styleText("bold", "url")}: ${styleText("underline", "https://" + (v === null || v === void 0 ? void 0 : v.domain))}`);
|
|
33
|
+
console.log(` ${styleText("bold", "usage")}:`, `${formatBytesHuman((_a = q === null || q === void 0 ? void 0 : q.current) !== null && _a !== void 0 ? _a : 0)} / ${formatBytesHuman((_b = q === null || q === void 0 ? void 0 : q.max) !== null && _b !== void 0 ? _b : 0)}`, `(${Math.round(((_c = q === null || q === void 0 ? void 0 : q.ratio) !== null && _c !== void 0 ? _c : 0) * 100)}%)`);
|
|
34
|
+
console.log(` ${styleText("bold", "S3 keys")}:`);
|
|
35
|
+
console.log(` ${styleText("bold", "access_key_id")}: ${kId}`);
|
|
36
|
+
console.log(` ${styleText("bold", "secret_access_key")}: ${kSecret}`);
|
|
37
37
|
console.log(separator());
|
|
38
|
-
console.log(
|
|
38
|
+
console.log(styleText(["gray", "italic"], `→ For more information and features, you can visit the web UI: ` +
|
|
39
|
+
`${styleText("underline", "https://guichet.deuxfleurs.fr/website/inspect/" + (v === null || v === void 0 ? void 0 : v.name))}`));
|
|
39
40
|
});
|
|
40
41
|
}
|
package/dist/utils.js
CHANGED
|
@@ -19,11 +19,7 @@ import crypto from "crypto";
|
|
|
19
19
|
import { stdin, stdout } from "process";
|
|
20
20
|
import readline from "readline/promises";
|
|
21
21
|
import { ErrorMsg } from "./error.js";
|
|
22
|
-
import
|
|
23
|
-
export const textGreen = clc.green;
|
|
24
|
-
export const textWarn = clc.yellow;
|
|
25
|
-
export const textError = clc.red;
|
|
26
|
-
export const textGrey = clc.xterm(242);
|
|
22
|
+
import { styleText } from "node:util";
|
|
27
23
|
export function getFileMd5(file) {
|
|
28
24
|
return __awaiter(this, void 0, void 0, function* () {
|
|
29
25
|
var _a, e_1, _b, _c;
|
|
@@ -132,5 +128,5 @@ export function separator(size = 42) {
|
|
|
132
128
|
for (let i = 0; i < size; i++) {
|
|
133
129
|
dashes += "-";
|
|
134
130
|
}
|
|
135
|
-
return
|
|
131
|
+
return styleText("gray", dashes);
|
|
136
132
|
}
|
package/dist/vhosts.js
CHANGED
|
@@ -9,8 +9,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import { WebsiteApi } from "guichet-sdk-ts";
|
|
11
11
|
import { openApiConf } from "./auth.js";
|
|
12
|
-
import { separator
|
|
13
|
-
import
|
|
12
|
+
import { separator } from "./utils.js";
|
|
13
|
+
import { styleText } from "node:util";
|
|
14
14
|
export function vhostsList() {
|
|
15
15
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16
16
|
var _a, _b, _c;
|
|
@@ -24,9 +24,9 @@ export function vhostsList() {
|
|
|
24
24
|
if (i === 0) {
|
|
25
25
|
console.log(separator());
|
|
26
26
|
}
|
|
27
|
-
console.log(
|
|
28
|
-
console.log(` ${
|
|
29
|
-
console.log(` ${
|
|
27
|
+
console.log(styleText("green", v.name || ""));
|
|
28
|
+
console.log(` ${styleText("green", "id")}: ${v.name}`);
|
|
29
|
+
console.log(` ${styleText("bold", "url")}: ${styleText("underline", "https://" + v.domain)}`);
|
|
30
30
|
console.log(separator());
|
|
31
31
|
});
|
|
32
32
|
});
|
package/dist/website_config.js
CHANGED
|
@@ -12,7 +12,7 @@ import TOML from "smol-toml";
|
|
|
12
12
|
import URI from "fast-uri";
|
|
13
13
|
import { z as zod } from "zod";
|
|
14
14
|
import { fromError as zodError } from "zod-validation-error";
|
|
15
|
-
import {
|
|
15
|
+
import { GetBucketWebsiteCommand, PutBucketWebsiteCommand, PutBucketCorsCommand, } from "@aws-sdk/client-s3";
|
|
16
16
|
import { ErrorMsg, withErrorMsg, wrapS3Call } from "./error.js";
|
|
17
17
|
import { getBucketFilesDetails } from "./bucket.js";
|
|
18
18
|
////////////// Utilities
|
|
@@ -324,12 +324,14 @@ export function getBucketConfig(bucket, files) {
|
|
|
324
324
|
// - A Head command for each file in the bucket to collect object redirects.
|
|
325
325
|
// (This can become relatively slow for buckets with thousands of files,
|
|
326
326
|
// but I don't know of a better way.)
|
|
327
|
-
var _a, _b
|
|
328
|
-
const [website,
|
|
327
|
+
var _a, _b;
|
|
328
|
+
const [website, details] = yield Promise.all([
|
|
329
329
|
// 204 "No Content" is returned when there is no existing website config
|
|
330
330
|
wrapS3Call(`read the bucket website config`, [200, 204], () => bucket.client.send(new GetBucketWebsiteCommand({ Bucket: bucket.name }))),
|
|
331
331
|
// 204 "No Content" is returned when there are no existing CORS rules
|
|
332
|
-
wrapS3Call(`read the bucket CORS config`, [200, 204], () =>
|
|
332
|
+
// wrapS3Call(`read the bucket CORS config`, [200, 204], () =>
|
|
333
|
+
// bucket.client.send(new GetBucketCorsCommand({ Bucket: bucket.name })),
|
|
334
|
+
// ),
|
|
333
335
|
getBucketFilesDetails(bucket, files),
|
|
334
336
|
]);
|
|
335
337
|
// Collect object redirects
|
|
@@ -340,7 +342,8 @@ export function getBucketConfig(bucket, files) {
|
|
|
340
342
|
}
|
|
341
343
|
}
|
|
342
344
|
// Interpret bucket redirects
|
|
343
|
-
if (website.RedirectAllRequestsTo
|
|
345
|
+
if (website.RedirectAllRequestsTo &&
|
|
346
|
+
"HostName" in website.RedirectAllRequestsTo) {
|
|
344
347
|
// NB: garage does not currently support RedirectAllRequestsTo so this should never happen
|
|
345
348
|
throw new ErrorMsg(`remote website configuration: RedirectAllRequestsTo is specified; ` +
|
|
346
349
|
`this is currently unsupported by dxfl`);
|
|
@@ -414,16 +417,16 @@ export function getBucketConfig(bucket, files) {
|
|
|
414
417
|
}
|
|
415
418
|
// Interpret CORS rules
|
|
416
419
|
let cors_rules = [];
|
|
417
|
-
if (cors.CORSRules) {
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
}
|
|
420
|
+
// if (cors.CORSRules) {
|
|
421
|
+
// for (const rule of cors.CORSRules) {
|
|
422
|
+
// cors_rules.push({
|
|
423
|
+
// allowed_origins: rule.AllowedOrigins ?? [],
|
|
424
|
+
// allowed_methods: rule.AllowedMethods ?? [],
|
|
425
|
+
// allowed_headers: rule.AllowedHeaders ?? [],
|
|
426
|
+
// expose_headers: rule.ExposeHeaders ?? [],
|
|
427
|
+
// });
|
|
428
|
+
// }
|
|
429
|
+
// }
|
|
427
430
|
return {
|
|
428
431
|
index_page,
|
|
429
432
|
error_page,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dxfl",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2-alpha",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "EUPL-1.2",
|
|
6
6
|
"author": "Deuxfleurs Team <coucou@deuxfleurs.fr>",
|
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
"bin": {
|
|
14
14
|
"dxfl": "dist/index.js"
|
|
15
15
|
},
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=20.0.0"
|
|
18
|
+
},
|
|
16
19
|
"scripts": {
|
|
17
20
|
"prepare": "npx tsc",
|
|
18
21
|
"prettier": "npx prettier . --write",
|
|
@@ -24,7 +27,6 @@
|
|
|
24
27
|
"@commander-js/extra-typings": "^14.0.0",
|
|
25
28
|
"@supercharge/promise-pool": "^3.2.0",
|
|
26
29
|
"@types/node": "^25.2.1",
|
|
27
|
-
"cli-color": "^2.0.4",
|
|
28
30
|
"commander": "^14.0.3",
|
|
29
31
|
"fast-uri": "^3.1.0",
|
|
30
32
|
"guichet-sdk-ts": "^0.1.0",
|
|
@@ -36,7 +38,6 @@
|
|
|
36
38
|
"zod-validation-error": "^3.4.1"
|
|
37
39
|
},
|
|
38
40
|
"devDependencies": {
|
|
39
|
-
"@types/cli-color": "^2.0.6",
|
|
40
41
|
"onchange": "^7.1.0",
|
|
41
42
|
"prettier": "3.5.3"
|
|
42
43
|
}
|