apostrophe 3.8.1 → 3.11.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/.github/workflows/main.yml +45 -0
- package/CHANGELOG.md +61 -0
- package/README.md +1 -2
- package/lib/moog.js +26 -1
- package/modules/@apostrophecms/admin-bar/ui/apos/apps/AposAdminBar.js +7 -1
- package/modules/@apostrophecms/any-page-type/index.js +2 -0
- package/modules/@apostrophecms/area/ui/apos/apps/AposAreas.js +28 -11
- package/modules/@apostrophecms/asset/index.js +35 -4
- package/modules/@apostrophecms/asset/lib/webpack/apos/webpack.config.js +2 -2
- package/modules/@apostrophecms/asset/lib/webpack/src/webpack.config.js +1 -1
- package/modules/@apostrophecms/attachment/index.js +0 -4
- package/modules/@apostrophecms/busy/ui/apos/apps/AposBusy.js +3 -1
- package/modules/@apostrophecms/doc-type/index.js +12 -8
- package/modules/@apostrophecms/doc-type/ui/apos/components/AposDocEditor.vue +0 -1
- package/modules/@apostrophecms/i18n/i18n/en.json +8 -0
- package/modules/@apostrophecms/i18n/i18n/es.json +1 -1
- package/modules/@apostrophecms/i18n/index.js +26 -5
- package/modules/@apostrophecms/job/index.js +10 -17
- package/modules/@apostrophecms/login/index.js +23 -10
- package/modules/@apostrophecms/login/ui/apos/apps/AposLogin.js +3 -2
- package/modules/@apostrophecms/modal/ui/apos/apps/AposModals.js +8 -5
- package/modules/@apostrophecms/modal/ui/apos/components/AposDocsManagerToolbar.vue +1 -1
- package/modules/@apostrophecms/module/index.js +1 -4
- package/modules/@apostrophecms/notification/ui/apos/apps/AposNotification.js +3 -1
- package/modules/@apostrophecms/notification/ui/apos/components/AposNotification.vue +1 -1
- package/modules/@apostrophecms/page/index.js +51 -27
- package/modules/@apostrophecms/page-type/index.js +5 -1
- package/modules/@apostrophecms/piece-type/index.js +5 -0
- package/modules/@apostrophecms/piece-type/ui/apos/components/AposDocsManager.vue +2 -1
- package/modules/@apostrophecms/piece-type/ui/apos/components/AposDocsManagerSelectBox.vue +27 -24
- package/modules/@apostrophecms/rich-text-widget/index.js +2 -1
- package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposRichTextWidgetEditor.vue +3 -1
- package/modules/@apostrophecms/schema/index.js +7 -19
- package/modules/@apostrophecms/schema/ui/apos/components/AposArrayEditor.vue +9 -3
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputCheckboxes.vue +3 -3
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputPassword.vue +11 -4
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputRange.vue +2 -2
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputWrapper.vue +0 -2
- package/modules/@apostrophecms/schema/ui/apos/components/AposLogo.vue +1 -1
- package/modules/@apostrophecms/schema/ui/apos/components/AposLogoIcon.vue +1 -1
- package/modules/@apostrophecms/schema/ui/apos/components/AposLogoPadless.vue +1 -1
- package/modules/@apostrophecms/schema/ui/apos/components/AposSearchList.vue +0 -1
- package/modules/@apostrophecms/search/index.js +53 -33
- package/modules/@apostrophecms/task/index.js +5 -1
- package/modules/@apostrophecms/template/index.js +5 -11
- package/modules/@apostrophecms/ui/ui/apos/components/AposMinMaxCount.vue +9 -3
- package/modules/@apostrophecms/ui/ui/apos/mixins/AposPublishMixin.js +3 -2
- package/modules/@apostrophecms/widget-type/index.js +9 -0
- package/modules/@apostrophecms/widget-type/ui/apos/mixins/AposWidgetMixin.js +5 -27
- package/package.json +10 -10
- package/test/moog.js +48 -0
- package/test-lib/util.js +4 -2
- package/.circleci/config.yml +0 -94
- package/.github/pull_request_template.md +0 -8
- package/.scratch.md +0 -2
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
// are edge cases not relevant enough to explicitly offer a filter for, but
|
|
45
45
|
// which should nevertheless be included in results.
|
|
46
46
|
|
|
47
|
+
const { stripIndent } = require('common-tags');
|
|
47
48
|
const _ = require('lodash');
|
|
48
49
|
|
|
49
50
|
module.exports = {
|
|
@@ -98,37 +99,7 @@ module.exports = {
|
|
|
98
99
|
},
|
|
99
100
|
'@apostrophecms/doc-type:beforeSave': {
|
|
100
101
|
indexDoc(req, doc) {
|
|
101
|
-
|
|
102
|
-
const texts = self.getSearchTexts(doc);
|
|
103
|
-
|
|
104
|
-
_.each(texts, function (text) {
|
|
105
|
-
if (text.text === undefined) {
|
|
106
|
-
text.text = '';
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
const highTexts = _.filter(texts, function (text) {
|
|
111
|
-
return text.weight > 10;
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
const searchSummary = _.map(_.filter(texts, function (text) {
|
|
115
|
-
return !text.silent;
|
|
116
|
-
}), function (text) {
|
|
117
|
-
return text.text;
|
|
118
|
-
}).join(' ');
|
|
119
|
-
const highText = self.boilTexts(highTexts);
|
|
120
|
-
const lowText = self.boilTexts(texts);
|
|
121
|
-
const titleSortified = self.apos.util.sortify(doc.title);
|
|
122
|
-
const highWords = _.uniq(highText.split(/ /));
|
|
123
|
-
|
|
124
|
-
// merge our doc with its various search texts
|
|
125
|
-
_.assign(doc, {
|
|
126
|
-
titleSortified: titleSortified,
|
|
127
|
-
highSearchText: highText,
|
|
128
|
-
highSearchWords: highWords,
|
|
129
|
-
lowSearchText: lowText,
|
|
130
|
-
searchSummary: searchSummary
|
|
131
|
-
});
|
|
102
|
+
self.indexDoc(req, doc);
|
|
132
103
|
}
|
|
133
104
|
}
|
|
134
105
|
};
|
|
@@ -261,13 +232,58 @@ module.exports = {
|
|
|
261
232
|
self.dispatch('/', self.indexPage);
|
|
262
233
|
},
|
|
263
234
|
|
|
235
|
+
indexDoc(req, doc) {
|
|
236
|
+
|
|
237
|
+
const texts = self.getSearchTexts(doc);
|
|
238
|
+
|
|
239
|
+
_.each(texts, function (text) {
|
|
240
|
+
if (text.text === undefined) {
|
|
241
|
+
text.text = '';
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
const highTexts = _.filter(texts, function (text) {
|
|
246
|
+
return text.weight > 10;
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
const searchSummary = _.map(_.filter(texts, function (text) {
|
|
250
|
+
return !text.silent;
|
|
251
|
+
}), function (text) {
|
|
252
|
+
return text.text;
|
|
253
|
+
}).join(' ');
|
|
254
|
+
const highText = self.boilTexts(highTexts);
|
|
255
|
+
const lowText = self.boilTexts(texts);
|
|
256
|
+
const titleSortified = self.apos.util.sortify(doc.title);
|
|
257
|
+
const highWords = _.uniq(highText.split(/ /));
|
|
258
|
+
|
|
259
|
+
// merge our doc with its various search texts
|
|
260
|
+
_.assign(doc, {
|
|
261
|
+
titleSortified: titleSortified,
|
|
262
|
+
highSearchText: highText,
|
|
263
|
+
highSearchWords: highWords,
|
|
264
|
+
lowSearchText: lowText,
|
|
265
|
+
searchSummary: searchSummary
|
|
266
|
+
});
|
|
267
|
+
},
|
|
268
|
+
|
|
264
269
|
// Indexes just one document as part of the implementation of the
|
|
265
270
|
// `@apostrophecms/search:index` task. This isn't the method you want to
|
|
266
271
|
// override. See `indexDoc` and `getSearchTexts`
|
|
267
272
|
|
|
268
273
|
async indexTaskOne(req, doc) {
|
|
269
274
|
self.indexDoc(req, doc);
|
|
270
|
-
|
|
275
|
+
|
|
276
|
+
return self.apos.doc.db.updateOne({
|
|
277
|
+
_id: doc._id
|
|
278
|
+
}, {
|
|
279
|
+
$set: {
|
|
280
|
+
titleSortified: doc.titleSortified,
|
|
281
|
+
highSearchText: doc.highSearchText,
|
|
282
|
+
highSearchWords: doc.highSearchWords,
|
|
283
|
+
lowSearchText: doc.lowSearchText,
|
|
284
|
+
searchSummary: doc.searchSummary
|
|
285
|
+
}
|
|
286
|
+
});
|
|
271
287
|
},
|
|
272
288
|
|
|
273
289
|
// Returns texts which are a reasonable basis for
|
|
@@ -348,7 +364,11 @@ module.exports = {
|
|
|
348
364
|
tasks(self) {
|
|
349
365
|
return {
|
|
350
366
|
index: {
|
|
351
|
-
usage:
|
|
367
|
+
usage: stripIndent`
|
|
368
|
+
Rebuild the search index. Normally this happens automatically.
|
|
369
|
+
This should only be needed if you have changed the"searchable" property
|
|
370
|
+
for various fields or types.
|
|
371
|
+
`,
|
|
352
372
|
task(argv) {
|
|
353
373
|
const req = self.apos.task.getReq();
|
|
354
374
|
return self.apos.migration.eachDoc({}, _.partial(self.indexTaskOne, req));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Implements template rendering via Nunjucks. **You should use the
|
|
2
|
-
// `self.render`
|
|
2
|
+
// `self.render` method of *your own* module**,
|
|
3
3
|
// which exist courtesy of [@apostrophecms/module](../@apostrophecms/module/index.html)
|
|
4
4
|
// and invoke methods of this module more conveniently for you.
|
|
5
5
|
//
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
// you have a custom version of Nunjucks that is compatible.
|
|
22
22
|
//
|
|
23
23
|
// ### `viewsFolderFallback`: specifies a folder to be checked for templates
|
|
24
|
-
// if they are not found in the module that called `self.render`
|
|
24
|
+
// if they are not found in the module that called `self.render`
|
|
25
25
|
// or those it extends. This is a handy place for project-wide macro files.
|
|
26
26
|
// Often set to `__dirname + '/views'` in `app.js`.
|
|
27
27
|
|
|
@@ -203,7 +203,7 @@ module.exports = {
|
|
|
203
203
|
|
|
204
204
|
async renderForModule(req, name, data, module) {
|
|
205
205
|
if (typeof req !== 'object') {
|
|
206
|
-
throw new Error('The first argument to module.render must be req.
|
|
206
|
+
throw new Error('The first argument to module.render must be req.');
|
|
207
207
|
}
|
|
208
208
|
return self.renderBody(req, 'file', name, data, module);
|
|
209
209
|
},
|
|
@@ -214,7 +214,7 @@ module.exports = {
|
|
|
214
214
|
|
|
215
215
|
async renderStringForModule(req, s, data, module) {
|
|
216
216
|
if (typeof req !== 'object') {
|
|
217
|
-
throw new Error('The first argument to module.render must be req.
|
|
217
|
+
throw new Error('The first argument to module.render must be req.');
|
|
218
218
|
}
|
|
219
219
|
return self.renderBody(req, 'string', s, data, module);
|
|
220
220
|
},
|
|
@@ -289,12 +289,6 @@ module.exports = {
|
|
|
289
289
|
|
|
290
290
|
args.data = merged;
|
|
291
291
|
|
|
292
|
-
// // Allows templates to render other templates in an independent
|
|
293
|
-
// // nunjucks environment, rather than including them
|
|
294
|
-
// args.partial = function(name, data) {
|
|
295
|
-
// return self.partialForModule(name, data, module);
|
|
296
|
-
// };
|
|
297
|
-
|
|
298
292
|
if (req.data) {
|
|
299
293
|
_.defaults(merged, req.data);
|
|
300
294
|
}
|
|
@@ -334,7 +328,7 @@ module.exports = {
|
|
|
334
328
|
|
|
335
329
|
// Fetch a nunjucks environment in which `include`, `extends`, etc. search
|
|
336
330
|
// the views directories of the specified module and its ancestors.
|
|
337
|
-
// Typically you will call `self.render`
|
|
331
|
+
// Typically you will call `self.render` on your module
|
|
338
332
|
// object rather than calling this directly.
|
|
339
333
|
//
|
|
340
334
|
// `req` is effectively here for bc purposes only. This method
|
|
@@ -61,7 +61,9 @@ export default {
|
|
|
61
61
|
return maxError;
|
|
62
62
|
},
|
|
63
63
|
countLabel() {
|
|
64
|
-
return
|
|
64
|
+
return this.$t('apostrophe:numberAdded', {
|
|
65
|
+
count: this.value.length
|
|
66
|
+
});
|
|
65
67
|
},
|
|
66
68
|
// Here in the array editor we use effectiveMin to factor in the
|
|
67
69
|
// required property because there is no other good place to do that,
|
|
@@ -69,14 +71,18 @@ export default {
|
|
|
69
71
|
// representation of "required".
|
|
70
72
|
minLabel() {
|
|
71
73
|
if (this.effectiveMin) {
|
|
72
|
-
return
|
|
74
|
+
return this.$t('apostrophe:minUi', {
|
|
75
|
+
number: this.effectiveMin
|
|
76
|
+
});
|
|
73
77
|
} else {
|
|
74
78
|
return false;
|
|
75
79
|
}
|
|
76
80
|
},
|
|
77
81
|
maxLabel() {
|
|
78
82
|
if ((typeof this.field.max) === 'number') {
|
|
79
|
-
return
|
|
83
|
+
return this.$t('apostrophe:maxUi', {
|
|
84
|
+
number: this.field.max
|
|
85
|
+
});
|
|
80
86
|
} else {
|
|
81
87
|
return false;
|
|
82
88
|
}
|
|
@@ -49,9 +49,10 @@ export default {
|
|
|
49
49
|
if ((e.name === 'invalid') && e.body && e.body.data && e.body.data.unpublishedAncestors) {
|
|
50
50
|
if (await apos.confirm({
|
|
51
51
|
heading: 'apostrophe:unpublishedParent',
|
|
52
|
-
description: 'apostrophe:unpublishedParentDescription'
|
|
52
|
+
description: 'apostrophe:unpublishedParentDescription'
|
|
53
|
+
}, {
|
|
53
54
|
interpolate: {
|
|
54
|
-
unpublishedParents:
|
|
55
|
+
unpublishedParents: e.body.data.unpublishedAncestors.map(page => page.title).join(this.$t('apostrophe:listJoiner'))
|
|
55
56
|
}
|
|
56
57
|
})) {
|
|
57
58
|
try {
|
|
@@ -112,6 +112,7 @@
|
|
|
112
112
|
// you are debugging a change and need to test all of the different ways a widget has
|
|
113
113
|
// been used, or are wondering if you can safely remove one.
|
|
114
114
|
|
|
115
|
+
const { stripIndent } = require('common-tags');
|
|
115
116
|
const _ = require('lodash');
|
|
116
117
|
|
|
117
118
|
module.exports = {
|
|
@@ -310,12 +311,20 @@ module.exports = {
|
|
|
310
311
|
},
|
|
311
312
|
|
|
312
313
|
// override to add CSS classes to the outer wrapper div of the widget.
|
|
314
|
+
// TODO: Remove in the 4.x major version.
|
|
313
315
|
getWidgetWrapperClasses(widget) {
|
|
316
|
+
self.apos.util.warnDev(stripIndent`
|
|
317
|
+
The getWidgetWrapperClasses method is deprecated and will be removed in the next
|
|
318
|
+
major version. The method in 3.x simply returns an empty array.`);
|
|
314
319
|
return [];
|
|
315
320
|
},
|
|
316
321
|
|
|
317
322
|
// Override to add CSS classes to the div of the widget itself.
|
|
323
|
+
// TODO: Remove in the 4.x major version.
|
|
318
324
|
getWidgetClasses(widget) {
|
|
325
|
+
self.apos.util.warnDev(stripIndent`
|
|
326
|
+
The getWidgetClasses method is deprecated and will be removed in the next major
|
|
327
|
+
version. The method in 3.x simply returns an empty array.`);
|
|
319
328
|
return [];
|
|
320
329
|
}
|
|
321
330
|
};
|
|
@@ -22,17 +22,11 @@ export default {
|
|
|
22
22
|
},
|
|
23
23
|
data() {
|
|
24
24
|
return {
|
|
25
|
-
rendered: '...'
|
|
26
|
-
playerOpts: null,
|
|
27
|
-
playerEl: null
|
|
25
|
+
rendered: '...'
|
|
28
26
|
};
|
|
29
27
|
},
|
|
30
28
|
mounted() {
|
|
31
29
|
this.renderContent();
|
|
32
|
-
this.playerOpts = apos.util.widgetPlayers[this.type] || null;
|
|
33
|
-
},
|
|
34
|
-
updated () {
|
|
35
|
-
this.runPlayer();
|
|
36
30
|
},
|
|
37
31
|
computed: {
|
|
38
32
|
moduleOptions() {
|
|
@@ -41,7 +35,7 @@ export default {
|
|
|
41
35
|
},
|
|
42
36
|
methods: {
|
|
43
37
|
async renderContent() {
|
|
44
|
-
|
|
38
|
+
apos.bus.$emit('widget-rendering');
|
|
45
39
|
const parameters = {
|
|
46
40
|
_docId: this.docId,
|
|
47
41
|
widget: this.value,
|
|
@@ -51,7 +45,6 @@ export default {
|
|
|
51
45
|
try {
|
|
52
46
|
if (this.rendering && (isEqual(this.rendering.parameters, parameters))) {
|
|
53
47
|
this.rendered = this.rendering.html;
|
|
54
|
-
this.runPlayer();
|
|
55
48
|
} else {
|
|
56
49
|
this.rendered = '...';
|
|
57
50
|
this.rendered = await apos.http.post(`${apos.area.action}/render-widget?aposEdit=1&aposMode=draft`, {
|
|
@@ -59,11 +52,10 @@ export default {
|
|
|
59
52
|
body: parameters
|
|
60
53
|
});
|
|
61
54
|
}
|
|
62
|
-
// Wait for reactivity to
|
|
63
|
-
//
|
|
64
|
-
//
|
|
55
|
+
// Wait for reactivity to render v-html so that markup is
|
|
56
|
+
// in the DOM before hinting that it might be time to prepare
|
|
57
|
+
// sub-area editors and run players
|
|
65
58
|
setTimeout(function() {
|
|
66
|
-
self.setPlayerEl();
|
|
67
59
|
apos.bus.$emit('widget-rendered');
|
|
68
60
|
}, 0);
|
|
69
61
|
} catch (e) {
|
|
@@ -71,20 +63,6 @@ export default {
|
|
|
71
63
|
console.error('Unable to render widget. Possibly the schema has been changed and the existing widget does not pass validation.', e);
|
|
72
64
|
}
|
|
73
65
|
},
|
|
74
|
-
setPlayerEl() {
|
|
75
|
-
if (this.playerOpts) {
|
|
76
|
-
const el = this.$el.querySelector(this.playerOpts.selector);
|
|
77
|
-
if (el && this.playerOpts.player) {
|
|
78
|
-
this.playerEl = el;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
},
|
|
82
|
-
runPlayer() {
|
|
83
|
-
if (this.playerEl && !this.playerEl.aposWidgetPlayed) {
|
|
84
|
-
this.playerOpts.player(this.playerEl);
|
|
85
|
-
this.playerEl.aposWidgetPlayed = true;
|
|
86
|
-
}
|
|
87
|
-
},
|
|
88
66
|
clicked(e) {
|
|
89
67
|
// If you do not want a particular click to swap to the edit view
|
|
90
68
|
// for your widget, you should make sure it does not bubble
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "apostrophe",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.11.0",
|
|
4
4
|
"description": "The Apostrophe Content Management System.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -28,16 +28,16 @@
|
|
|
28
28
|
"license": "MIT",
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@apostrophecms/vue-color": "^2.8.2",
|
|
31
|
-
"@babel/core": "^7.
|
|
32
|
-
"@babel/preset-env": "^7.
|
|
31
|
+
"@babel/core": "^7.16.7",
|
|
32
|
+
"@babel/preset-env": "^7.16.7",
|
|
33
33
|
"@tiptap/extension-highlight": "^2.0.0-beta.13",
|
|
34
34
|
"@tiptap/extension-link": "^2.0.0-beta.17",
|
|
35
35
|
"@tiptap/extension-text-align": "^2.0.0-beta.17",
|
|
36
36
|
"@tiptap/extension-text-style": "^2.0.0-beta.13",
|
|
37
|
-
"@tiptap/extension-underline": "^2.0.0-beta.
|
|
38
|
-
"@tiptap/starter-kit": "^2.0.0-beta.
|
|
39
|
-
"@tiptap/vue-2": "^2.0.0-beta.
|
|
40
|
-
"autoprefixer": "^10.
|
|
37
|
+
"@tiptap/extension-underline": "^2.0.0-beta.22",
|
|
38
|
+
"@tiptap/starter-kit": "^2.0.0-beta.164",
|
|
39
|
+
"@tiptap/vue-2": "^2.0.0-beta.73",
|
|
40
|
+
"autoprefixer": "^10.4.1",
|
|
41
41
|
"babel-loader": "^8.2.2",
|
|
42
42
|
"bluebird": "^3.7.2",
|
|
43
43
|
"body-parser": "^1.18.2",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"he": "^0.5.0",
|
|
69
69
|
"html-to-text": "^5.1.1",
|
|
70
70
|
"i18next": "^20.3.2",
|
|
71
|
-
"i18next-http-middleware": "^3.1.
|
|
71
|
+
"i18next-http-middleware": "^3.1.5",
|
|
72
72
|
"import-fresh": "^3.3.0",
|
|
73
73
|
"is-wsl": "^2.2.0",
|
|
74
74
|
"jsdom": "^17.0.0",
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
"resolve": "^1.19.0",
|
|
96
96
|
"resolve-from": "^5.0.0",
|
|
97
97
|
"sanitize-html": "^2.0.0",
|
|
98
|
-
"sass": "^1.
|
|
98
|
+
"sass": "^1.45.2",
|
|
99
99
|
"sass-loader": "^10.1.1",
|
|
100
100
|
"server-destroy": "^1.0.1",
|
|
101
101
|
"sluggo": "^0.3.0",
|
|
@@ -110,7 +110,7 @@
|
|
|
110
110
|
"uploadfs": "^1.17.1",
|
|
111
111
|
"v-tooltip": "^2.0.3",
|
|
112
112
|
"vue": "^2.6.14",
|
|
113
|
-
"vue-click-outside-element": "^1.0.
|
|
113
|
+
"vue-click-outside-element": "^1.0.15",
|
|
114
114
|
"vue-loader": "^15.9.6",
|
|
115
115
|
"vue-material-design-icons": "~4.12.1",
|
|
116
116
|
"vue-style-loader": "^4.1.2",
|
package/test/moog.js
CHANGED
|
@@ -284,6 +284,54 @@ describe('moog', function() {
|
|
|
284
284
|
assert(myObject.fieldsGroups.basics.fields.includes('five'));
|
|
285
285
|
});
|
|
286
286
|
|
|
287
|
+
it('should order fields with the last option unless the order array overrides', async function() {
|
|
288
|
+
const moog = require('../lib/moog.js')({});
|
|
289
|
+
|
|
290
|
+
moog.define('unorderedObject', {
|
|
291
|
+
cascades: [ 'fields' ],
|
|
292
|
+
fields: {
|
|
293
|
+
add: {
|
|
294
|
+
first: { type: 'string' },
|
|
295
|
+
last: {
|
|
296
|
+
type: 'string',
|
|
297
|
+
last: true
|
|
298
|
+
},
|
|
299
|
+
second: { type: 'string' },
|
|
300
|
+
third: { type: 'string' }
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
moog.define('orderedObject', {
|
|
306
|
+
cascades: [ 'fields' ],
|
|
307
|
+
fields: {
|
|
308
|
+
add: {
|
|
309
|
+
first: { type: 'string' },
|
|
310
|
+
last: {
|
|
311
|
+
type: 'string',
|
|
312
|
+
last: true
|
|
313
|
+
},
|
|
314
|
+
second: { type: 'string' },
|
|
315
|
+
third: { type: 'string' }
|
|
316
|
+
},
|
|
317
|
+
order: [ 'last', 'third', 'second', 'first' ]
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
const unordered = await moog.create('unorderedObject', {});
|
|
321
|
+
assert(unordered);
|
|
322
|
+
assert(Object.keys(unordered.fields)[0] === 'first');
|
|
323
|
+
assert(Object.keys(unordered.fields)[1] === 'second');
|
|
324
|
+
assert(Object.keys(unordered.fields)[2] === 'third');
|
|
325
|
+
assert(Object.keys(unordered.fields)[3] === 'last');
|
|
326
|
+
|
|
327
|
+
const ordered = await moog.create('orderedObject', {});
|
|
328
|
+
assert(ordered);
|
|
329
|
+
assert(Object.keys(ordered.fields)[0] === 'last');
|
|
330
|
+
assert(Object.keys(ordered.fields)[1] === 'third');
|
|
331
|
+
assert(Object.keys(ordered.fields)[2] === 'second');
|
|
332
|
+
assert(Object.keys(ordered.fields)[3] === 'first');
|
|
333
|
+
});
|
|
334
|
+
|
|
287
335
|
// ==================================================
|
|
288
336
|
// `redefine` AND `isDefined`
|
|
289
337
|
// ==================================================
|
package/test-lib/util.js
CHANGED
|
@@ -43,12 +43,14 @@ async function create(options) {
|
|
|
43
43
|
};
|
|
44
44
|
// Automatically configure Express, but not if we're in a special
|
|
45
45
|
// environment where the default apostrophe modules don't initialize
|
|
46
|
+
// TODO: Remove __testDefaults references in 4.x major version or formalize
|
|
47
|
+
// intended usage with documentation.
|
|
46
48
|
if (!config.__testDefaults) {
|
|
47
49
|
config.modules = config.modules || {};
|
|
48
50
|
const express = config.modules['@apostrophecms/express'] || {};
|
|
49
51
|
express.options = express.options || {};
|
|
50
|
-
// Allow OS to choose open port
|
|
51
|
-
express.options.port = null;
|
|
52
|
+
// Allow OS to choose open port if not explicitly set.
|
|
53
|
+
express.options.port = express.options.port || null;
|
|
52
54
|
express.options.address = express.options.address || 'localhost';
|
|
53
55
|
express.options.session = express.options.session || {};
|
|
54
56
|
express.options.session.secret = express.options.session.secret || 'test';
|
package/.circleci/config.yml
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
version: 2
|
|
2
|
-
jobs:
|
|
3
|
-
build-node14-mongo5:
|
|
4
|
-
docker:
|
|
5
|
-
- image: circleci/node:14-browsers
|
|
6
|
-
- image: mongo:5.0
|
|
7
|
-
steps:
|
|
8
|
-
- checkout
|
|
9
|
-
- run:
|
|
10
|
-
name: update-npm
|
|
11
|
-
command: 'sudo npm install -g npm@7'
|
|
12
|
-
- restore_cache:
|
|
13
|
-
key: dependency-cache-{{ checksum "package.json" }}
|
|
14
|
-
- run:
|
|
15
|
-
name: install-npm-wee
|
|
16
|
-
command: npm install
|
|
17
|
-
- save_cache:
|
|
18
|
-
key: dependency-cache-{{ checksum "package.json" }}
|
|
19
|
-
paths:
|
|
20
|
-
- ./node_modules
|
|
21
|
-
- run:
|
|
22
|
-
name: test
|
|
23
|
-
command: npm test
|
|
24
|
-
build-node14-mongo44:
|
|
25
|
-
docker:
|
|
26
|
-
- image: circleci/node:14-browsers
|
|
27
|
-
- image: mongo:4.4
|
|
28
|
-
steps:
|
|
29
|
-
- checkout
|
|
30
|
-
- run:
|
|
31
|
-
name: update-npm
|
|
32
|
-
command: 'sudo npm install -g npm@7'
|
|
33
|
-
- restore_cache:
|
|
34
|
-
key: dependency-cache-{{ checksum "package.json" }}
|
|
35
|
-
- run:
|
|
36
|
-
name: install-npm-wee
|
|
37
|
-
command: npm install
|
|
38
|
-
- save_cache:
|
|
39
|
-
key: dependency-cache-{{ checksum "package.json" }}
|
|
40
|
-
paths:
|
|
41
|
-
- ./node_modules
|
|
42
|
-
- run:
|
|
43
|
-
name: test
|
|
44
|
-
command: npm test
|
|
45
|
-
build-node14-mongo42:
|
|
46
|
-
docker:
|
|
47
|
-
- image: circleci/node:14-browsers
|
|
48
|
-
- image: mongo:4.2
|
|
49
|
-
steps:
|
|
50
|
-
- checkout
|
|
51
|
-
- run:
|
|
52
|
-
name: update-npm
|
|
53
|
-
command: 'sudo npm install -g npm@7'
|
|
54
|
-
- restore_cache:
|
|
55
|
-
key: dependency-cache-{{ checksum "package.json" }}
|
|
56
|
-
- run:
|
|
57
|
-
name: install-npm-wee
|
|
58
|
-
command: npm install
|
|
59
|
-
- save_cache:
|
|
60
|
-
key: dependency-cache-{{ checksum "package.json" }}
|
|
61
|
-
paths:
|
|
62
|
-
- ./node_modules
|
|
63
|
-
- run:
|
|
64
|
-
name: test
|
|
65
|
-
command: npm test
|
|
66
|
-
build-node12:
|
|
67
|
-
docker:
|
|
68
|
-
- image: circleci/node:12-browsers
|
|
69
|
-
- image: mongo:3.6.11
|
|
70
|
-
steps:
|
|
71
|
-
- checkout
|
|
72
|
-
- run:
|
|
73
|
-
name: update-npm
|
|
74
|
-
command: "sudo npm install -g npm"
|
|
75
|
-
- restore_cache:
|
|
76
|
-
key: dependency-cache-{{ .Branch }}-{{ checksum "package-lock.json" }}
|
|
77
|
-
- run:
|
|
78
|
-
name: install-npm-wee
|
|
79
|
-
command: npm install
|
|
80
|
-
- save_cache:
|
|
81
|
-
key: dependency-cache-{{ .Branch }}-{{ checksum "package-lock.json" }}
|
|
82
|
-
paths:
|
|
83
|
-
- ./node_modules
|
|
84
|
-
- run:
|
|
85
|
-
name: test
|
|
86
|
-
command: npm test
|
|
87
|
-
workflows:
|
|
88
|
-
version: 2
|
|
89
|
-
build:
|
|
90
|
-
jobs:
|
|
91
|
-
- build-node14-mongo5
|
|
92
|
-
- build-node14-mongo44
|
|
93
|
-
- build-node14-mongo42
|
|
94
|
-
- build-node12
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
Please ensure your pull request follows these guidelines:
|
|
2
|
-
|
|
3
|
-
- [ ] Link to the related issue with requirements and/or clearly describe 1) what problem this solves and 2) the requirements to review it against.
|
|
4
|
-
- [ ] Update the `CHANGELOG.md` file with the added feature or fix. If there is not yet a heading for an upcoming release, add one following the established pattern.
|
|
5
|
-
- [ ] Keep the pull request minimal! Break large updates into separate pull requests for individual features/fixes whenever possible. Small requests get reviewed more quickly.
|
|
6
|
-
- [ ] All tests must pass, including the linters. Run `npm run lint` to test code linting independently.
|
|
7
|
-
|
|
8
|
-
Thanks for contributing!
|
package/.scratch.md
DELETED