@strapi/strapi 4.6.0-beta.2 → 4.6.1

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 CHANGED
@@ -95,12 +95,12 @@ Strapi only supports maintenance and LTS versions of Node.js. Please refer to th
95
95
 
96
96
  **Database:**
97
97
 
98
- | Database | Minimum | Recommended |
99
- | ---------- | ------- | ----------- |
100
- | MySQL | 5.7.8 | 8.0 |
101
- | MariaDB | 10.3 | 10.6 |
102
- | PostgreSQL | 11.0 | 14.0 |
103
- | SQLite | 3 | 3 |
98
+ | Database | Recommended | Minimum |
99
+ | ---------- | ----------- | ------- |
100
+ | MySQL | 8.0 | 5.7.8 |
101
+ | MariaDB | 10.6 | 10.3 |
102
+ | PostgreSQL | 14.0 | 11.0 |
103
+ | SQLite | 3 | 3 |
104
104
 
105
105
  **We recommend always using the latest version of Strapi stable to start your new projects**.
106
106
 
package/bin/strapi.js CHANGED
@@ -17,16 +17,19 @@ const packageJSON = require('../package.json');
17
17
  const {
18
18
  promptEncryptionKey,
19
19
  confirmMessage,
20
- parseURL,
21
20
  forceOption,
22
21
  } = require('../lib/commands/utils/commander');
23
- const { ifOptions, assertUrlHasProtocol, exitWith } = require('../lib/commands/utils/helpers');
22
+ const { exitWith } = require('../lib/commands/utils/helpers');
24
23
  const {
25
24
  excludeOption,
26
25
  onlyOption,
27
26
  validateExcludeOnly,
28
27
  } = require('../lib/commands/transfer/utils');
29
28
 
29
+ process.on('SIGINT', () => {
30
+ process.exit();
31
+ });
32
+
30
33
  const checkCwdIsStrapiApp = (name) => {
31
34
  const logErrorAndExit = () => {
32
35
  console.log(
@@ -269,59 +272,59 @@ program
269
272
  .option('-s, --silent', `Run the generation silently, without any output`, false)
270
273
  .action(getLocalScript('ts/generate-types'));
271
274
 
272
- if (process.env.STRAPI_EXPERIMENTAL === 'true') {
273
- // `$ strapi transfer`
274
- program
275
- .command('transfer')
276
- .description('Transfer data from one source to another')
277
- .allowExcessArguments(false)
278
- .addOption(
279
- new Option(
280
- '--from <sourceURL>',
281
- `URL of the remote Strapi instance to get data from`
282
- ).argParser(parseURL)
283
- )
284
- .addOption(
285
- new Option(
286
- '--to <destinationURL>',
287
- `URL of the remote Strapi instance to send data to`
288
- ).argParser(parseURL)
289
- )
290
- .addOption(forceOption)
291
- // Validate URLs
292
- .hook(
293
- 'preAction',
294
- ifOptions(
295
- (opts) => opts.from,
296
- (thisCommand) => assertUrlHasProtocol(thisCommand.opts().from, ['https:', 'http:'])
297
- )
298
- )
299
- .hook(
300
- 'preAction',
301
- ifOptions(
302
- (opts) => opts.to,
303
- (thisCommand) => assertUrlHasProtocol(thisCommand.opts().to, ['https:', 'http:'])
304
- )
305
- )
306
- .hook(
307
- 'preAction',
308
- ifOptions(
309
- (opts) => !opts.from && !opts.to,
310
- () => exitWith(1, 'At least one source (from) or destination (to) option must be provided')
311
- )
312
- )
313
- .addOption(forceOption)
314
- .addOption(excludeOption)
315
- .addOption(onlyOption)
316
- .hook('preAction', validateExcludeOnly)
317
- .hook(
318
- 'preAction',
319
- confirmMessage(
320
- 'The import will delete all data in the remote database. Are you sure you want to proceed?'
321
- )
322
- )
323
- .action(getLocalScript('transfer/transfer'));
324
- }
275
+ // if (process.env.STRAPI_EXPERIMENTAL === 'true') {
276
+ // // `$ strapi transfer`
277
+ // program
278
+ // .command('transfer')
279
+ // .description('Transfer data from one source to another')
280
+ // .allowExcessArguments(false)
281
+ // .addOption(
282
+ // new Option(
283
+ // '--from <sourceURL>',
284
+ // `URL of the remote Strapi instance to get data from`
285
+ // ).argParser(parseURL)
286
+ // )
287
+ // .addOption(
288
+ // new Option(
289
+ // '--to <destinationURL>',
290
+ // `URL of the remote Strapi instance to send data to`
291
+ // ).argParser(parseURL)
292
+ // )
293
+ // .addOption(forceOption)
294
+ // // Validate URLs
295
+ // .hook(
296
+ // 'preAction',
297
+ // ifOptions(
298
+ // (opts) => opts.from,
299
+ // (thisCommand) => assertUrlHasProtocol(thisCommand.opts().from, ['https:', 'http:'])
300
+ // )
301
+ // )
302
+ // .hook(
303
+ // 'preAction',
304
+ // ifOptions(
305
+ // (opts) => opts.to,
306
+ // (thisCommand) => assertUrlHasProtocol(thisCommand.opts().to, ['https:', 'http:'])
307
+ // )
308
+ // )
309
+ // .hook(
310
+ // 'preAction',
311
+ // ifOptions(
312
+ // (opts) => !opts.from && !opts.to,
313
+ // () => exitWith(1, 'At least one source (from) or destination (to) option must be provided')
314
+ // )
315
+ // )
316
+ // .addOption(forceOption)
317
+ // .addOption(excludeOption)
318
+ // .addOption(onlyOption)
319
+ // .hook('preAction', validateExcludeOnly)
320
+ // .hook(
321
+ // 'preAction',
322
+ // confirmMessage(
323
+ // 'The import will delete all data in the remote database. Are you sure you want to proceed?'
324
+ // )
325
+ // )
326
+ // .action(getLocalScript('transfer/transfer'));
327
+ // }
325
328
 
326
329
  // `$ strapi export`
327
330
  program
@@ -385,6 +388,35 @@ program
385
388
  }
386
389
  }
387
390
  })
391
+ // set decrypt and decompress options based on filename
392
+ .hook('preAction', (thisCommand) => {
393
+ const opts = thisCommand.opts();
394
+
395
+ const { extname, parse } = path;
396
+
397
+ let file = opts.file;
398
+
399
+ if (extname(file) === '.enc') {
400
+ file = parse(file).name; // trim the .enc extension
401
+ thisCommand.opts().decrypt = true;
402
+ } else {
403
+ thisCommand.opts().decrypt = false;
404
+ }
405
+
406
+ if (extname(file) === '.gz') {
407
+ file = parse(file).name; // trim the .gz extension
408
+ thisCommand.opts().decompress = true;
409
+ } else {
410
+ thisCommand.opts().decompress = false;
411
+ }
412
+
413
+ if (extname(file) !== '.tar') {
414
+ exitWith(
415
+ 1,
416
+ `The file '${opts.file}' does not appear to be a valid Strapi data file. It must have an extension ending in .tar[.gz][.enc]`
417
+ );
418
+ }
419
+ })
388
420
  .hook(
389
421
  'preAction',
390
422
  confirmMessage(
package/ee/ee-store.js ADDED
@@ -0,0 +1,18 @@
1
+ 'use strict';
2
+
3
+ const eeStoreModel = {
4
+ uid: 'strapi::ee-store',
5
+ collectionName: 'strapi_ee_store_settings',
6
+ attributes: {
7
+ key: {
8
+ type: 'string',
9
+ },
10
+ value: {
11
+ type: 'text',
12
+ },
13
+ },
14
+ };
15
+
16
+ module.exports = {
17
+ eeStoreModel,
18
+ };
package/ee/index.js ADDED
@@ -0,0 +1,173 @@
1
+ 'use strict';
2
+
3
+ const { pick } = require('lodash/fp');
4
+
5
+ const { readLicense, verifyLicense, fetchLicense, LicenseCheckError } = require('./license');
6
+ const { eeStoreModel } = require('./ee-store');
7
+ const { shiftCronExpression } = require('../lib/utils/cron');
8
+
9
+ const ONE_MINUTE = 1000 * 60;
10
+
11
+ const ee = {
12
+ enabled: false,
13
+ licenseInfo: {},
14
+ };
15
+
16
+ const disable = (message) => {
17
+ ee.logger?.warn(`${message} Switching to CE.`);
18
+ // Only keep the license key for potential re-enabling during a later check
19
+ ee.licenseInfo = pick('licenseKey', ee.licenseInfo);
20
+ ee.enabled = false;
21
+ };
22
+
23
+ let initialized = false;
24
+
25
+ /**
26
+ * Optimistically enable EE if the format of the license is valid, only run once.
27
+ */
28
+ const init = (licenseDir, logger) => {
29
+ if (initialized) {
30
+ return;
31
+ }
32
+
33
+ initialized = true;
34
+ ee.logger = logger;
35
+
36
+ if (process.env.STRAPI_DISABLE_EE?.toLowerCase() === 'true') {
37
+ return;
38
+ }
39
+
40
+ try {
41
+ const license = process.env.STRAPI_LICENSE || readLicense(licenseDir);
42
+
43
+ if (license) {
44
+ ee.licenseInfo = verifyLicense(license);
45
+ ee.enabled = true;
46
+ }
47
+ } catch (error) {
48
+ disable(error.message);
49
+ }
50
+ };
51
+
52
+ /**
53
+ * Contact the license registry to update the license to its latest state.
54
+ *
55
+ * Store the result in database to avoid unecessary requests, and will fallback to that in case of a network failure.
56
+ */
57
+ const onlineUpdate = async ({ strapi }) => {
58
+ const { get, commit, rollback } = await strapi.db.transaction();
59
+ const transaction = get();
60
+
61
+ try {
62
+ const storedInfo = await strapi.db
63
+ .queryBuilder(eeStoreModel.uid)
64
+ .where({ key: 'ee_information' })
65
+ .select('value')
66
+ .first()
67
+ .transacting(transaction)
68
+ .forUpdate()
69
+ .execute()
70
+ .then((result) => (result ? JSON.parse(result.value) : result));
71
+
72
+ const shouldContactRegistry = (storedInfo?.lastCheckAt ?? 0) < Date.now() - ONE_MINUTE;
73
+ const result = { lastCheckAt: Date.now() };
74
+
75
+ const fallback = (error) => {
76
+ if (error instanceof LicenseCheckError && error.shouldFallback && storedInfo?.license) {
77
+ ee.logger?.warn(
78
+ `${error.message} The last stored one will be used as a potential fallback.`
79
+ );
80
+ return storedInfo.license;
81
+ }
82
+
83
+ result.error = error.message;
84
+ disable(error.message);
85
+ };
86
+
87
+ const license = shouldContactRegistry
88
+ ? await fetchLicense(ee.licenseInfo.licenseKey, strapi.config.get('uuid')).catch(fallback)
89
+ : storedInfo.license;
90
+
91
+ if (license) {
92
+ try {
93
+ ee.licenseInfo = verifyLicense(license);
94
+ validateInfo();
95
+ } catch (error) {
96
+ disable(error.message);
97
+ }
98
+ } else if (!shouldContactRegistry) {
99
+ disable(storedInfo.error);
100
+ }
101
+
102
+ if (shouldContactRegistry) {
103
+ result.license = license ?? null;
104
+ const query = strapi.db.queryBuilder(eeStoreModel.uid).transacting(transaction);
105
+
106
+ if (!storedInfo) {
107
+ query.insert({ key: 'ee_information', value: JSON.stringify(result) });
108
+ } else {
109
+ query.update({ value: JSON.stringify(result) }).where({ key: 'ee_information' });
110
+ }
111
+
112
+ await query.execute();
113
+ }
114
+
115
+ await commit();
116
+ } catch (error) {
117
+ // Example of errors: SQLite does not support FOR UPDATE
118
+ await rollback();
119
+ }
120
+ };
121
+
122
+ const validateInfo = () => {
123
+ const expirationTime = new Date(ee.licenseInfo.expireAt).getTime();
124
+
125
+ if (expirationTime < new Date().getTime()) {
126
+ return disable('License expired.');
127
+ }
128
+
129
+ ee.enabled = true;
130
+ };
131
+
132
+ const checkLicense = async ({ strapi }) => {
133
+ const shouldStayOffline =
134
+ ee.licenseInfo.type === 'gold' &&
135
+ // This env variable support is temporarily used to ease the migration between online vs offline
136
+ process.env.STRAPI_DISABLE_LICENSE_PING?.toLowerCase() === 'true';
137
+
138
+ if (!shouldStayOffline) {
139
+ await onlineUpdate({ strapi });
140
+ strapi.cron.add({ [shiftCronExpression('0 0 */12 * * *')]: onlineUpdate });
141
+ } else {
142
+ if (!ee.licenseInfo.expireAt) {
143
+ return disable('Your license does not have offline support.');
144
+ }
145
+
146
+ validateInfo();
147
+ }
148
+ };
149
+
150
+ const list = () => {
151
+ return (
152
+ ee.licenseInfo.features?.map((feature) =>
153
+ typeof feature === 'object' ? feature : { name: feature }
154
+ ) || []
155
+ );
156
+ };
157
+
158
+ const get = (featureName) => list().find((feature) => feature.name === featureName);
159
+
160
+ module.exports = Object.freeze({
161
+ init,
162
+ checkLicense,
163
+
164
+ get isEE() {
165
+ return ee.enabled;
166
+ },
167
+
168
+ features: Object.freeze({
169
+ list,
170
+ get,
171
+ isEnabled: (featureName) => get(featureName) !== undefined,
172
+ }),
173
+ });
package/ee/license.js ADDED
@@ -0,0 +1,102 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const { join } = require('path');
5
+ const crypto = require('crypto');
6
+ const fetch = require('node-fetch');
7
+
8
+ const machineId = require('../lib/utils/machine-id');
9
+
10
+ const DEFAULT_FEATURES = {
11
+ bronze: [],
12
+ silver: [],
13
+ gold: ['sso', { name: 'audit-logs', options: { retentionDays: 90 } }],
14
+ };
15
+
16
+ const publicKey = fs.readFileSync(join(__dirname, 'resources/key.pub'));
17
+
18
+ class LicenseCheckError extends Error {
19
+ constructor(message, shouldFallback = false) {
20
+ super(message);
21
+
22
+ this.shouldFallback = shouldFallback;
23
+ }
24
+ }
25
+
26
+ const readLicense = (directory) => {
27
+ try {
28
+ const path = join(directory, 'license.txt');
29
+ return fs.readFileSync(path).toString();
30
+ } catch (error) {
31
+ if (error.code !== 'ENOENT') {
32
+ throw Error('License file not readable, review its format and access rules.');
33
+ }
34
+ }
35
+ };
36
+
37
+ const verifyLicense = (license) => {
38
+ const [signature, base64Content] = Buffer.from(license, 'base64').toString().split('\n');
39
+
40
+ if (!signature || !base64Content) {
41
+ throw new Error('Invalid license.');
42
+ }
43
+
44
+ const stringifiedContent = Buffer.from(base64Content, 'base64').toString();
45
+
46
+ const verify = crypto.createVerify('RSA-SHA256');
47
+ verify.update(stringifiedContent);
48
+ verify.end();
49
+
50
+ const verified = verify.verify(publicKey, signature, 'base64');
51
+
52
+ if (!verified) {
53
+ throw new Error('Invalid license.');
54
+ }
55
+
56
+ const licenseInfo = JSON.parse(stringifiedContent);
57
+
58
+ if (!licenseInfo.features) {
59
+ licenseInfo.features = DEFAULT_FEATURES[licenseInfo.type];
60
+ }
61
+
62
+ Object.freeze(licenseInfo.features);
63
+ return licenseInfo;
64
+ };
65
+
66
+ const throwError = () => {
67
+ throw new LicenseCheckError('Could not proceed to the online validation of your license.', true);
68
+ };
69
+
70
+ const fetchLicense = async (key, projectId) => {
71
+ const response = await fetch(`https://license.strapi.io/api/licenses/validate`, {
72
+ method: 'POST',
73
+ headers: { 'Content-Type': 'application/json' },
74
+ body: JSON.stringify({ key, projectId, deviceId: machineId() }),
75
+ }).catch(throwError);
76
+
77
+ const contentType = response.headers.get('Content-Type');
78
+
79
+ if (contentType.includes('application/json')) {
80
+ const { data, error } = await response.json();
81
+
82
+ switch (response.status) {
83
+ case 200:
84
+ return data.license;
85
+ case 400:
86
+ throw new LicenseCheckError(error.message);
87
+ case 404:
88
+ throw new LicenseCheckError('The license used does not exists.');
89
+ default:
90
+ throwError();
91
+ }
92
+ } else {
93
+ throwError();
94
+ }
95
+ };
96
+
97
+ module.exports = Object.freeze({
98
+ readLicense,
99
+ verifyLicense,
100
+ fetchLicense,
101
+ LicenseCheckError,
102
+ });
File without changes
package/lib/Strapi.js CHANGED
@@ -17,6 +17,7 @@ const { createServer } = require('./services/server');
17
17
  const createWebhookRunner = require('./services/webhook-runner');
18
18
  const { webhookModel, createWebhookStore } = require('./services/webhook-store');
19
19
  const { createCoreStore, coreStoreModel } = require('./services/core-store');
20
+ const { eeStoreModel } = require('../ee/ee-store');
20
21
  const createEntityService = require('./services/entity-service');
21
22
  const createCronService = require('./services/cron');
22
23
  const entityValidator = require('./services/entity-validator');
@@ -120,16 +121,20 @@ class Strapi {
120
121
  this.customFields = createCustomFields(this);
121
122
 
122
123
  createUpdateNotifier(this).notify();
124
+
125
+ Object.defineProperty(this, 'EE', {
126
+ get: () => {
127
+ ee.init(this.dirs.app.root, this.log);
128
+ return ee.isEE;
129
+ },
130
+ configurable: false,
131
+ });
123
132
  }
124
133
 
125
134
  get config() {
126
135
  return this.container.get('config');
127
136
  }
128
137
 
129
- get EE() {
130
- return ee({ dir: this.dirs.app.root, logger: this.log });
131
- }
132
-
133
138
  get services() {
134
139
  return this.container.get('services').getAll();
135
140
  }
@@ -404,6 +409,7 @@ class Strapi {
404
409
  const contentTypes = [
405
410
  coreStoreModel,
406
411
  webhookModel,
412
+ eeStoreModel,
407
413
  ...Object.values(strapi.contentTypes),
408
414
  ...Object.values(strapi.components),
409
415
  ];
@@ -447,6 +453,10 @@ class Strapi {
447
453
 
448
454
  await this.db.schema.sync();
449
455
 
456
+ if (this.EE) {
457
+ await ee.checkLicense({ strapi: this });
458
+ }
459
+
450
460
  await this.hook('strapi::content-types.afterSync').call({
451
461
  oldContentTypes,
452
462
  contentTypes: strapi.contentTypes,
@@ -30,7 +30,7 @@ module.exports = async ({ buildDestDir, forceBuild = true, optimization, srcDir
30
30
  // Always remove the .cache and build folders
31
31
  await strapiAdmin.clean({ appDir: srcDir, buildDestDir });
32
32
 
33
- ee({ dir: srcDir });
33
+ ee.init(srcDir);
34
34
 
35
35
  return strapiAdmin
36
36
  .build({
@@ -11,15 +11,17 @@ const { isObject, isString, isFinite, toNumber } = require('lodash/fp');
11
11
  const fs = require('fs-extra');
12
12
  const chalk = require('chalk');
13
13
 
14
+ const { TransferEngineTransferError } = require('@strapi/data-transfer/lib/engine/errors');
14
15
  const {
15
16
  getDefaultExportName,
16
17
  buildTransferTable,
17
18
  DEFAULT_IGNORED_CONTENT_TYPES,
18
19
  createStrapiInstance,
20
+ formatDiagnostic,
19
21
  } = require('./utils');
20
22
 
21
23
  /**
22
- * @typedef ImportCommandOptions Options given to the CLI import command
24
+ * @typedef ExportCommandOptions Options given to the CLI import command
23
25
  *
24
26
  * @property {string} [file] The file path to import
25
27
  * @property {boolean} [encrypt] Used to encrypt the final archive
@@ -32,11 +34,11 @@ const logger = console;
32
34
  const BYTES_IN_MB = 1024 * 1024;
33
35
 
34
36
  /**
35
- * Import command.
37
+ * Export command.
36
38
  *
37
- * It transfers data from a local file to a local strapi instance
39
+ * It transfers data from a local Strapi instance to a file
38
40
  *
39
- * @param {ImportCommandOptions} opts
41
+ * @param {ExportCommandOptions} opts
40
42
  */
41
43
  module.exports = async (opts) => {
42
44
  // Validate inputs from Commander
@@ -76,6 +78,8 @@ module.exports = async (opts) => {
76
78
  },
77
79
  });
78
80
 
81
+ engine.diagnostics.onDiagnostic(formatDiagnostic('export'));
82
+
79
83
  const progress = engine.progress.stream;
80
84
 
81
85
  const getTelemetryPayload = (/* payload */) => {
@@ -101,14 +105,14 @@ module.exports = async (opts) => {
101
105
 
102
106
  const outFileExists = await fs.pathExists(outFile);
103
107
  if (!outFileExists) {
104
- throw new Error(`Export file not created "${outFile}"`);
108
+ throw new TransferEngineTransferError(`Export file not created "${outFile}"`);
105
109
  }
106
110
 
107
111
  logger.log(`${chalk.bold('Export process has been completed successfully!')}`);
108
112
  logger.log(`Export archive is in ${chalk.green(outFile)}`);
109
- } catch (e) {
113
+ } catch {
110
114
  await strapi.telemetry.send('didDEITSProcessFail', getTelemetryPayload());
111
- logger.error('Export process failed unexpectedly:', e.toString());
115
+ logger.error('Export process failed.');
112
116
  process.exit(1);
113
117
  }
114
118
 
@@ -131,7 +135,7 @@ const createSourceProvider = (strapi) => {
131
135
  /**
132
136
  * It creates a local file destination provider based on the given options
133
137
  *
134
- * @param {ImportCommandOptions} opts
138
+ * @param {ExportCommandOptions} opts
135
139
  */
136
140
  const createDestinationProvider = (opts) => {
137
141
  const { file, compress, encrypt, key, maxSizeJsonl } = opts;
@@ -13,10 +13,13 @@ const {
13
13
  } = require('@strapi/data-transfer/lib/engine');
14
14
 
15
15
  const { isObject } = require('lodash/fp');
16
- const path = require('path');
17
16
 
18
- const strapi = require('../../index');
19
- const { buildTransferTable, DEFAULT_IGNORED_CONTENT_TYPES } = require('./utils');
17
+ const {
18
+ buildTransferTable,
19
+ DEFAULT_IGNORED_CONTENT_TYPES,
20
+ createStrapiInstance,
21
+ formatDiagnostic,
22
+ } = require('./utils');
20
23
 
21
24
  /**
22
25
  * @typedef {import('@strapi/data-transfer').ILocalFileSourceProviderOptions} ILocalFileSourceProviderOptions
@@ -41,7 +44,7 @@ module.exports = async (opts) => {
41
44
  /**
42
45
  * To local Strapi instance
43
46
  */
44
- const strapiInstance = await strapi(await strapi.compile()).load();
47
+ const strapiInstance = await createStrapiInstance();
45
48
 
46
49
  const destinationOptions = {
47
50
  async getStrapi() {
@@ -84,6 +87,8 @@ module.exports = async (opts) => {
84
87
 
85
88
  const engine = createTransferEngine(source, destination, engineOptions);
86
89
 
90
+ engine.diagnostics.onDiagnostic(formatDiagnostic('import'));
91
+
87
92
  const progress = engine.progress.stream;
88
93
  const getTelemetryPayload = () => {
89
94
  return {
@@ -107,8 +112,7 @@ module.exports = async (opts) => {
107
112
  logger.info('Import process has been completed successfully!');
108
113
  } catch (e) {
109
114
  await strapiInstance.telemetry.send('didDEITSProcessFail', getTelemetryPayload());
110
- logger.error('Import process failed unexpectedly:');
111
- logger.error(e);
115
+ logger.error('Import process failed.');
112
116
  process.exit(1);
113
117
  }
114
118
 
@@ -132,23 +136,9 @@ const getLocalFileSourceOptions = (opts) => {
132
136
  */
133
137
  const options = {
134
138
  file: { path: opts.file },
135
- compression: { enabled: false },
136
- encryption: { enabled: false },
139
+ compression: { enabled: !!opts.decompress },
140
+ encryption: { enabled: !!opts.decrypt, key: opts.key },
137
141
  };
138
142
 
139
- const { extname, parse } = path;
140
-
141
- let file = options.file.path;
142
-
143
- if (extname(file) === '.enc') {
144
- file = parse(file).name;
145
- options.encryption = { enabled: true, key: opts.key };
146
- }
147
-
148
- if (extname(file) === '.gz') {
149
- file = parse(file).name;
150
- options.compression = { enabled: true };
151
- }
152
-
153
143
  return options;
154
144
  };