dxfl 0.1.8 → 0.1.9

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 CHANGED
@@ -1,3 +1,9 @@
1
+ # v0.1.9
2
+
3
+ - `deuxfleurs.toml`: rename redirection property `if_error = 404` to `force = true`, to simplify and improve comprehension.
4
+
5
+ # v0.1.8
6
+
1
7
  - `deploy`: add support for redirects, configured from a new `deuxfleurs.toml` file.
2
8
  - supports S3 "object redirects" (redirects from a path in the website)
3
9
  - supports global "bucket redirects" (redirects from any path in the website
package/README.md CHANGED
@@ -10,7 +10,7 @@ npm install -g dxfl
10
10
 
11
11
  ## Usage
12
12
 
13
- _Not ready_
13
+ _Warning: software still in an experimental state_
14
14
 
15
15
  Start by login with your username, for example for `john`:
16
16
 
@@ -30,13 +30,19 @@ And then to deploy your `_public` folder on `example.com`:
30
30
  dxfl deploy example.com _public
31
31
  ```
32
32
 
33
- Or potentially preview the upcoming changes with the `--dry-run` option:
33
+ To deploy without confirmation, use the `--yes` option:
34
+
35
+ ```
36
+ dxfl deploy example.com _public --yes
37
+ ```
38
+
39
+ Or only display the changes without applying them, with the `--dry-run` option:
34
40
 
35
41
  ```
36
42
  dxfl deploy example.com _public --dry-run
37
43
  ```
38
44
 
39
- If you need to empty a website from its contents:
45
+ Use the `empty` command to delete all files from a website (required before deleting it):
40
46
 
41
47
  ```
42
48
  dxfl empty example.com
@@ -45,7 +51,7 @@ dxfl empty example.com
45
51
  ## Website configuration
46
52
 
47
53
  `dxfl deploy` reads a `deuxfleurs.toml` configuration file (if it exists in the current directory).
48
- This file can be used to specify website configuration metadata, such as redirections.
54
+ This file can be used to specify website configuration metadata such as redirections.
49
55
 
50
56
  Your `deuxfleurs.toml` should follow the following structure:
51
57
 
@@ -53,8 +59,8 @@ Your `deuxfleurs.toml` should follow the following structure:
53
59
  # Filename added after URLs that point to directories.
54
60
  # Default value: "index.html"
55
61
  index_page = "index.html"
56
- # Path to the file to serve in case of 404 error
57
- # Default value: none.
62
+ # Path to the file to serve in case of 404 error.
63
+ # Default value: none
58
64
  error_page = "404.html"
59
65
 
60
66
  # A redirect entry. There can be as many as desired.
@@ -75,9 +81,15 @@ from = "foobar/*"
75
81
  # single path.
76
82
  to = "baz/*"
77
83
  # Optional: custom HTTP status code for the redirection.
78
- status = 302
79
- # Optional: only redirect if the original request triggered a 404 error
80
- if_error = 404
84
+ # Default value: 302
85
+ status = 301
86
+ # Optional: always apply the redirect.
87
+ # By default, redirections that match multiple paths do not apply
88
+ # if a file that matches the requested path could be served instead.
89
+ # Setting this option to true overrides this behavior and always
90
+ # applies the redirection.
91
+ # Default value: false
92
+ force = true
81
93
  ```
82
94
 
83
95
  ## Development
@@ -113,6 +125,7 @@ Do not forget also to run `npm login` to bind your account with the CLI.
113
125
  Then to publish a release:
114
126
 
115
127
  ```bash
128
+ vim CHANGELOG.md # update the version and its content in this file
116
129
  vim package.json # update the version in this file
117
130
  vim index.ts # update the version in this file
118
131
  npm install # update the version in the package-lock.json
package/dist/deploy.js CHANGED
@@ -163,8 +163,8 @@ function printPlan(plan, details) {
163
163
  const proto = r.protocol ? `${r.protocol}://` : "";
164
164
  const hostname = r.hostname ? `${r.hostname}/` : "";
165
165
  const status = r.status ? ` status=${r.status}` : "";
166
- const if_error = r.if_error ? ` if_error=${r.if_error}` : "";
167
- return `${proto}${hostname}${to}${status}${if_error}`;
166
+ const force = r.force ? ` force=${r.force}` : "";
167
+ return `${proto}${hostname}${to}${status}${force}`;
168
168
  }
169
169
  function showBucketRedirect(r) {
170
170
  return `${r.prefix}* -> ${showBucketRedirectTarget(r)}`;
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import { login } from "./auth.js";
4
4
  import { deploy } from "./deploy.js";
5
5
  import { empty } from "./empty.js";
6
6
  import { vhostsList } from "./vhosts.js";
7
- program.name("dxfl").description("Deuxfleurs CLI tool").version("0.1.8");
7
+ program.name("dxfl").description("Deuxfleurs CLI tool").version("0.1.9");
8
8
  program
9
9
  .command("login")
10
10
  .description("Link your Deuxfleurs account with this tool.")
@@ -28,7 +28,7 @@ export function equalBucketRedirect(b1, b2) {
28
28
  }
29
29
  }
30
30
  return (b1.prefix === b2.prefix &&
31
- b1.if_error === b2.if_error &&
31
+ b1.force === b2.force &&
32
32
  b1.hostname === b2.hostname &&
33
33
  b1.status === b2.status &&
34
34
  b1.protocol === b2.protocol &&
@@ -64,7 +64,7 @@ function readConfigFileObject(filename) {
64
64
  const RawRedirectSchema = zod.object({
65
65
  from: zod.string(),
66
66
  to: zod.string(),
67
- if_error: zod.number().int().optional(),
67
+ force: zod.boolean().optional(),
68
68
  status: zod.number().int().positive().optional(),
69
69
  });
70
70
  const RawConfigSchema = zod.object({
@@ -124,7 +124,7 @@ function interpConfig(rawcfg) {
124
124
  }
125
125
  }
126
126
  function interpRedirect(i, r) {
127
- var _a;
127
+ var _a, _b;
128
128
  const rfrom = interpPath(`Redirect ${i}, from`, r.from);
129
129
  const rto = interpPath(`Redirect ${i}, to`, r.to);
130
130
  let redirect;
@@ -167,7 +167,7 @@ function interpConfig(rawcfg) {
167
167
  }
168
168
  let bredirect = {
169
169
  prefix,
170
- if_error: undefined,
170
+ force: (_b = r.force) !== null && _b !== void 0 ? _b : false,
171
171
  hostname: toURI.host,
172
172
  protocol: toURI.scheme,
173
173
  // Unless specified, set the status to 302.
@@ -180,12 +180,6 @@ function interpConfig(rawcfg) {
180
180
  ? { kind: "replace_prefix", prefix: path }
181
181
  : { kind: "replace", target: path },
182
182
  };
183
- if (r.if_error) {
184
- if (r.if_error != 404) {
185
- throw `Redirect ${i}: the only currently supported value for 'if_error' is 404`;
186
- }
187
- bredirect.if_error = 404;
188
- }
189
183
  if (r.status) {
190
184
  if ([301, 302, 303, 307, 308].includes(r.status)) {
191
185
  bredirect.status = r.status;
@@ -204,8 +198,9 @@ function interpConfig(rawcfg) {
204
198
  }
205
199
  else {
206
200
  // This is an object redirect
207
- if (r.if_error) {
208
- throw `Redirect ${i}: 'if_error' is not supported for single redirections`;
201
+ if (r.force) {
202
+ throw (`Redirect ${i}: 'force' is not supported for single redirections.\n` +
203
+ "The source of the redirection must not exist already as a file.");
209
204
  }
210
205
  if (r.status) {
211
206
  throw (`Redirect ${i}: 'status' is not supported for single redirections.\n` +
@@ -221,7 +216,7 @@ function interpConfig(rawcfg) {
221
216
  if (from.startsWith("/")) {
222
217
  from = from.substring(1);
223
218
  }
224
- // for the 'to' field, garage expects a target that starts with 'http://', 'https://'
219
+ // for the 'to' field, garage expects the target to start with 'http://', 'https://'
225
220
  // or '/'. So if the 'to' field does not start with '/', add one...
226
221
  let to = rto.s;
227
222
  if (!(to.startsWith("http://") ||
@@ -297,16 +292,17 @@ export function getBucketConfig(bucket, files) {
297
292
  // If no Condition is specified, then the redirect always applies, which is equivalent
298
293
  // to matching on an empty prefix
299
294
  let prefix = "";
300
- let if_error = undefined;
295
+ // If no HttpErrorCodeReturnedEquals is specified, then the redirection always
296
+ // applies, which is equivalent to force=true
297
+ let force = true;
301
298
  if (rule.Condition) {
302
299
  if (rule.Condition.HttpErrorCodeReturnedEquals) {
303
300
  if (rule.Condition.HttpErrorCodeReturnedEquals == "404") {
304
- if_error = 404;
301
+ force = false;
305
302
  }
306
303
  else {
307
- // currently not supported by garage
308
- throw (`remote website configuration: 'if_error' specified with a different ` +
309
- `status code than 404; this is currently unsupported by dxfl`);
304
+ // not supported by garage
305
+ throw `remote website configuration: unexpected value for 'HttpErrorCodeReturnedEquals': ${rule.Condition.HttpErrorCodeReturnedEquals}`;
310
306
  }
311
307
  }
312
308
  if (rule.Condition.KeyPrefixEquals) {
@@ -346,7 +342,7 @@ export function getBucketConfig(bucket, files) {
346
342
  }
347
343
  bucket_redirects.push({
348
344
  prefix,
349
- if_error,
345
+ force,
350
346
  hostname,
351
347
  status,
352
348
  protocol,
@@ -378,8 +374,8 @@ export function putBucketWebsiteConfig(bucket, index_page, error_page, bucket_re
378
374
  },
379
375
  Redirect: {},
380
376
  };
381
- if (r.if_error) {
382
- rule.Condition.HttpErrorCodeReturnedEquals = r.if_error.toString();
377
+ if (!r.force) {
378
+ rule.Condition.HttpErrorCodeReturnedEquals = "404";
383
379
  }
384
380
  if (r.hostname) {
385
381
  rule.Redirect.HostName = r.hostname;
package/package.json CHANGED
@@ -1,9 +1,13 @@
1
1
  {
2
2
  "name": "dxfl",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "",
5
5
  "license": "EUPL-1.2",
6
6
  "author": "Deuxfleurs Team <coucou@deuxfleurs.fr>",
7
+ "keywords": [
8
+ "cli",
9
+ "deuxfleurs"
10
+ ],
7
11
  "type": "module",
8
12
  "main": "dist/main.js",
9
13
  "bin": {