-
Notifications
You must be signed in to change notification settings - Fork 615
add addMissingSchemaFields task #5101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 10 commits
b96e13e
4beeed2
c15a6e7
80a96aa
64576d9
eb623ec
4a6802a
8b81ab0
2bcf377
f33d52f
ba9d6b1
21a722a
90bc5f7
05e3214
a50f9ab
5580277
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,13 +14,28 @@ const addMissingSchemaFields = require('./lib/addMissingSchemaFields.js'); | |
| // is difficult to guarantee, you may wish to write a task instead. | ||
|
|
||
| module.exports = { | ||
| options: { alias: 'migration' }, | ||
| options: { | ||
| alias: 'migration', | ||
| skipMigrationTasks: [ | ||
| '@apostrophecms/migration:add-missing-schema-fields' | ||
| ] | ||
| }, | ||
| async init(self) { | ||
| self.migrations = []; | ||
| await self.enableCollection(); | ||
| }, | ||
| handlers(self) { | ||
| return { | ||
| [`${self.__meta.name}:before`]: { | ||
| setSkipMigration() { | ||
| if ( | ||
| self.apos.isTask() && | ||
| self.options.skipMigrationTasks.includes(self.apos.argv._.at(0)) | ||
| ) { | ||
| self.apos.skipMigration = true; | ||
| } | ||
| } | ||
| }, | ||
| 'apostrophe:ready': { | ||
| addSortifyMigrations() { | ||
| const managers = self.apos.doc.managers; | ||
|
|
@@ -237,6 +252,10 @@ module.exports = { | |
| // the @apostrophecms/migration:migrate task | ||
| async migrate(options) { | ||
| await self.emit('before'); | ||
|
||
| if (self.apos.skipMigration === true) { | ||
| return; | ||
| } | ||
|
|
||
| if (self.apos.isNew) { | ||
| // Since the site is brand new (zero documents), we may assume | ||
| // it requires no migrations. Mark them all as "done" but note | ||
|
|
@@ -305,6 +324,17 @@ module.exports = { | |
| // and automatically detect whether any work | ||
| // must be done | ||
| task: () => {} | ||
| }, | ||
| 'add-missing-schema-fields': { | ||
| usage: 'Add missing schema fields to existing database documents', | ||
| task: async () => { | ||
| const result = await self.addMissingSchemaFields(); | ||
| const migrations = await self.db.find().toArray(); | ||
| console.log({ | ||
| result, | ||
| migrations | ||
| }); | ||
| } | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| import config from './config.js'; | ||
| import apostrophe from '../../index.js'; | ||
|
|
||
| export default apostrophe(config); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| export default { | ||
| root: import.meta, | ||
| shortName: 'add-missing-schema-fields-project', | ||
| baseUrl: 'http://localhost:3000', | ||
| modules: { | ||
| '@apostrophecms/express': { | ||
| options: { | ||
| address: '127.0.0.1' | ||
| } | ||
| }, | ||
| product: {} | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| export default { | ||
| extend: '@apostrophecms/piece-type', | ||
| options: { | ||
| label: 'Product', | ||
| pluralLabel: 'Products' | ||
| }, | ||
| fields: { | ||
| add: { | ||
| price: { | ||
| type: 'float', | ||
| label: 'Price', | ||
| required: true | ||
| }, | ||
| description: { | ||
| type: 'string', | ||
| label: 'Description', | ||
| textarea: true, | ||
| required: true | ||
| }, | ||
| image: { | ||
| label: 'Product photo', | ||
| type: 'area', | ||
| options: { | ||
| max: 1, | ||
| widgets: { | ||
| '@apostrophecms/image': {} | ||
| } | ||
| } | ||
| }, | ||
| copyright: { | ||
| type: 'string', | ||
| label: 'Copyright' | ||
| } | ||
| }, | ||
| group: { | ||
| basics: { | ||
| label: 'Basics', | ||
| fields: [ 'title', 'price', 'description', 'image', 'copyright' ] | ||
| // 👆 'title' is included here because it is in the default `basics` | ||
| // group for all piece types. Since we are replacing that group, we | ||
| // include it ourselves. | ||
| } | ||
| } | ||
| }, | ||
| init(self) { | ||
| self.apos.migration.add('add-first-product', self.addFirstProduct); | ||
| self.apos.migration.add('add-copyright-notice', self.addCopyrightNotice); | ||
| }, | ||
| methods(self) { | ||
| return { | ||
| async addFirstProduct() { | ||
| await self.apos.modules.product.insert( | ||
| self.apos.task.getReq(), | ||
| { | ||
| ...self.apos.modules.product.newInstance(), | ||
| title: 'My first product', | ||
| price: 10.00, | ||
| description: 'Product description' | ||
| } | ||
| ); | ||
| }, | ||
| async addCopyrightNotice() { | ||
| await self.apos.migration.eachDoc({ | ||
| type: 'product' | ||
| }, async (doc) => { | ||
| if (doc.copyright === undefined) { | ||
| await self.apos.doc.db.updateOne({ | ||
| _id: doc._id | ||
| }, { | ||
| $set: { copyright: '©2024 ApostropheCMS. All rights reserved.' } | ||
| }); | ||
| } | ||
| }); | ||
| } | ||
| }; | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| { | ||
| "name": "add-missing-schema-fields-project", | ||
| "version": "1.0.0", | ||
| "description": "", | ||
| "main": "app.js", | ||
| "type": "module", | ||
| "scripts": { | ||
| "test": "echo \"Error: no test specified\" && exit 1" | ||
| }, | ||
| "keywords": [], | ||
| "author": "", | ||
| "license": "ISC", | ||
| "dependencies": { | ||
| "apostrophe": "file:../../." | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| import { strict as assert } from 'node:assert'; | ||
| import process from 'node:process'; | ||
| import path from 'node:path'; | ||
| import util from 'node:util'; | ||
| import { exec } from 'node:child_process'; | ||
| import t from '../../test-lib/test.js'; | ||
| import config from './config.js'; | ||
|
|
||
| describe('Apostrophe - add-missing-schema-fields task', function() { | ||
| this.timeout(t.timeout); | ||
|
|
||
| let apos; | ||
|
|
||
| before(async function() { | ||
| await util.promisify(exec)( | ||
| 'npm install', | ||
| { cwd: path.resolve(process.cwd(), 'test/add-missing-schema-fields-project/') } | ||
| ); | ||
| }); | ||
|
|
||
| afterEach(function() { | ||
| return t.destroy(apos); | ||
| }); | ||
|
|
||
| it('should not run migrations when running the task', async function() { | ||
| await util.promisify(exec)( | ||
| 'node app.js @apostrophecms/migration:add-missing-schema-fields', | ||
| { cwd: path.resolve(process.cwd(), 'test/add-missing-schema-fields-project/') } | ||
| ); | ||
|
|
||
| apos = await t.create({ | ||
| ...config, | ||
| root: import.meta, | ||
| modules: { | ||
| ...config.modules, | ||
| debug: { | ||
| handlers(self) { | ||
| return { | ||
| '@apostrophecms/migration:before': { | ||
| forceSkipMigration() { | ||
| self.apos.skipMigration = true; | ||
| } | ||
| } | ||
| }; | ||
| } | ||
| } | ||
| } | ||
| }); | ||
|
|
||
| const migrations = await apos.migration.db.find().toArray(); | ||
|
|
||
| const actual = { | ||
| migrations: migrations.map(migration => migration._id) | ||
| }; | ||
| const expected = { | ||
| migrations: [ '*lastPropLists' ] | ||
| }; | ||
|
|
||
| assert.deepEqual(actual, expected); | ||
| }); | ||
|
|
||
| it('should run migrations when running @apostrophecms/migration:migrate task', async function() { | ||
| await util.promisify(exec)( | ||
| 'node app.js @apostrophecms/migration:migrate', | ||
| { cwd: path.resolve(process.cwd(), 'test/add-missing-schema-fields-project/') } | ||
| ); | ||
|
|
||
| apos = await t.create({ | ||
| ...config, | ||
| root: import.meta, | ||
| modules: { | ||
| ...config.modules, | ||
| debug: { | ||
| handlers(self) { | ||
| return { | ||
| '@apostrophecms/migration:before': { | ||
| forceSkipMigration() { | ||
| self.apos.skipMigration = true; | ||
| } | ||
| } | ||
| }; | ||
| } | ||
| } | ||
| } | ||
| }); | ||
|
|
||
| const migrations = await apos.migration.db.find().toArray(); | ||
|
|
||
| const actual = { | ||
| migrations: migrations.map(migration => migration._id) | ||
| }; | ||
| const expected = { | ||
| migrations: [ '*lastPropLists' ].concat( | ||
| apos.migration.migrations.map(migration => migration.name) | ||
| ) | ||
| }; | ||
|
|
||
| assert.deepEqual(actual, expected); | ||
| }); | ||
|
|
||
| it('should run migrations when starting apostrophe', async function() { | ||
| apos = await t.create({ | ||
| ...config, | ||
| root: import.meta | ||
| }); | ||
|
|
||
| const migrations = await apos.migration.db.find().toArray(); | ||
|
|
||
| const actual = { | ||
| migrations: migrations.map(migration => migration._id) | ||
| }; | ||
| const expected = { | ||
| migrations: [ '*lastPropLists' ].concat( | ||
| apos.migration.migrations.map(migration => migration.name) | ||
| ) | ||
| }; | ||
|
|
||
| assert.deepEqual(actual, expected); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Recreating the section because this is not part of today's release, easier for me to handle future conflict.