@akemona-org/strapi 3.7.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.
Files changed (125) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +163 -0
  3. package/bin/strapi.js +239 -0
  4. package/index.d.ts +13 -0
  5. package/lib/Strapi.js +498 -0
  6. package/lib/commands/admin-reset.js +51 -0
  7. package/lib/commands/build.js +47 -0
  8. package/lib/commands/configurationDump.js +50 -0
  9. package/lib/commands/configurationRestore.js +160 -0
  10. package/lib/commands/console.js +26 -0
  11. package/lib/commands/develop.js +155 -0
  12. package/lib/commands/generate-template.js +97 -0
  13. package/lib/commands/generate.js +66 -0
  14. package/lib/commands/install.js +48 -0
  15. package/lib/commands/new.js +11 -0
  16. package/lib/commands/start.js +8 -0
  17. package/lib/commands/uninstall.js +68 -0
  18. package/lib/commands/watchAdmin.js +35 -0
  19. package/lib/core/app-configuration/config-loader.js +56 -0
  20. package/lib/core/app-configuration/config-provider.js +28 -0
  21. package/lib/core/app-configuration/index.js +99 -0
  22. package/lib/core/bootstrap.js +166 -0
  23. package/lib/core/fs.js +52 -0
  24. package/lib/core/index.js +21 -0
  25. package/lib/core/load-admin.js +36 -0
  26. package/lib/core/load-apis.js +22 -0
  27. package/lib/core/load-components.js +43 -0
  28. package/lib/core/load-extensions.js +71 -0
  29. package/lib/core/load-functions.js +21 -0
  30. package/lib/core/load-hooks.js +117 -0
  31. package/lib/core/load-middlewares.js +130 -0
  32. package/lib/core/load-modules.js +61 -0
  33. package/lib/core/load-plugins.js +68 -0
  34. package/lib/core/load-policies.js +36 -0
  35. package/lib/core/walk.js +27 -0
  36. package/lib/core-api/controller.js +158 -0
  37. package/lib/core-api/index.js +33 -0
  38. package/lib/core-api/service/collection-type.js +122 -0
  39. package/lib/core-api/service/index.js +81 -0
  40. package/lib/core-api/service/single-type.js +68 -0
  41. package/lib/hooks/index.js +97 -0
  42. package/lib/index.js +3 -0
  43. package/lib/load/check-reserved-filename.js +18 -0
  44. package/lib/load/filepath-to-prop-path.js +22 -0
  45. package/lib/load/glob.js +15 -0
  46. package/lib/load/index.js +9 -0
  47. package/lib/load/load-config-files.js +22 -0
  48. package/lib/load/load-files.js +56 -0
  49. package/lib/load/package-path.js +9 -0
  50. package/lib/load/require-file-parse.js +15 -0
  51. package/lib/middlewares/boom/defaults.json +5 -0
  52. package/lib/middlewares/boom/index.js +147 -0
  53. package/lib/middlewares/cors/index.js +66 -0
  54. package/lib/middlewares/cron/defaults.json +5 -0
  55. package/lib/middlewares/cron/index.js +43 -0
  56. package/lib/middlewares/csp/defaults.json +5 -0
  57. package/lib/middlewares/csp/index.js +26 -0
  58. package/lib/middlewares/favicon/defaults.json +7 -0
  59. package/lib/middlewares/favicon/index.js +35 -0
  60. package/lib/middlewares/gzip/defaults.json +6 -0
  61. package/lib/middlewares/gzip/index.js +19 -0
  62. package/lib/middlewares/hsts/defaults.json +7 -0
  63. package/lib/middlewares/hsts/index.js +30 -0
  64. package/lib/middlewares/index.js +120 -0
  65. package/lib/middlewares/ip/defaults.json +7 -0
  66. package/lib/middlewares/ip/index.js +25 -0
  67. package/lib/middlewares/language/defaults.json +9 -0
  68. package/lib/middlewares/language/index.js +40 -0
  69. package/lib/middlewares/logger/defaults.json +8 -0
  70. package/lib/middlewares/logger/index.js +63 -0
  71. package/lib/middlewares/p3p/defaults.json +6 -0
  72. package/lib/middlewares/p3p/index.js +29 -0
  73. package/lib/middlewares/parser/defaults.json +10 -0
  74. package/lib/middlewares/parser/index.js +71 -0
  75. package/lib/middlewares/poweredBy/defaults.json +5 -0
  76. package/lib/middlewares/poweredBy/index.js +16 -0
  77. package/lib/middlewares/public/assets/images/group_people_1.png +0 -0
  78. package/lib/middlewares/public/assets/images/group_people_2.png +0 -0
  79. package/lib/middlewares/public/assets/images/group_people_3.png +0 -0
  80. package/lib/middlewares/public/assets/images/logo_login.png +0 -0
  81. package/lib/middlewares/public/defaults.json +8 -0
  82. package/lib/middlewares/public/index.html +66 -0
  83. package/lib/middlewares/public/index.js +98 -0
  84. package/lib/middlewares/public/serve-static.js +23 -0
  85. package/lib/middlewares/responseTime/defaults.json +5 -0
  86. package/lib/middlewares/responseTime/index.js +25 -0
  87. package/lib/middlewares/responses/defaults.json +5 -0
  88. package/lib/middlewares/responses/index.js +18 -0
  89. package/lib/middlewares/router/defaults.json +7 -0
  90. package/lib/middlewares/router/index.js +64 -0
  91. package/lib/middlewares/router/utils/composeEndpoint.js +25 -0
  92. package/lib/middlewares/router/utils/routerChecker.js +92 -0
  93. package/lib/middlewares/session/defaults.json +18 -0
  94. package/lib/middlewares/session/index.js +140 -0
  95. package/lib/middlewares/xframe/defaults.json +6 -0
  96. package/lib/middlewares/xframe/index.js +33 -0
  97. package/lib/middlewares/xss/defaults.json +6 -0
  98. package/lib/middlewares/xss/index.js +30 -0
  99. package/lib/services/core-store.js +144 -0
  100. package/lib/services/entity-service.js +260 -0
  101. package/lib/services/entity-validator/index.js +199 -0
  102. package/lib/services/entity-validator/validators.js +125 -0
  103. package/lib/services/event-hub.js +15 -0
  104. package/lib/services/metrics/index.js +103 -0
  105. package/lib/services/metrics/is-truthy.js +9 -0
  106. package/lib/services/metrics/middleware.js +33 -0
  107. package/lib/services/metrics/rate-limiter.js +27 -0
  108. package/lib/services/metrics/sender.js +76 -0
  109. package/lib/services/metrics/stringify-deep.js +22 -0
  110. package/lib/services/utils/upload-files.js +70 -0
  111. package/lib/services/webhook-runner.js +159 -0
  112. package/lib/services/webhook-store.js +97 -0
  113. package/lib/services/worker-queue.js +58 -0
  114. package/lib/utils/addSlash.js +10 -0
  115. package/lib/utils/ee.js +123 -0
  116. package/lib/utils/get-prefixed-dependencies.js +7 -0
  117. package/lib/utils/index.js +25 -0
  118. package/lib/utils/openBrowser.js +145 -0
  119. package/lib/utils/resources/key.pub +9 -0
  120. package/lib/utils/resources/openChrome.applescript +83 -0
  121. package/lib/utils/run-checks.js +37 -0
  122. package/lib/utils/success.js +31 -0
  123. package/lib/utils/update-notifier/index.js +96 -0
  124. package/lib/utils/url-from-segments.js +13 -0
  125. package/package.json +143 -0
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Webhook store is the implementation of webhook storage over the core_store
3
+ */
4
+ 'use strict';
5
+
6
+ const webhookModel = config => ({
7
+ connection: config.get('database.defaultConnection'),
8
+ uid: 'strapi::webhooks',
9
+ globalId: 'StrapiWebhooks',
10
+ collectionName: 'strapi_webhooks',
11
+ info: {
12
+ name: 'Strapi webhooks',
13
+ description: '',
14
+ },
15
+ pluginOptions: {
16
+ 'content-manager': {
17
+ visible: false,
18
+ },
19
+ 'content-type-builder': {
20
+ visible: false,
21
+ },
22
+ },
23
+ attributes: {
24
+ name: {
25
+ type: 'string',
26
+ },
27
+ url: {
28
+ type: 'text',
29
+ },
30
+ headers: {
31
+ type: 'json',
32
+ },
33
+ events: {
34
+ type: 'json',
35
+ },
36
+ enabled: {
37
+ type: 'boolean',
38
+ },
39
+ },
40
+ });
41
+
42
+ const toDBObject = data => {
43
+ return {
44
+ name: data.name,
45
+ url: data.url,
46
+ headers: data.headers,
47
+ events: data.events,
48
+ enabled: data.isEnabled,
49
+ };
50
+ };
51
+
52
+ const fromDBObject = row => {
53
+ return {
54
+ id: row.id,
55
+ name: row.name,
56
+ url: row.url,
57
+ headers: row.headers,
58
+ events: row.events,
59
+ isEnabled: row.enabled,
60
+ };
61
+ };
62
+
63
+ const createWebhookStore = ({ db }) => {
64
+ const webhookQueries = db.query('strapi_webhooks');
65
+
66
+ return {
67
+ async findWebhooks() {
68
+ const results = await webhookQueries.find();
69
+
70
+ return results.map(fromDBObject);
71
+ },
72
+
73
+ async findWebhook(id) {
74
+ const result = await webhookQueries.findOne({ id });
75
+ return result ? fromDBObject(result) : null;
76
+ },
77
+
78
+ createWebhook(data) {
79
+ return webhookQueries.create(toDBObject({ ...data, isEnabled: true })).then(fromDBObject);
80
+ },
81
+
82
+ async updateWebhook(id, data) {
83
+ const webhook = await webhookQueries.update({ id }, toDBObject(data));
84
+ return webhook ? fromDBObject(webhook) : null;
85
+ },
86
+
87
+ async deleteWebhook(id) {
88
+ const webhook = await webhookQueries.delete({ id });
89
+ return webhook ? fromDBObject(webhook) : null;
90
+ },
91
+ };
92
+ };
93
+
94
+ module.exports = {
95
+ webhookModel,
96
+ createWebhookStore,
97
+ };
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Simple worker queue in memory
3
+ */
4
+ 'use strict';
5
+
6
+ const debug = require('debug')('strapi:worker-queue');
7
+
8
+ module.exports = class WorkerQueue {
9
+ constructor({ logger, concurrency = 5 } = {}) {
10
+ debug('Initialize worker queue');
11
+
12
+ this.logger = logger;
13
+ this.worker = noop;
14
+
15
+ this.concurrency = concurrency;
16
+ this.running = 0;
17
+ this.queue = [];
18
+ }
19
+
20
+ subscribe(worker) {
21
+ debug('Subscribe to worker queue');
22
+ this.worker = worker;
23
+ }
24
+
25
+ enqueue(payload) {
26
+ debug('Enqueue event in worker queue');
27
+ if (this.running < this.concurrency) {
28
+ this.running++;
29
+ this.execute(payload);
30
+ } else {
31
+ this.queue.unshift(payload);
32
+ }
33
+ }
34
+
35
+ pop() {
36
+ debug('Pop worker queue and execute');
37
+ const payload = this.queue.pop();
38
+
39
+ if (payload) {
40
+ this.execute(payload);
41
+ } else {
42
+ this.running--;
43
+ }
44
+ }
45
+
46
+ async execute(payload) {
47
+ debug('Execute worker');
48
+ try {
49
+ await this.worker(payload);
50
+ } catch (error) {
51
+ this.logger.error(error);
52
+ } finally {
53
+ this.pop();
54
+ }
55
+ }
56
+ };
57
+
58
+ function noop() {}
@@ -0,0 +1,10 @@
1
+ 'use strict';
2
+
3
+ module.exports = path => {
4
+ if (typeof path !== 'string') throw new Error('admin.url must be a string');
5
+ if (path === '' || path === '/') return '/';
6
+
7
+ if (path[0] != '/') path = '/' + path;
8
+ if (path[path.length - 1] != '/') path = path + '/';
9
+ return path;
10
+ };
@@ -0,0 +1,123 @@
1
+ 'use strict';
2
+
3
+ const path = require('path');
4
+ const fs = require('fs');
5
+ const crypto = require('crypto');
6
+ const _ = require('lodash');
7
+
8
+ const publicKey = fs.readFileSync(path.join(__dirname, '../utils/resources/key.pub'));
9
+
10
+ const noop = () => {};
11
+
12
+ const noLog = {
13
+ warn: noop,
14
+ info: noop,
15
+ };
16
+
17
+ const internals = {};
18
+ const features = {
19
+ bronze: [],
20
+ silver: [],
21
+ gold: ['sso'],
22
+ };
23
+
24
+ module.exports = ({ dir, logger = noLog }) => {
25
+ if (_.has(internals, 'isEE')) return internals.isEE;
26
+
27
+ const warnAndReturn = (msg = 'Invalid license. Starting in CE.') => {
28
+ logger.warn(msg);
29
+ internals.isEE = false;
30
+ return false;
31
+ };
32
+
33
+ if (process.env.STRAPI_DISABLE_EE === 'true') {
34
+ internals.isEE = false;
35
+ return false;
36
+ }
37
+
38
+ const licensePath = path.join(dir, 'license.txt');
39
+
40
+ let license;
41
+ if (_.has(process.env, 'STRAPI_LICENSE')) {
42
+ license = process.env.STRAPI_LICENSE;
43
+ } else if (fs.existsSync(licensePath)) {
44
+ license = fs.readFileSync(licensePath).toString();
45
+ }
46
+
47
+ if (_.isNil(license)) {
48
+ internals.isEE = false;
49
+ return false;
50
+ }
51
+
52
+ try {
53
+ const plainLicense = Buffer.from(license, 'base64').toString();
54
+ const [signatureb64, contentb64] = plainLicense.split('\n');
55
+
56
+ const signature = Buffer.from(signatureb64, 'base64');
57
+ const content = Buffer.from(contentb64, 'base64').toString();
58
+
59
+ const verifier = crypto.createVerify('RSA-SHA256');
60
+ verifier.update(content);
61
+ verifier.end();
62
+
63
+ const isValid = verifier.verify(publicKey, signature);
64
+ if (!isValid) return warnAndReturn();
65
+
66
+ internals.licenseInfo = JSON.parse(content);
67
+
68
+ const expirationTime = new Date(internals.licenseInfo.expireAt).getTime();
69
+ if (expirationTime < new Date().getTime()) {
70
+ return warnAndReturn('License expired. Starting in CE');
71
+ }
72
+ } catch (err) {
73
+ return warnAndReturn();
74
+ }
75
+
76
+ internals.isEE = true;
77
+ return true;
78
+ };
79
+
80
+ Object.defineProperty(module.exports, 'licenseInfo', {
81
+ get: () => {
82
+ mustHaveKey('licenseInfo');
83
+ return internals.licenseInfo;
84
+ },
85
+ configurable: false,
86
+ enumerable: false,
87
+ });
88
+
89
+ Object.defineProperty(module.exports, 'isEE', {
90
+ get: () => {
91
+ mustHaveKey('isEE');
92
+ return internals.isEE;
93
+ },
94
+ configurable: false,
95
+ enumerable: false,
96
+ });
97
+
98
+ Object.defineProperty(module.exports, 'features', {
99
+ get: () => {
100
+ mustHaveKey('licenseInfo');
101
+
102
+ const { type: licenseType } = module.exports.licenseInfo;
103
+
104
+ return {
105
+ isEnabled(feature) {
106
+ return features[licenseType].includes(feature);
107
+ },
108
+ getEnabled() {
109
+ return features[licenseType];
110
+ },
111
+ };
112
+ },
113
+ configurable: false,
114
+ enumerable: false,
115
+ });
116
+
117
+ const mustHaveKey = key => {
118
+ if (!_.has(internals, key)) {
119
+ const err = new Error('Tampering with license');
120
+ err.stack = null;
121
+ throw err;
122
+ }
123
+ };
@@ -0,0 +1,7 @@
1
+ 'use strict';
2
+
3
+ module.exports = (prefix, pkgJSON) => {
4
+ return Object.keys(pkgJSON.dependencies)
5
+ .filter(d => d.startsWith(prefix) && d.length > prefix.length)
6
+ .map(pkgName => pkgName.substring(prefix.length + 1));
7
+ };
@@ -0,0 +1,25 @@
1
+ 'use strict';
2
+
3
+ // Dependencies.
4
+ const { isEmpty } = require('lodash');
5
+ const openBrowser = require('./openBrowser');
6
+
7
+ module.exports = {
8
+ /*
9
+ * Return false where there is no administrator, otherwise return true.
10
+ */
11
+ async isInitialised(strapi) {
12
+ try {
13
+ if (isEmpty(strapi.admin)) {
14
+ return true;
15
+ }
16
+
17
+ const numberOfAdministrators = await strapi.query('user', 'admin').find({ _limit: 1 });
18
+
19
+ return numberOfAdministrators.length > 0;
20
+ } catch (err) {
21
+ strapi.stopWithError(err);
22
+ }
23
+ },
24
+ openBrowser,
25
+ };
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Copyright (c) 2015-present, Facebook, Inc.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ 'use strict';
9
+
10
+ var execSync = require('child_process').execSync;
11
+ var chalk = require('chalk');
12
+ var spawn = require('cross-spawn');
13
+ var opn = require('opn');
14
+ const fetch = require('node-fetch');
15
+ const { getAbsoluteAdminUrl } = require('@akemona-org/strapi-utils');
16
+
17
+ // https://github.com/sindresorhus/opn#app
18
+ var OSX_CHROME = 'google chrome';
19
+
20
+ const Actions = Object.freeze({
21
+ NONE: 0,
22
+ BROWSER: 1,
23
+ SCRIPT: 2,
24
+ });
25
+
26
+ function getBrowserEnv() {
27
+ // Attempt to honor this environment variable.
28
+ // It is specific to the operating system.
29
+ // See https://github.com/sindresorhus/opn#app for documentation.
30
+ const value = process.env.BROWSER;
31
+ let action;
32
+ if (!value) {
33
+ // Default.
34
+ action = Actions.BROWSER;
35
+ } else if (value.toLowerCase().endsWith('.js')) {
36
+ action = Actions.SCRIPT;
37
+ } else if (value.toLowerCase() === 'none') {
38
+ action = Actions.NONE;
39
+ } else {
40
+ action = Actions.BROWSER;
41
+ }
42
+ return { action, value };
43
+ }
44
+
45
+ function executeNodeScript(scriptPath, url) {
46
+ const extraArgs = process.argv.slice(2);
47
+ const child = spawn('node', [scriptPath, ...extraArgs, url], {
48
+ stdio: 'inherit',
49
+ });
50
+ child.on('close', (code) => {
51
+ if (code !== 0) {
52
+ console.log();
53
+ console.log(chalk.red('The script specified as BROWSER environment variable failed.'));
54
+ console.log(`${chalk.cyan(scriptPath)} exited with code ${code}.`);
55
+ console.log();
56
+ return;
57
+ }
58
+ });
59
+ return true;
60
+ }
61
+
62
+ function startBrowserProcess(browser, url) {
63
+ // If we're on OS X, the user hasn't specifically
64
+ // requested a different browser, we can try opening
65
+ // Chrome with AppleScript. This lets us reuse an
66
+ // existing tab when possible instead of creating a new one.
67
+ const shouldTryOpenChromeWithAppleScript =
68
+ process.platform === 'darwin' && (typeof browser !== 'string' || browser === OSX_CHROME);
69
+
70
+ if (shouldTryOpenChromeWithAppleScript) {
71
+ try {
72
+ // Try our best to reuse existing tab
73
+ // on OS X Google Chrome with AppleScript
74
+ execSync('ps cax | grep "Google Chrome"');
75
+ execSync(`osascript resources/openChrome.applescript "${encodeURI(url)}"`, {
76
+ cwd: __dirname,
77
+ stdio: 'ignore',
78
+ });
79
+ return true;
80
+ } catch (err) {
81
+ strapi.log.error('Failed to open Google Chrome with AppleScript');
82
+ }
83
+ }
84
+
85
+ // Another special case: on OS X, check if BROWSER has been set to "open".
86
+ // In this case, instead of passing `open` to `opn` (which won't work),
87
+ // just ignore it (thus ensuring the intended behavior, i.e. opening the system browser):
88
+ // https://github.com/facebook/create-react-app/pull/1690#issuecomment-283518768
89
+ if (process.platform === 'darwin' && browser === 'open') {
90
+ browser = undefined;
91
+ }
92
+
93
+ // Fallback to opn
94
+ // (It will always open new tab)
95
+ try {
96
+ var options = { app: browser };
97
+ opn(url, options).catch(() => {}); // Prevent `unhandledRejection` error.
98
+ return true;
99
+ } catch (err) {
100
+ return false;
101
+ }
102
+ }
103
+
104
+ async function pingDashboard(url, multipleTime = false) {
105
+ try {
106
+ await fetch(url, { method: 'HEAD', timeout: 300, body: null });
107
+ // Inform the user that we're going to open the administration panel.
108
+ this.log.info('⏳ Opening the admin panel...');
109
+ } catch (e) {
110
+ if (e.code !== 'ECONNREFUSED' && e.type !== 'request-timeout') {
111
+ return console.error(e);
112
+ }
113
+
114
+ // Only display once.
115
+ if (!multipleTime) {
116
+ this.log.warn(`⚠️ The admin panel is unavailable... Impossible to open it in the browser.`);
117
+ }
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Reads the BROWSER evironment variable and decides what to do with it. Returns
123
+ * true if it opened a browser or ran a node.js script, otherwise false.
124
+ */
125
+ async function openBrowser() {
126
+ const url = getAbsoluteAdminUrl(strapi.config);
127
+
128
+ // Ping the dashboard to ensure it's available.
129
+ await pingDashboard.call(this, url);
130
+
131
+ const { action, value } = getBrowserEnv();
132
+ switch (action) {
133
+ case Actions.NONE:
134
+ // Special case: BROWSER="none" will prevent opening completely.
135
+ return false;
136
+ case Actions.SCRIPT:
137
+ return executeNodeScript(value, url);
138
+ case Actions.BROWSER:
139
+ return startBrowserProcess(value, url);
140
+ default:
141
+ throw new Error('Not implemented.');
142
+ }
143
+ }
144
+
145
+ module.exports = openBrowser;
@@ -0,0 +1,9 @@
1
+ -----BEGIN PUBLIC KEY-----
2
+ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApuI1XlPkYos3WsSeVPtS
3
+ l1Q2k8GnLEO5vFZ4EuSghMbqI+yE0tWVEaiptdV3KgERaALRXmH+IFrHqvSRjKQC
4
+ 1ORUarBU5ntWbNEr713R3K0BPOzz9OOoWHdk+Wmr4ViOTk0iD1u4bw/97RpyMoBm
5
+ +pXeBLHbEESK2kelk+LEmKUoY5nXp6KzZV5wxgD5QweZheU7mjXL5WMpIBJva8kp
6
+ RZMYXEF+uSZIep0q5FHEo2AazGUMAU3GjY/dpXisLmtleOa1xlKZmkvaXl/D2Mhb
7
+ BBqPbDMa72ToZg2J8K5UP9zXUP41FHr7o9rwSJ2uOkuZPg5nhDXeoVbrJwxP/U1M
8
+ nQIDAQAB
9
+ -----END PUBLIC KEY-----
@@ -0,0 +1,83 @@
1
+ (*
2
+ Copyright (c) 2015-present, Facebook, Inc.
3
+
4
+ This source code is licensed under the MIT license found in the
5
+ LICENSE file in the root directory of this source tree.
6
+ *)
7
+
8
+ property targetTab: null
9
+ property targetTabIndex: -1
10
+ property targetWindow: null
11
+
12
+ on run argv
13
+ set theURL to item 1 of argv
14
+
15
+ tell application "Chrome"
16
+
17
+ if (count every window) = 0 then
18
+ make new window
19
+ end if
20
+
21
+ -- 1: Looking for tab running debugger
22
+ -- then, Reload debugging tab if found
23
+ -- then return
24
+ set found to my lookupTabWithUrl(theURL)
25
+ if found then
26
+ set targetWindow's active tab index to targetTabIndex
27
+ tell targetTab to reload
28
+ tell targetWindow to activate
29
+ set index of targetWindow to 1
30
+ return
31
+ end if
32
+
33
+ -- 2: Looking for Empty tab
34
+ -- In case debugging tab was not found
35
+ -- We try to find an empty tab instead
36
+ set found to my lookupTabWithUrl("chrome://newtab/")
37
+ if found then
38
+ set targetWindow's active tab index to targetTabIndex
39
+ set URL of targetTab to theURL
40
+ tell targetWindow to activate
41
+ return
42
+ end if
43
+
44
+ -- 3: Create new tab
45
+ -- both debugging and empty tab were not found
46
+ -- make a new tab with url
47
+ tell window 1
48
+ activate
49
+ make new tab with properties {URL:theURL}
50
+ end tell
51
+ end tell
52
+ end run
53
+
54
+ -- Function:
55
+ -- Lookup tab with given url
56
+ -- if found, store tab, index, and window in properties
57
+ -- (properties were declared on top of file)
58
+ on lookupTabWithUrl(lookupUrl)
59
+ tell application "Chrome"
60
+ -- Find a tab with the given url
61
+ set found to false
62
+ set theTabIndex to -1
63
+ repeat with theWindow in every window
64
+ set theTabIndex to 0
65
+ repeat with theTab in every tab of theWindow
66
+ set theTabIndex to theTabIndex + 1
67
+ if (theTab's URL as string) contains lookupUrl then
68
+ -- assign tab, tab index, and window to properties
69
+ set targetTab to theTab
70
+ set targetTabIndex to theTabIndex
71
+ set targetWindow to theWindow
72
+ set found to true
73
+ exit repeat
74
+ end if
75
+ end repeat
76
+
77
+ if found then
78
+ exit repeat
79
+ end if
80
+ end repeat
81
+ end tell
82
+ return found
83
+ end lookupTabWithUrl
@@ -0,0 +1,37 @@
1
+ 'use strict';
2
+
3
+ const path = require('path');
4
+ const fs = require('fs-extra');
5
+ const _ = require('lodash');
6
+
7
+ const requiredPaths = ['api', 'extensions', 'plugins', 'config', 'public'];
8
+ const checkFoldersExist = ({ appPath }) => {
9
+ let missingPaths = [];
10
+ for (let reqPath of requiredPaths) {
11
+ if (!fs.pathExistsSync(path.resolve(appPath, reqPath))) {
12
+ missingPaths.push(reqPath);
13
+ }
14
+ }
15
+
16
+ if (missingPaths.length > 0) {
17
+ throw new Error(`Missing required folders:\n${missingPaths.map(p => `- ./${p}`).join('\n')}`);
18
+ }
19
+ };
20
+
21
+ const checkPluginsConflicts = ({ appPath, installedPlugins }) => {
22
+ const localPluginNames = fs.readdirSync(path.resolve(appPath, 'plugins'));
23
+ const pluginsIntersection = _.intersection(localPluginNames, installedPlugins);
24
+
25
+ if (pluginsIntersection.length > 0) {
26
+ throw new Error(
27
+ `You have some local plugins with the same name as npm installed plugins:\n${pluginsIntersection
28
+ .map(p => `- ${p}`)
29
+ .join('\n')}`
30
+ );
31
+ }
32
+ };
33
+
34
+ module.exports = config => {
35
+ checkFoldersExist(config);
36
+ checkPluginsConflicts(config);
37
+ };
@@ -0,0 +1,31 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Module dependencies
5
+ */
6
+
7
+ // const fetch = require('node-fetch');
8
+ // const { machineIdSync } = require('node-machine-id');
9
+
10
+ /*
11
+ * No need to worry about this file, we only retrieve anonymous data here.
12
+ * It allows us to know on how many times the package has been installed globally.
13
+ */
14
+
15
+ /* try {
16
+ if (
17
+ process.env.npm_config_global === 'true' ||
18
+ JSON.parse(process.env.npm_config_argv).original.includes('global')
19
+ ) {
20
+ fetch('https://analytics.strapi.io/track', {
21
+ method: 'POST',
22
+ body: JSON.stringify({
23
+ event: 'didInstallStrapi',
24
+ deviceId: machineIdSync(),
25
+ }),
26
+ headers: { 'Content-Type': 'application/json' },
27
+ }).catch(() => {});
28
+ }
29
+ } catch (e) {
30
+ //...
31
+ } */