apostrophe 3.16.0 → 3.17.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/.eslintignore +3 -1
- package/CHANGELOG.md +23 -1
- package/index.js +5 -4
- package/lib/moog.js +14 -1
- package/modules/@apostrophecms/area/ui/apos/components/AposAreaEditor.vue +3 -1
- package/modules/@apostrophecms/asset/index.js +213 -101
- package/modules/@apostrophecms/asset/lib/webpack/apos/webpack.config.js +3 -3
- package/modules/@apostrophecms/asset/lib/webpack/src/webpack.config.js +30 -12
- package/modules/@apostrophecms/asset/lib/webpack/src/webpack.es5.js +1 -1
- package/modules/@apostrophecms/asset/lib/webpack/src/webpack.scss.js +6 -2
- package/modules/@apostrophecms/asset/lib/webpack/utils.js +266 -0
- package/modules/@apostrophecms/asset/views/scripts.html +1 -0
- package/modules/@apostrophecms/asset/views/stylesheets.html +1 -0
- package/modules/@apostrophecms/doc/index.js +64 -0
- package/modules/@apostrophecms/doc-type/index.js +35 -0
- package/modules/@apostrophecms/i18n/i18n/en.json +2 -0
- package/modules/@apostrophecms/i18n/ui/apos/components/AposI18nLocalize.vue +7 -0
- package/modules/@apostrophecms/login/index.js +4 -0
- package/modules/@apostrophecms/schema/index.js +40 -49
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputObject.vue +67 -0
- package/modules/@apostrophecms/template/index.js +14 -5
- package/modules/@apostrophecms/template/lib/bundlesLoader.js +158 -0
- package/modules/@apostrophecms/template/views/outerLayoutBase.html +6 -0
- package/modules/@apostrophecms/widget-type/index.js +21 -0
- package/package.json +1 -1
- package/test/areas.js +2 -1
- package/test/assets.js +307 -3
- package/test/docs.js +67 -2
- package/test/modules/bundle/index.js +7 -0
- package/test/modules/bundle-page/index.js +32 -0
- package/test/modules/bundle-page/ui/src/extra.js +1 -0
- package/test/modules/bundle-page/ui/src/extra.scss +0 -0
- package/test/modules/bundle-page/views/index.html +9 -0
- package/test/modules/bundle-page/views/show.html +10 -0
- package/test/modules/bundle-widget/index.js +27 -0
- package/test/modules/bundle-widget/ui/src/extra2.js +1 -0
- package/test/modules/bundle-widget/views/widget.html +1 -0
- package/test/pieces.js +38 -12
- package/test/public/static-test.txt +0 -1
package/.eslintignore
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,34 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
# 3.17.0 (2022-03-31)
|
|
4
|
+
|
|
5
|
+
### Adds
|
|
6
|
+
|
|
7
|
+
* Full support for the [`object` field type](https://v3.docs.apostrophecms.org/reference/field-types/object.html), which works just like `array` but stores just one sub-object as a property, rather than an array of objects.
|
|
8
|
+
* To help find documents that reference related ones via `relationship` fields, implement backlinks of related documents by adding a `relatedReverseIds` field to them and keeping it up to date. There is no UI based on this feature yet but it will permit various useful features in the near future.
|
|
9
|
+
* Adds possibility for modules to [extend the webpack configuration](https://v3.docs.apostrophecms.org/guide/webpack.html).
|
|
10
|
+
* Adds possibility for modules to [add extra frontend bundles for scss and js](https://v3.docs.apostrophecms.org/guide/webpack.html). This is useful when the `ui/src` build would otherwise be very large due to code used on rarely accessed pages.
|
|
11
|
+
* Loads the right bundles on the right pages depending on the page template and the loaded widgets. Logged-in users have all the bundles on every page, because they might introduce widgets at any time.
|
|
12
|
+
|
|
13
|
+
### Fixes
|
|
14
|
+
|
|
15
|
+
* Apostrophe's webpack build now works properly when developing code that imports module-specific npm dependencies from `ui/src` or `ui/apos` when using `npm link` to develop the module in question.
|
|
16
|
+
* The `es5: true` option to `@apostrophecms/asset` works again.
|
|
17
|
+
|
|
18
|
+
# 3.16.1 (2022-03-21)
|
|
19
|
+
|
|
20
|
+
### Fixes
|
|
21
|
+
|
|
22
|
+
* Fixes a bug in the new `Cache-Control` support introduced by 3.16.0 in which we get the logged-out homepage right after logging in. This issue only came into play if the new caching options were enabled.
|
|
23
|
+
|
|
3
24
|
## 3.16.0 (2022-03-18)
|
|
4
25
|
|
|
5
26
|
### Adds
|
|
6
27
|
|
|
7
|
-
* Offers a simple way to set a Cache-Control max-age for Apostrophe page and GET REST API responses for pieces and pages.
|
|
28
|
+
* Offers a simple way to set a Cache-Control max-age for Apostrophe page and GET REST API responses for pieces and pages. [See the documentation for more information](https://v3.docs.apostrophecms.org/guide/caching.html).
|
|
8
29
|
* API keys and bearer tokens "win" over session cookies when both are present. Since API keys and bearer tokens are explicitly added to the request at hand, it never makes sense to ignore them in favor of a cookie, which is implicit. This also simplifies automated testing.
|
|
9
30
|
* `data-apos-test=""` selectors for certain elements frequently selected in QA tests, such as `data-apos-test="adminBar"`.
|
|
31
|
+
* Offer a simple way to set a Cache-Control max-age for Apostrophe page and GET REST API responses for pieces and pages.
|
|
10
32
|
* To speed up functional tests, an `insecurePasswords` option has been added to the login module. This option is deliberately named to discourage use for any purpose other than functional tests in which repeated password hashing would unduly limit performance. Normally password hashing is intentionally difficult to slow down brute force attacks, especially if a database is compromised.
|
|
11
33
|
|
|
12
34
|
### Fixes
|
package/index.js
CHANGED
|
@@ -291,11 +291,11 @@ module.exports = async function(options) {
|
|
|
291
291
|
${self.localModules}
|
|
292
292
|
|
|
293
293
|
must export an object containing configuration for Apostrophe modules.
|
|
294
|
-
|
|
294
|
+
|
|
295
295
|
The file:
|
|
296
|
-
|
|
296
|
+
|
|
297
297
|
${config}
|
|
298
|
-
|
|
298
|
+
|
|
299
299
|
did not parse.
|
|
300
300
|
`);
|
|
301
301
|
throw e;
|
|
@@ -441,7 +441,8 @@ module.exports = async function(options) {
|
|
|
441
441
|
'queries',
|
|
442
442
|
'extendQueries',
|
|
443
443
|
'icons',
|
|
444
|
-
'i18n'
|
|
444
|
+
'i18n',
|
|
445
|
+
'webpack'
|
|
445
446
|
]
|
|
446
447
|
});
|
|
447
448
|
|
package/lib/moog.js
CHANGED
|
@@ -134,7 +134,20 @@ module.exports = function(options) {
|
|
|
134
134
|
self.options.sections = self.options.sections || [];
|
|
135
135
|
self.options.unparsedSections = self.options.unparsedSections || [];
|
|
136
136
|
|
|
137
|
-
const validKeys = [
|
|
137
|
+
const validKeys = [
|
|
138
|
+
'__meta',
|
|
139
|
+
'options',
|
|
140
|
+
'cascades',
|
|
141
|
+
'beforeSuperClass',
|
|
142
|
+
'init',
|
|
143
|
+
'afterAllSections',
|
|
144
|
+
'extend',
|
|
145
|
+
'improve',
|
|
146
|
+
'methods',
|
|
147
|
+
'extendMethods',
|
|
148
|
+
'instantiate',
|
|
149
|
+
'bundle'
|
|
150
|
+
]
|
|
138
151
|
.concat(self.options.sections)
|
|
139
152
|
.concat(self.options.sections.map(getExtendKey))
|
|
140
153
|
.concat(self.options.unparsedSections)
|
|
@@ -363,7 +363,7 @@ export default {
|
|
|
363
363
|
index
|
|
364
364
|
});
|
|
365
365
|
},
|
|
366
|
-
// Regenerate all array item, area and widget ids so they are considered
|
|
366
|
+
// Regenerate all array item, area, object and widget ids so they are considered
|
|
367
367
|
// new. Useful when copying a widget with nested content.
|
|
368
368
|
regenerateIds(schema, object) {
|
|
369
369
|
object._id = cuid();
|
|
@@ -372,6 +372,8 @@ export default {
|
|
|
372
372
|
for (const item of (object[field.name] || [])) {
|
|
373
373
|
this.regenerateIds(field.schema, item);
|
|
374
374
|
}
|
|
375
|
+
} else if (field.type === 'object') {
|
|
376
|
+
this.regenerateIds(field.schema, object[field.name] || {});
|
|
375
377
|
} else if (field.type === 'area') {
|
|
376
378
|
if (object[field.name]) {
|
|
377
379
|
object[field.name]._id = cuid();
|
|
@@ -6,6 +6,15 @@ const globalIcons = require('./lib/globalIcons');
|
|
|
6
6
|
const path = require('path');
|
|
7
7
|
const express = require('express');
|
|
8
8
|
const { stripIndent } = require('common-tags');
|
|
9
|
+
const { merge: webpackMerge } = require('webpack-merge');
|
|
10
|
+
const cuid = require('cuid');
|
|
11
|
+
const {
|
|
12
|
+
checkModulesWebpackConfig,
|
|
13
|
+
getWebpackExtensions,
|
|
14
|
+
fillExtraBundles,
|
|
15
|
+
getBundlesNames,
|
|
16
|
+
writeBundlesImportFiles
|
|
17
|
+
} = require('./lib/webpack/utils');
|
|
9
18
|
|
|
10
19
|
module.exports = {
|
|
11
20
|
|
|
@@ -22,13 +31,22 @@ module.exports = {
|
|
|
22
31
|
refreshOnRestart: false
|
|
23
32
|
},
|
|
24
33
|
|
|
25
|
-
init(self) {
|
|
34
|
+
async init(self) {
|
|
26
35
|
self.restartId = self.apos.util.generateId();
|
|
27
36
|
self.iconMap = {
|
|
28
37
|
...globalIcons
|
|
29
38
|
};
|
|
30
39
|
self.configureBuilds();
|
|
31
40
|
self.initUploadfs();
|
|
41
|
+
|
|
42
|
+
const { extensions, verifiedBundles } = await getWebpackExtensions({
|
|
43
|
+
getMetadata: self.apos.synth.getMetadata,
|
|
44
|
+
modulesToInstantiate: self.apos.modulesToBeInstantiated()
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
self.extraBundles = fillExtraBundles(verifiedBundles);
|
|
48
|
+
self.webpackExtensions = extensions;
|
|
49
|
+
self.verifiedBundles = verifiedBundles;
|
|
32
50
|
},
|
|
33
51
|
handlers (self) {
|
|
34
52
|
return {
|
|
@@ -42,12 +60,18 @@ module.exports = {
|
|
|
42
60
|
// Or if we've set an app option to skip the auto build
|
|
43
61
|
self.apos.options.autoBuild !== false
|
|
44
62
|
) {
|
|
63
|
+
|
|
64
|
+
checkModulesWebpackConfig(self.apos.modules, self.apos.task.getReq().t);
|
|
45
65
|
// If starting up normally, run the build task, checking if we
|
|
46
66
|
// really need to update the apos build
|
|
47
67
|
await self.apos.task.invoke('@apostrophecms/asset:build', {
|
|
48
68
|
'check-apos-build': true
|
|
49
69
|
});
|
|
50
70
|
}
|
|
71
|
+
},
|
|
72
|
+
injectAssetsPlaceholders() {
|
|
73
|
+
self.apos.template.prepend('head', '@apostrophecms/asset:stylesheets');
|
|
74
|
+
self.apos.template.append('body', '@apostrophecms/asset:scripts');
|
|
51
75
|
}
|
|
52
76
|
},
|
|
53
77
|
'apostrophe:destroy': {
|
|
@@ -59,6 +83,28 @@ module.exports = {
|
|
|
59
83
|
}
|
|
60
84
|
};
|
|
61
85
|
},
|
|
86
|
+
components(self) {
|
|
87
|
+
return {
|
|
88
|
+
scripts(req, data) {
|
|
89
|
+
const placeholder = `[scripts-placeholder:${cuid()}]`;
|
|
90
|
+
|
|
91
|
+
req.scriptsPlaceholder = placeholder;
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
placeholder
|
|
95
|
+
};
|
|
96
|
+
},
|
|
97
|
+
stylesheets(req, data) {
|
|
98
|
+
const placeholder = `[stylesheets-placeholder:${cuid()}]`;
|
|
99
|
+
|
|
100
|
+
req.stylesheetsPlaceholder = placeholder;
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
placeholder
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
},
|
|
62
108
|
tasks(self) {
|
|
63
109
|
return {
|
|
64
110
|
build: {
|
|
@@ -69,6 +115,8 @@ module.exports = {
|
|
|
69
115
|
const namespace = self.getNamespace();
|
|
70
116
|
const buildDir = `${self.apos.rootDir}/apos-build/${namespace}`;
|
|
71
117
|
const bundleDir = `${self.apos.rootDir}/public/apos-frontend/${namespace}`;
|
|
118
|
+
const modulesToInstantiate = self.apos.modulesToBeInstantiated();
|
|
119
|
+
|
|
72
120
|
// Don't clutter up with previous builds.
|
|
73
121
|
await fs.remove(buildDir);
|
|
74
122
|
await fs.mkdirp(buildDir);
|
|
@@ -120,7 +168,10 @@ module.exports = {
|
|
|
120
168
|
|
|
121
169
|
if (rebuild) {
|
|
122
170
|
await fs.mkdirp(bundleDir);
|
|
123
|
-
await build(
|
|
171
|
+
await build({
|
|
172
|
+
name,
|
|
173
|
+
options
|
|
174
|
+
});
|
|
124
175
|
}
|
|
125
176
|
}
|
|
126
177
|
|
|
@@ -128,16 +179,19 @@ module.exports = {
|
|
|
128
179
|
// just `public` and `apos`) by examining those specified as
|
|
129
180
|
// targets for the various builds
|
|
130
181
|
const scenes = [ ...new Set(Object.values(self.builds).map(options => options.scenes).flat()) ];
|
|
131
|
-
|
|
132
|
-
for (const scene of scenes) {
|
|
133
|
-
deployFiles = [ ...deployFiles, ...merge(scene) ];
|
|
134
|
-
}
|
|
182
|
+
|
|
135
183
|
// enumerate public assets and include them in deployment if appropriate
|
|
136
184
|
const publicAssets = glob.sync('modules/**/*', {
|
|
137
185
|
cwd: bundleDir,
|
|
138
186
|
mark: true
|
|
139
187
|
}).filter(match => !match.endsWith('/'));
|
|
140
|
-
|
|
188
|
+
|
|
189
|
+
const deployFiles = [
|
|
190
|
+
...publicAssets,
|
|
191
|
+
...merge(scenes),
|
|
192
|
+
...getBundlesNames(self.extraBundles, self.options.es5)
|
|
193
|
+
];
|
|
194
|
+
|
|
141
195
|
await deploy(deployFiles);
|
|
142
196
|
|
|
143
197
|
if (process.env.APOS_BUNDLE_ANALYZER) {
|
|
@@ -154,7 +208,7 @@ module.exports = {
|
|
|
154
208
|
const directories = {};
|
|
155
209
|
// Most other modules are not actually instantiated yet, but
|
|
156
210
|
// we can access their metadata, which is sufficient
|
|
157
|
-
for (const name of
|
|
211
|
+
for (const name of modulesToInstantiate) {
|
|
158
212
|
const ancestorDirectories = [];
|
|
159
213
|
const metadata = self.apos.synth.getMetadata(name);
|
|
160
214
|
for (const entry of metadata.__meta.chain) {
|
|
@@ -181,7 +235,9 @@ module.exports = {
|
|
|
181
235
|
}
|
|
182
236
|
}
|
|
183
237
|
|
|
184
|
-
async function build(
|
|
238
|
+
async function build({
|
|
239
|
+
name, options
|
|
240
|
+
}) {
|
|
185
241
|
self.apos.util.log(req.t('apostrophe:assetTypeBuilding', {
|
|
186
242
|
label: req.t(options.label)
|
|
187
243
|
}));
|
|
@@ -203,6 +259,7 @@ module.exports = {
|
|
|
203
259
|
importSuffix: 'App'
|
|
204
260
|
});
|
|
205
261
|
}
|
|
262
|
+
|
|
206
263
|
if (options.index) {
|
|
207
264
|
indexJsImports = getImports(source, 'index.js', {
|
|
208
265
|
invokeApps: true,
|
|
@@ -219,29 +276,16 @@ module.exports = {
|
|
|
219
276
|
if (options.webpack) {
|
|
220
277
|
const importFile = `${buildDir}/${name}-import.js`;
|
|
221
278
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
${(tiptapExtensionImports && tiptapExtensionImports.registerCode) || ''}
|
|
233
|
-
` +
|
|
234
|
-
(appImports ? stripIndent`
|
|
235
|
-
setTimeout(() => {
|
|
236
|
-
${appImports.invokeCode}
|
|
237
|
-
}, 0);
|
|
238
|
-
` : '') +
|
|
239
|
-
// No delay on these, they expect to run early like ui/public code
|
|
240
|
-
// and the first ones invoked set up expected stuff like apos.http
|
|
241
|
-
(indexJsImports ? stripIndent`
|
|
242
|
-
${indexJsImports.invokeCode}
|
|
243
|
-
` : '')
|
|
244
|
-
);
|
|
279
|
+
writeImportFile({
|
|
280
|
+
importFile,
|
|
281
|
+
prologue: options.prologue,
|
|
282
|
+
icon: iconImports,
|
|
283
|
+
components: componentImports,
|
|
284
|
+
tiptap: tiptapExtensionImports,
|
|
285
|
+
app: appImports,
|
|
286
|
+
indexJs: indexJsImports,
|
|
287
|
+
indexSass: indexSassImports
|
|
288
|
+
});
|
|
245
289
|
|
|
246
290
|
const outputFilename = `${name}-build.js`;
|
|
247
291
|
// Remove previous build artifacts, as some pipelines won't build all artifacts
|
|
@@ -251,13 +295,29 @@ module.exports = {
|
|
|
251
295
|
fs.removeSync(cssPath);
|
|
252
296
|
const webpack = Promise.promisify(webpackModule);
|
|
253
297
|
const webpackBaseConfig = require(`./lib/webpack/${name}/webpack.config`);
|
|
298
|
+
|
|
299
|
+
const webpackExtraBundles = writeBundlesImportFiles({
|
|
300
|
+
name,
|
|
301
|
+
buildDir,
|
|
302
|
+
mainBundleName: outputFilename.replace('.js', ''),
|
|
303
|
+
verifiedBundles: self.verifiedBundles,
|
|
304
|
+
getImportFileOutput,
|
|
305
|
+
writeImportFile
|
|
306
|
+
});
|
|
307
|
+
|
|
254
308
|
const webpackInstanceConfig = webpackBaseConfig({
|
|
255
309
|
importFile,
|
|
256
310
|
modulesDir,
|
|
257
311
|
outputPath: bundleDir,
|
|
258
|
-
outputFilename
|
|
312
|
+
outputFilename,
|
|
313
|
+
bundles: webpackExtraBundles
|
|
259
314
|
}, self.apos);
|
|
260
|
-
|
|
315
|
+
|
|
316
|
+
const webpackInstanceConfigMerged = self.webpackExtensions
|
|
317
|
+
? webpackMerge(webpackInstanceConfig, ...Object.values(self.webpackExtensions))
|
|
318
|
+
: webpackInstanceConfig;
|
|
319
|
+
|
|
320
|
+
const result = await webpack(webpackInstanceConfigMerged);
|
|
261
321
|
if (result.compilation.errors.length) {
|
|
262
322
|
// Throwing a string is appropriate in a command line task
|
|
263
323
|
throw cleanErrors(result.toString('errors'));
|
|
@@ -285,7 +345,7 @@ module.exports = {
|
|
|
285
345
|
//
|
|
286
346
|
// Of course, developers can push an "public" asset that is
|
|
287
347
|
// the output of an ES6 pipeline.
|
|
288
|
-
const publicImports = getImports(name, '*.js'
|
|
348
|
+
const publicImports = getImports(name, '*.js');
|
|
289
349
|
fs.writeFileSync(`${bundleDir}/${name}-build.js`,
|
|
290
350
|
(((options.prologue || '') + '\n') || '') +
|
|
291
351
|
publicImports.paths.map(path => {
|
|
@@ -294,7 +354,7 @@ module.exports = {
|
|
|
294
354
|
);
|
|
295
355
|
}
|
|
296
356
|
if (options.outputs.includes('css')) {
|
|
297
|
-
const publicImports = getImports(name, '*.css'
|
|
357
|
+
const publicImports = getImports(name, '*.css');
|
|
298
358
|
fs.writeFileSync(`${bundleDir}/${name}-build.css`,
|
|
299
359
|
publicImports.paths.map(path => {
|
|
300
360
|
return self.filterCss(fs.readFileSync(path, 'utf8'), {
|
|
@@ -309,9 +369,43 @@ module.exports = {
|
|
|
309
369
|
}));
|
|
310
370
|
}
|
|
311
371
|
|
|
312
|
-
function
|
|
372
|
+
function writeImportFile ({
|
|
373
|
+
importFile,
|
|
374
|
+
prologue,
|
|
375
|
+
icon,
|
|
376
|
+
components,
|
|
377
|
+
tiptap,
|
|
378
|
+
app,
|
|
379
|
+
indexJs,
|
|
380
|
+
indexSass
|
|
381
|
+
}) {
|
|
382
|
+
fs.writeFileSync(importFile, (prologue || '') + stripIndent`
|
|
383
|
+
${(icon && icon.importCode) || ''}
|
|
384
|
+
${(icon && icon.registerCode) || ''}
|
|
385
|
+
${(components && components.importCode) || ''}
|
|
386
|
+
${(tiptap && tiptap.importCode) || ''}
|
|
387
|
+
${(app && app.importCode) || ''}
|
|
388
|
+
${(indexJs && indexJs.importCode) || ''}
|
|
389
|
+
${(indexSass && indexSass.importCode) || ''}
|
|
390
|
+
${(icon && icon.registerCode) || ''}
|
|
391
|
+
${(components && components.registerCode) || ''}
|
|
392
|
+
${(tiptap && tiptap.registerCode) || ''}
|
|
393
|
+
` +
|
|
394
|
+
(app ? stripIndent`
|
|
395
|
+
setTimeout(() => {
|
|
396
|
+
${app.invokeCode}
|
|
397
|
+
}, 0);
|
|
398
|
+
` : '') +
|
|
399
|
+
// No delay on these, they expect to run early like ui/public code
|
|
400
|
+
// and the first ones invoked set up expected stuff like apos.http
|
|
401
|
+
(indexJs ? stripIndent`
|
|
402
|
+
${indexJs.invokeCode}
|
|
403
|
+
` : '')
|
|
404
|
+
);
|
|
405
|
+
}
|
|
313
406
|
|
|
314
|
-
|
|
407
|
+
function getIcons() {
|
|
408
|
+
for (const name of modulesToInstantiate) {
|
|
315
409
|
const metadata = self.apos.synth.getMetadata(name);
|
|
316
410
|
// icons is an unparsed section, so getMetadata gives it back
|
|
317
411
|
// to us as an object with a property for each class in the
|
|
@@ -347,45 +441,65 @@ module.exports = {
|
|
|
347
441
|
return output;
|
|
348
442
|
}
|
|
349
443
|
|
|
350
|
-
function merge(
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
)
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
)
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
444
|
+
function merge(scenes) {
|
|
445
|
+
return scenes.reduce((acc, scene) => {
|
|
446
|
+
const jsModules = `${scene}-module-bundle.js`;
|
|
447
|
+
const jsNoModules = `${scene}-nomodule-bundle.js`;
|
|
448
|
+
const css = `${scene}-bundle.css`;
|
|
449
|
+
|
|
450
|
+
writeSceneBundle({
|
|
451
|
+
scene,
|
|
452
|
+
filePath: jsModules,
|
|
453
|
+
jsCondition: 'module'
|
|
454
|
+
});
|
|
455
|
+
writeSceneBundle({
|
|
456
|
+
scene,
|
|
457
|
+
filePath: jsNoModules,
|
|
458
|
+
jsCondition: 'nomodule'
|
|
459
|
+
});
|
|
460
|
+
writeSceneBundle({
|
|
461
|
+
scene,
|
|
462
|
+
filePath: css,
|
|
463
|
+
checkForFile: true
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
return [
|
|
467
|
+
...acc,
|
|
468
|
+
jsModules,
|
|
469
|
+
jsNoModules,
|
|
470
|
+
css
|
|
471
|
+
];
|
|
472
|
+
}, []);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
function writeSceneBundle ({
|
|
476
|
+
scene, filePath, jsCondition, checkForFile = false
|
|
477
|
+
}) {
|
|
478
|
+
const [ _ext, fileExt ] = filePath.match(/\.(\w+)$/);
|
|
479
|
+
const filterBuilds = ({
|
|
480
|
+
scenes, outputs, condition
|
|
481
|
+
}) => {
|
|
482
|
+
return outputs.includes(fileExt) &&
|
|
483
|
+
((!condition || !jsCondition) || condition === jsCondition) &&
|
|
484
|
+
scenes.includes(scene);
|
|
485
|
+
};
|
|
486
|
+
|
|
487
|
+
const filesContent = Object.entries(self.builds)
|
|
488
|
+
.filter(([ _, options ]) => filterBuilds(options))
|
|
489
|
+
.map(([ name ]) => {
|
|
490
|
+
const file = `${bundleDir}/${name}-build.${fileExt}`;
|
|
491
|
+
const readFile = (n, f) => `/* BUILD: ${n} */\n${fs.readFileSync(f, 'utf8')}`;
|
|
492
|
+
|
|
493
|
+
if (checkForFile) {
|
|
494
|
+
return fs.existsSync(file)
|
|
495
|
+
? readFile(name, file)
|
|
496
|
+
: '';
|
|
385
497
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
498
|
+
|
|
499
|
+
return readFile(name, file);
|
|
500
|
+
}).join('\n');
|
|
501
|
+
|
|
502
|
+
fs.writeFileSync(`${bundleDir}/${filePath}`, filesContent);
|
|
389
503
|
}
|
|
390
504
|
|
|
391
505
|
// If NODE_ENV is production, this function will copy the given
|
|
@@ -432,10 +546,10 @@ module.exports = {
|
|
|
432
546
|
return fs.copyFile(from, to);
|
|
433
547
|
}
|
|
434
548
|
|
|
435
|
-
function getImports(folder, pattern, options) {
|
|
549
|
+
function getImports(folder, pattern, options = {}) {
|
|
436
550
|
let components = [];
|
|
437
551
|
const seen = {};
|
|
438
|
-
for (const name of
|
|
552
|
+
for (const name of modulesToInstantiate) {
|
|
439
553
|
const metadata = self.apos.synth.getMetadata(name);
|
|
440
554
|
for (const entry of metadata.__meta.chain) {
|
|
441
555
|
if (seen[entry.dirname]) {
|
|
@@ -445,12 +559,6 @@ module.exports = {
|
|
|
445
559
|
seen[entry.dirname] = true;
|
|
446
560
|
}
|
|
447
561
|
}
|
|
448
|
-
const output = {
|
|
449
|
-
importCode: '',
|
|
450
|
-
registerCode: '',
|
|
451
|
-
invokeCode: '',
|
|
452
|
-
paths: []
|
|
453
|
-
};
|
|
454
562
|
|
|
455
563
|
if (options.importLastVersion) {
|
|
456
564
|
// Reverse the list so we can easily find the last configured import
|
|
@@ -471,6 +579,17 @@ module.exports = {
|
|
|
471
579
|
components.reverse();
|
|
472
580
|
}
|
|
473
581
|
|
|
582
|
+
return getImportFileOutput(components, options);
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
function getImportFileOutput (components, options = {}) {
|
|
586
|
+
const output = {
|
|
587
|
+
importCode: '',
|
|
588
|
+
registerCode: '',
|
|
589
|
+
invokeCode: '',
|
|
590
|
+
paths: []
|
|
591
|
+
};
|
|
592
|
+
|
|
474
593
|
components.forEach((component, i) => {
|
|
475
594
|
if (options.requireDefaultExport) {
|
|
476
595
|
if (!fs.readFileSync(component, 'utf8').match(/export[\s\n]+default/)) {
|
|
@@ -485,10 +604,11 @@ module.exports = {
|
|
|
485
604
|
const jsFilename = JSON.stringify(component);
|
|
486
605
|
const name = getComponentName(component, options, i);
|
|
487
606
|
const jsName = JSON.stringify(name);
|
|
488
|
-
output.paths.push(component);
|
|
489
607
|
const importCode = `
|
|
490
608
|
import ${name}${options.importSuffix || ''} from ${jsFilename};
|
|
491
609
|
`;
|
|
610
|
+
|
|
611
|
+
output.paths.push(component);
|
|
492
612
|
output.importCode += `${importCode}\n`;
|
|
493
613
|
|
|
494
614
|
if (options.registerComponents) {
|
|
@@ -505,6 +625,7 @@ module.exports = {
|
|
|
505
625
|
output.invokeCode += `${name}${options.importSuffix || ''}();\n`;
|
|
506
626
|
}
|
|
507
627
|
});
|
|
628
|
+
|
|
508
629
|
return output;
|
|
509
630
|
}
|
|
510
631
|
|
|
@@ -523,8 +644,11 @@ module.exports = {
|
|
|
523
644
|
return pkgTimestamp > parseInt(timestamp);
|
|
524
645
|
}
|
|
525
646
|
|
|
526
|
-
function getComponentName(component,
|
|
527
|
-
return
|
|
647
|
+
function getComponentName(component, { enumerateImports } = {}, i) {
|
|
648
|
+
return path
|
|
649
|
+
.basename(component)
|
|
650
|
+
.replace(/-/g, '_')
|
|
651
|
+
.replace(/\.\w+/, '') + (enumerateImports ? `_${i}` : '');
|
|
528
652
|
}
|
|
529
653
|
|
|
530
654
|
function cleanErrors(errors) {
|
|
@@ -555,22 +679,10 @@ module.exports = {
|
|
|
555
679
|
}
|
|
556
680
|
},
|
|
557
681
|
stylesheetsHelper(when) {
|
|
558
|
-
|
|
559
|
-
const bundle = `<link href="${base}/${when}-bundle.css" rel="stylesheet" />`;
|
|
560
|
-
return self.apos.template.safe(bundle);
|
|
682
|
+
return '';
|
|
561
683
|
},
|
|
562
684
|
scriptsHelper(when) {
|
|
563
|
-
|
|
564
|
-
if (self.options.es5) {
|
|
565
|
-
return self.apos.template.safe(stripIndent`
|
|
566
|
-
<script nomodule src="${base}/${when}-nomodule-bundle.js"></script>
|
|
567
|
-
<script type="module" src="${base}/${when}-module-bundle.js"></script>
|
|
568
|
-
`);
|
|
569
|
-
} else {
|
|
570
|
-
return self.apos.template.safe(stripIndent`
|
|
571
|
-
<script src="${base}/${when}-module-bundle.js"></script>
|
|
572
|
-
`);
|
|
573
|
-
}
|
|
685
|
+
return '';
|
|
574
686
|
},
|
|
575
687
|
shouldRefreshOnRestart() {
|
|
576
688
|
return self.options.refreshOnRestart && (process.env.NODE_ENV !== 'production');
|
|
@@ -47,11 +47,11 @@ module.exports = ({
|
|
|
47
47
|
Modules: path.resolve(modulesDir)
|
|
48
48
|
},
|
|
49
49
|
modules: [
|
|
50
|
-
|
|
51
|
-
// apostrophe module itself
|
|
50
|
+
'node_modules',
|
|
52
51
|
`${apos.npmRootDir}/node_modules/apostrophe/node_modules`,
|
|
53
52
|
`${apos.npmRootDir}/node_modules`
|
|
54
|
-
]
|
|
53
|
+
],
|
|
54
|
+
symlinks: false
|
|
55
55
|
},
|
|
56
56
|
stats: 'verbose',
|
|
57
57
|
plugins: process.env.APOS_BUNDLE_ANALYZER ? [ new BundleAnalyzerPlugin() ] : []
|