From 3c4a0e465ed8ff91b53367b3878fb8f3eb31d36b Mon Sep 17 00:00:00 2001 From: Duncan Paterson Date: Wed, 3 Feb 2021 11:40:34 +0100 Subject: [PATCH 01/20] fix(libs): remove index config from scaffold close #608 --- README.md | 1 - generators/app/index.js | 12 ++++++------ test/generated-pkg/app-lib.js | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 304ee41f..76d8fda5 100644 --- a/README.md +++ b/README.md @@ -264,7 +264,6 @@ Since if would be impractical to go through all possible combinations of option │   ├── lib_demo-1.0.0-dev.xar │   └── lib_demo-1.0.0.xar ├── build.xml -├── collection.xconf ├── expath-pkg.xml ├── node_modules │   └── pruned … diff --git a/generators/app/index.js b/generators/app/index.js index 5ba9711d..3537b273 100644 --- a/generators/app/index.js +++ b/generators/app/index.js @@ -474,6 +474,12 @@ module.exports = class extends Generator { this.templatePath('img/icon.png'), this.destinationPath('icon.png') ) + this.fs.copyTpl( + this.templatePath('collection.xconf'), + this.destinationPath('collection.xconf'), { + apptype: this.props.apptype[0], + index: this.props.index + }) } // not polymer (flexible) if (this.props.apptype[0] !== 'empty') { @@ -600,12 +606,6 @@ module.exports = class extends Generator { website: this.props.website } ) - this.fs.copyTpl( - this.templatePath('collection.xconf'), - this.destinationPath('collection.xconf'), { - apptype: this.props.apptype[0], - index: this.props.index - }) } // Post-install if (this.props.post) { diff --git a/test/generated-pkg/app-lib.js b/test/generated-pkg/app-lib.js index 9b70560c..7c5e064d 100644 --- a/test/generated-pkg/app-lib.js +++ b/test/generated-pkg/app-lib.js @@ -21,7 +21,7 @@ describe('library package', function () { atom: false, ci: 'travis' }) - assert.noFile(['modules/app.xql', 'modules/test-suite.xql', 'templates/page.html', 'reports/screenshots/.gitkeep', 'controller.xql']) + assert.noFile(['modules/app.xql', 'modules/test-suite.xql', 'templates/page.html', 'reports/screenshots/.gitkeep', 'controller.xql', 'collection.xconf']) }) describe('library has', function () { From 4248f52f9be243922c75f7ce0dfaaeee49f9ab49 Mon Sep 17 00:00:00 2001 From: Duncan Paterson Date: Wed, 3 Feb 2021 13:59:55 +0100 Subject: [PATCH 02/20] chore(test): remove unused files adjust test see #603 --- test/generated-pkg/app-eXide-plain.js | 10 +++- test/generated-pkg/app-polymer-app.js | 57 ------------------ test/generated-pkg/app-polymer-element.js | 70 ----------------------- 3 files changed, 9 insertions(+), 128 deletions(-) delete mode 100644 test/generated-pkg/app-polymer-app.js delete mode 100644 test/generated-pkg/app-polymer-element.js diff --git a/test/generated-pkg/app-eXide-plain.js b/test/generated-pkg/app-eXide-plain.js index b827fda7..ba7b2e90 100644 --- a/test/generated-pkg/app-eXide-plain.js +++ b/test/generated-pkg/app-eXide-plain.js @@ -21,7 +21,10 @@ describe('eXide plain app', function () { ci: 'GitHub Action', docker: true, dockertag: '5.0.0', - atom: true + atom: true, + instance: 'http://localhost:8080/exist', + admin: 'admin', + adminpw: 'pw123' }) assert.noFile(['resources/images/bold.gif', 'pre-install.xql', 'test/cypress/integration/secure_spec.js', '.travis.yml']) }) @@ -37,6 +40,11 @@ describe('eXide plain app', function () { done() }) + it('atom file with clearly visible PW', function (done) { + assert.fileContent('.existdb.json', 'pw123') + done() + }) + it('dockerfile with expanded package name', function (done) { assert.fileContent('Dockerfile', 'foo-1.0.0.xar') done() diff --git a/test/generated-pkg/app-polymer-app.js b/test/generated-pkg/app-polymer-app.js deleted file mode 100644 index acfd891c..00000000 --- a/test/generated-pkg/app-polymer-app.js +++ /dev/null @@ -1,57 +0,0 @@ -'use strict' -const path = require('path') -const assert = require('yeoman-assert') -const helpers = require('yeoman-test') -const fs = require('fs-extra') - -describe.skip('polymer element', function () { - before(async function () { - this.timeout(30000) - await helpers.run(path.join(__dirname, '../../generators/app')) - .withPrompts({ - title: 'foo', - author: 'tester', - email: 'te@st.er', - apptype: ['polymer', 'application'], - polytempl: 'polymer-2-application:app', - name: 'foo-element', - pre: false, - post: false, - license: ['MIT', 'MIT', 'https://opensource.org/licenses/MIT'], - github: true, - atom: false - }) - assert.noFile(['templates/page.html', 'error-page.html', 'test/index.html']) - }) - - describe('polymer element has', function () { - it('polymer cli derived files', function (done) { - assert.file(['bower.json', 'README.md', 'index.html', 'polymer.json', 'test/foo-element/foo-element_test.html', '.gitignore', 'src/foo-element/foo-element.html', 'manifest.json']) - done() - }) - - it('expanded paths in gulpfile', function (done) { - assert.fileContent('gulpfile.js', 'db/apps/foo') - done() - }) - - it('polymer style index page', function (done) { - assert.fileContent('index.html', / Date: Wed, 3 Feb 2021 14:06:32 +0100 Subject: [PATCH 03/20] =?UTF-8?q?refactor(index.js):=20restore=20simpler?= =?UTF-8?q?=20logic=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …now that polymer is gone --- generators/app/index.js | 473 +++++++++++++++----------------- test/generated-pkg/app-empty.js | 2 +- 2 files changed, 229 insertions(+), 246 deletions(-) diff --git a/generators/app/index.js b/generators/app/index.js index 3537b273..0486d293 100644 --- a/generators/app/index.js +++ b/generators/app/index.js @@ -10,11 +10,11 @@ const pjson = require('../../package.json') // Potential location for teipub defaults. see https://github.com/enquirer/enquirer/issues/15 module.exports = class extends Generator { - initializing () { + initializing() { this.props = {} } - prompting () { + prompting() { // Have Yeoman greet the user. this.log(yosay( 'Welcome to the stupendous ' + chalk.blue('exist-app') + ' generator!' @@ -350,7 +350,7 @@ module.exports = class extends Generator { }) } - writing () { + writing() { // try to clean invalid xml from streams this.registerTransformStream( stripBom({ @@ -401,210 +401,249 @@ module.exports = class extends Generator { }, repository: '' } + // Applies to all (without prompts) // TODO #56 html -> xhtml - // Applies to all (build, expath-pkg, repo, xqs) + + // EXPATH this.fs.copyTpl( this.templatePath('build.xml'), this.destinationPath('build.xml'), { - apptype: this.props.apptype[0], - title: this.props.title, - github: this.props.github, - desc: this.props.desc, - gitfiles: ', README.md, **/.git*/**' - }) + apptype: this.props.apptype[0], + title: this.props.title, + github: this.props.github, + desc: this.props.desc, + gitfiles: ', README.md, **/.git*/**' + }) this.fs.copyTpl( this.templatePath('repo.xml'), this.destinationPath('repo.xml'), { - desc: this.props.desc, - short: this.props.short, - author: this.props.author, - apptype: this.props.apptype[1], - status: this.props.status, - pre: this.props.pre, - prexq: 'pre-install.xql', - post: this.props.post, - postxq: 'post-install.xql', - setperm: this.props.setperm, - website: this.props.website, - license: this.props.license[0], - owner: this.props.owner, - userpw: this.props.userpw, - group: this.props.group, - mode: this.props.mode - }) + desc: this.props.desc, + short: this.props.short, + author: this.props.author, + apptype: this.props.apptype[1], + status: this.props.status, + pre: this.props.pre, + prexq: 'pre-install.xql', + post: this.props.post, + postxq: 'post-install.xql', + setperm: this.props.setperm, + website: this.props.website, + license: this.props.license[0], + owner: this.props.owner, + userpw: this.props.userpw, + group: this.props.group, + mode: this.props.mode + }) this.fs.copyTpl( this.templatePath('expath-pkg.xml'), this.destinationPath('expath-pkg.xml'), { - short: this.props.short, - defcoll: this.props.defcoll, - defuri: this.props.defuri, - version: this.props.version, - desc: this.props.desc, - apptype: this.props.apptype[0] - }) + short: this.props.short, + defcoll: this.props.defcoll, + defuri: this.props.defuri, + version: this.props.version, + desc: this.props.desc, + apptype: this.props.apptype[0] + }) + // Unit Test this.fs.copyTpl( this.templatePath('tests/xqs/test-suite.xql'), this.destinationPath('test/xqs/test-suite.xql'), { - apptype: this.props.apptype[0], - short: this.props.short, - defcoll: this.props.defcoll, - defuri: this.props.defuri, - version: this.props.version, - author: this.props.author, - website: this.props.website, - title: this.props.title - }) + apptype: this.props.apptype[0], + short: this.props.short, + defcoll: this.props.defcoll, + defuri: this.props.defuri, + version: this.props.version, + author: this.props.author, + website: this.props.website, + title: this.props.title + }) this.fs.copyTpl( this.templatePath('tests/xqs/test-runner.xq'), this.destinationPath('test/xqs/test-runner.xq'), { - short: this.props.short, - defcoll: this.props.defcoll, - defuri: this.props.defuri, - version: this.props.version, - author: this.props.author, - title: this.props.title - }) + short: this.props.short, + defcoll: this.props.defcoll, + defuri: this.props.defuri, + version: this.props.version, + author: this.props.author, + title: this.props.title + }) - // all application packages (fixed) + this.fs.copy( + this.templatePath('tests/mocha/app_spec.js'), + this.destinationPath('test/mocha/app_spec.js') + ) + + this.fs.copyTpl( + this.templatePath('tests/mocha/rest_spec.js'), + this.destinationPath('test/mocha/rest_spec.js'), { + apptype: this.props.apptype[0], + short: this.props.short, + defcoll: this.props.defcoll + }) + + this.fs.copyTpl( + this.templatePath('tests/xqs/xqSuite.js'), + this.destinationPath('test/xqs/xqSuite.js'), { + apptype: this.props.apptype[1], + short: this.props.short, + defcoll: this.props.defcoll, + version: this.props.version + }) + + // all application packages, … if (this.props.apptype[1] === 'application') { this.fs.copy( this.templatePath('img/icon.png'), this.destinationPath('icon.png') ) + this.fs.copy( + this.templatePath('tests/cypress/'), + this.destinationPath('test/cypress/') + ) + + this.fs.copy( + this.templatePath('tests/cypress.json'), + this.destinationPath('cypress.json') + ) + + this.fs.copy( + this.templatePath('github/.gitkeep'), + this.destinationPath('reports/screenshots/.gitkeep') + ) + + this.fs.copy( + this.templatePath('github/.gitkeep'), + this.destinationPath('reports/videos/.gitkeep') + ) + this.fs.copyTpl( - this.templatePath('collection.xconf'), - this.destinationPath('collection.xconf'), { - apptype: this.props.apptype[0], - index: this.props.index - }) + this.templatePath('tests/integration/landing_spec.js'), + this.destinationPath('test/cypress/integration/landing_spec.js'), { + apptype: this.props.apptype[0], + short: this.props.short, + defcoll: this.props.defcoll, + desc: this.props.desc, + mysec: this.props.mysec + }) + + Object.assign(pkgJson.devDependencies, { + cypress: pjson.devDependencies.cypress + }) + + Object.assign(pkgJson.scripts, { + cypress: 'cypress run' + }) } - // not polymer (flexible) + // … except empty (flexible) if (this.props.apptype[0] !== 'empty') { this.fs.copyTpl( this.templatePath('pages/error-page.html'), this.destinationPath('error-page.html'), { - apptype: this.props.apptype[0] - }) - } - // secure area (mysec) - if (this.props.mysec) { - this.fs.copy( - this.templatePath('mysec/**'), - this.destinationPath('') - ) + apptype: this.props.apptype[0] + }) + this.fs.copyTpl( - this.templatePath('tests/integration/login-*_spec.js'), - this.destinationPath('test/cypress/integration/'), { - defcoll: this.props.defcoll, - short: this.props.short - } + this.templatePath('pages/index.html'), + this.destinationPath('index.html'), { + apptype: this.props.apptype[0] + }) + this.fs.copyTpl( + this.templatePath('style.css'), + this.destinationPath('resources/css/style.css'), { + apptype: this.props.apptype[0] + }) - ) - } - // distinct contents (flexible) - switch (this.props.apptype[0]) { - case 'exist-design': - this.fs.copy( - this.templatePath('exist-design/images/**'), - this.destinationPath('resources/images/') - ) - break - default: - } + this.fs.copyTpl( + this.templatePath('collection.xconf'), + this.destinationPath('collection.xconf'), { + apptype: this.props.apptype[0], + index: this.props.index + }) - // Plain and exist design stuff - if (this.props.apptype[0] !== 'empty') { // XQuery this.fs.copyTpl( this.templatePath('controller.xql'), this.destinationPath('controller.xql'), { - apptype: this.props.apptype[0], - mysec: this.props.mysec - }) + apptype: this.props.apptype[0], + mysec: this.props.mysec + }) this.fs.copyTpl( this.templatePath('view.xql'), this.destinationPath('modules/view.xql'), { - short: this.props.short, - defcoll: this.props.defcoll, - defuri: this.props.defuri, - apptype: this.props.apptype[0], - version: this.props.version - }) + short: this.props.short, + defcoll: this.props.defcoll, + defuri: this.props.defuri, + apptype: this.props.apptype[0], + version: this.props.version + }) this.fs.copyTpl( this.templatePath('app.xql'), this.destinationPath('modules/app.xql'), { - short: this.props.short, - defcoll: this.props.defcoll, - defuri: this.props.defuri, - apptype: this.props.apptype[0], - version: this.props.version, - author: this.props.author, - website: this.props.website, - title: this.props.title, - mysec: this.props.mysec - }) + short: this.props.short, + defcoll: this.props.defcoll, + defuri: this.props.defuri, + apptype: this.props.apptype[0], + version: this.props.version, + author: this.props.author, + website: this.props.website, + title: this.props.title, + mysec: this.props.mysec + }) this.fs.copyTpl( this.templatePath('config.xqm'), this.destinationPath('modules/config.xqm'), { - short: this.props.short, - defcoll: this.props.defcoll, - defuri: this.props.defuri, - apptype: this.props.apptype[0], - defview: this.props.defview, - index: this.props.index, - dataloc: this.props.dataloc, - datasrc: this.props.datasrc, - odd: this.props.odd - }) + short: this.props.short, + defcoll: this.props.defcoll, + defuri: this.props.defuri, + apptype: this.props.apptype[0], + defview: this.props.defview, + index: this.props.index, + dataloc: this.props.dataloc, + datasrc: this.props.datasrc, + odd: this.props.odd + }) - // Page.html + // distinct contents (flexible) // see #28 switch (this.props.apptype[0]) { case 'exist-design': this.fs.copyTpl( this.templatePath('exist-design/page.html'), this.destinationPath('templates/page.html'), { - title: this.props.title, - mysec: this.props.mysec - }) + title: this.props.title, + mysec: this.props.mysec + }) + this.fs.copy( + this.templatePath('exist-design/images/**'), + this.destinationPath('resources/images/') + ) break case 'plain': this.fs.copyTpl( this.templatePath('exist-plain/page.html'), this.destinationPath('templates/page.html'), { - title: this.props.title, - mysec: this.props.mysec - }) + title: this.props.title, + mysec: this.props.mysec + }) break default: } - if (this.props.apptype[1] === 'application') { - this.fs.copyTpl( - this.templatePath('pages/index.html'), - this.destinationPath('index.html'), { - apptype: this.props.apptype[0] - }) - this.fs.copyTpl( - this.templatePath('style.css'), - this.destinationPath('resources/css/style.css'), { - apptype: this.props.apptype[0] - }) - } } + // Prompt based // Pre-install if (this.props.pre) { this.fs.copyTpl( this.templatePath('pre-install.xql'), this.destinationPath('pre-install.xql'), { - version: this.props.version, - author: this.props.author, - website: this.props.website - } + version: this.props.version, + author: this.props.author, + website: this.props.website + } ) } // Post-install @@ -612,14 +651,29 @@ module.exports = class extends Generator { this.fs.copyTpl( this.templatePath('post-install.xql'), this.destinationPath('post-install.xql'), { - apptype: this.props.apptype[0], - version: this.props.version, - author: this.props.author, - website: this.props.website - }) + apptype: this.props.apptype[0], + version: this.props.version, + author: this.props.author, + website: this.props.website + }) + } + + // Secure area (mysec) + if (this.props.mysec) { + this.fs.copy( + this.templatePath('mysec/**'), + this.destinationPath('') + ) + this.fs.copyTpl( + this.templatePath('tests/integration/login-*_spec.js'), + this.destinationPath('test/cypress/integration/'), { + defcoll: this.props.defcoll, + short: this.props.short + }) } // Github + // TODO #601 if (this.props.github) { this.fs.copy( this.templatePath('github/__gitignore__'), @@ -642,28 +696,28 @@ module.exports = class extends Generator { this.fs.copyTpl( this.templatePath('github/readme.md'), this.destinationPath('README.md'), { - apptype: this.props.apptype[0], - title: this.props.title, - desc: this.props.desc, - version: this.props.version, - ghuser: this.props.ghuser, - website: this.props.website, - author: this.props.author, - license: this.props.license[0], - badge: this.props.license[1], - badgelink: this.props.license[2], - ci: this.props.ci - }) + apptype: this.props.apptype[0], + title: this.props.title, + desc: this.props.desc, + version: this.props.version, + ghuser: this.props.ghuser, + website: this.props.website, + author: this.props.author, + license: this.props.license[0], + badge: this.props.license[1], + badgelink: this.props.license[2], + ci: this.props.ci + }) this.fs.copyTpl( this.templatePath('github/contributing.md'), this.destinationPath('.github/CONTRIBUTING.md'), { - title: this.props.title - }) + title: this.props.title + }) this.fs.copyTpl( this.templatePath('github/ISSUE_TEMPLATE.md'), this.destinationPath('.github/ISSUE_TEMPLATE/bug_report.md'), { - title: this.props.title - }) + title: this.props.title + }) // insert responses into pkgJson Object.assign(pkgJson, { homepage: 'https://github.com/' + this.props.ghuser + '/' + this.props.title.toLowerCase() + '#readme' @@ -683,10 +737,10 @@ module.exports = class extends Generator { this.fs.copyTpl( this.templatePath('Dockerfile'), this.destinationPath('Dockerfile'), { - dockertag: this.props.dockertag, - title: this.props.title, - version: this.props.version - }) + dockertag: this.props.dockertag, + title: this.props.title, + version: this.props.version + }) } // Atom @@ -694,12 +748,12 @@ module.exports = class extends Generator { this.fs.copyTpl( this.templatePath('.existdb.json'), this.destinationPath('.existdb.json'), { - short: this.props.short, - defcoll: this.props.defcoll, - instance: this.props.instance, - admin: this.props.admin, - adminpw: this.props.adminpw - }) + short: this.props.short, + defcoll: this.props.defcoll, + instance: this.props.instance, + admin: this.props.admin, + adminpw: this.props.adminpw + }) } // CI @@ -708,94 +762,23 @@ module.exports = class extends Generator { this.fs.copyTpl( this.templatePath('ci/.travis.yml'), this.destinationPath('.travis.yml'), { - apptype: this.props.apptype[1] - }) + apptype: this.props.apptype[1] + }) break default: this.fs.copyTpl( this.templatePath('ci/exist.yml'), this.destinationPath('.github/workflows/exist.yml'), { - apptype: this.props.apptype[1] - } - ) - } - - // no prompt - // TODO these will need to be adapted for polymer apps - // Mocha - this.fs.copy( - this.templatePath('tests/mocha/app_spec.js'), - this.destinationPath('test/mocha/app_spec.js') - ) - - this.fs.copyTpl( - this.templatePath('tests/mocha/rest_spec.js'), - this.destinationPath('test/mocha/rest_spec.js'), { - apptype: this.props.apptype[0], - short: this.props.short, - defcoll: this.props.defcoll - }) - - this.fs.copyTpl( - this.templatePath('tests/xqs/xqSuite.js'), - this.destinationPath('test/xqs/xqSuite.js'), { - apptype: this.props.apptype[1], - short: this.props.short, - defcoll: this.props.defcoll, - version: this.props.version - }) - - // Cypress - switch (this.props.apptype[1]) { - case 'application': - if (this.props.apptype[0] === 'exist-design' || this.props.apptype[0] === 'plain' || this.props.apptype[0] === 'empty') { - this.fs.copy( - this.templatePath('tests/cypress/'), - this.destinationPath('test/cypress/') - ) - - this.fs.copy( - this.templatePath('tests/cypress.json'), - this.destinationPath('cypress.json') - ) - - this.fs.copy( - this.templatePath('github/.gitkeep'), - this.destinationPath('reports/screenshots/.gitkeep') - ) - - this.fs.copy( - this.templatePath('github/.gitkeep'), - this.destinationPath('reports/videos/.gitkeep') - ) - - this.fs.copyTpl( - this.templatePath('tests/integration/landing_spec.js'), - this.destinationPath('test/cypress/integration/landing_spec.js'), { - apptype: this.props.apptype[0], - short: this.props.short, - defcoll: this.props.defcoll, - desc: this.props.desc, - mysec: this.props.mysec - }) - - Object.assign(pkgJson.devDependencies, { - cypress: pjson.devDependencies.cypress - }) - - Object.assign(pkgJson.scripts, { - cypress: 'cypress run' - }) + apptype: this.props.apptype[1] } - break - default: + ) } // Write the constructed pkgJson this.fs.writeJSON(this.destinationPath('package.json'), pkgJson) } - install () { + install() { this.installDependencies({ npm: true, bower: false, @@ -803,7 +786,7 @@ module.exports = class extends Generator { }) } - end () { + end() { if (this.props.github) { this.spawnCommandSync('git', ['init']) this.spawnCommandSync('git', ['add', '--all']) diff --git a/test/generated-pkg/app-empty.js b/test/generated-pkg/app-empty.js index 7b9431f1..a142ed48 100644 --- a/test/generated-pkg/app-empty.js +++ b/test/generated-pkg/app-empty.js @@ -19,7 +19,7 @@ describe('empty package', function () { github: false, atom: false }) - assert.noFile(['modules/app.xql', 'templates/page.html'], 'test/cypress/integration/login-ok_spec.js') + assert.noFile(['modules/app.xql', 'templates/page.html', 'test/cypress/integration/login-ok_spec.js', 'index.html']) }) describe('empty has', function () { From d77742bebf08250bb9b3128a92cdad4f698fc5fa Mon Sep 17 00:00:00 2001 From: Duncan Paterson Date: Wed, 3 Feb 2021 14:29:50 +0100 Subject: [PATCH 04/20] feat(docker): generate dockerignore rm dockerfiles from production xar close #604 --- generators/app/index.js | 310 +++++++++++++------------ generators/app/templates/.dockerignore | 5 + generators/app/templates/build.xml | 2 +- test/generated-pkg/app-eXide-plain.js | 2 +- 4 files changed, 165 insertions(+), 154 deletions(-) create mode 100644 generators/app/templates/.dockerignore diff --git a/generators/app/index.js b/generators/app/index.js index 0486d293..ead8b8d9 100644 --- a/generators/app/index.js +++ b/generators/app/index.js @@ -10,11 +10,11 @@ const pjson = require('../../package.json') // Potential location for teipub defaults. see https://github.com/enquirer/enquirer/issues/15 module.exports = class extends Generator { - initializing() { + initializing () { this.props = {} } - prompting() { + prompting () { // Have Yeoman greet the user. this.log(yosay( 'Welcome to the stupendous ' + chalk.blue('exist-app') + ' generator!' @@ -350,7 +350,7 @@ module.exports = class extends Generator { }) } - writing() { + writing () { // try to clean invalid xml from streams this.registerTransformStream( stripBom({ @@ -408,68 +408,70 @@ module.exports = class extends Generator { this.fs.copyTpl( this.templatePath('build.xml'), this.destinationPath('build.xml'), { - apptype: this.props.apptype[0], - title: this.props.title, - github: this.props.github, - desc: this.props.desc, - gitfiles: ', README.md, **/.git*/**' - }) + apptype: this.props.apptype[0], + title: this.props.title, + github: this.props.github, + desc: this.props.desc, + docker: this.props.docker, + dockerfiles: ', Dockerfile, .dockerignore', + gitfiles: ', README.md, **/.git*/**' + }) this.fs.copyTpl( this.templatePath('repo.xml'), this.destinationPath('repo.xml'), { - desc: this.props.desc, - short: this.props.short, - author: this.props.author, - apptype: this.props.apptype[1], - status: this.props.status, - pre: this.props.pre, - prexq: 'pre-install.xql', - post: this.props.post, - postxq: 'post-install.xql', - setperm: this.props.setperm, - website: this.props.website, - license: this.props.license[0], - owner: this.props.owner, - userpw: this.props.userpw, - group: this.props.group, - mode: this.props.mode - }) + desc: this.props.desc, + short: this.props.short, + author: this.props.author, + apptype: this.props.apptype[1], + status: this.props.status, + pre: this.props.pre, + prexq: 'pre-install.xql', + post: this.props.post, + postxq: 'post-install.xql', + setperm: this.props.setperm, + website: this.props.website, + license: this.props.license[0], + owner: this.props.owner, + userpw: this.props.userpw, + group: this.props.group, + mode: this.props.mode + }) this.fs.copyTpl( this.templatePath('expath-pkg.xml'), this.destinationPath('expath-pkg.xml'), { - short: this.props.short, - defcoll: this.props.defcoll, - defuri: this.props.defuri, - version: this.props.version, - desc: this.props.desc, - apptype: this.props.apptype[0] - }) + short: this.props.short, + defcoll: this.props.defcoll, + defuri: this.props.defuri, + version: this.props.version, + desc: this.props.desc, + apptype: this.props.apptype[0] + }) // Unit Test this.fs.copyTpl( this.templatePath('tests/xqs/test-suite.xql'), this.destinationPath('test/xqs/test-suite.xql'), { - apptype: this.props.apptype[0], - short: this.props.short, - defcoll: this.props.defcoll, - defuri: this.props.defuri, - version: this.props.version, - author: this.props.author, - website: this.props.website, - title: this.props.title - }) + apptype: this.props.apptype[0], + short: this.props.short, + defcoll: this.props.defcoll, + defuri: this.props.defuri, + version: this.props.version, + author: this.props.author, + website: this.props.website, + title: this.props.title + }) this.fs.copyTpl( this.templatePath('tests/xqs/test-runner.xq'), this.destinationPath('test/xqs/test-runner.xq'), { - short: this.props.short, - defcoll: this.props.defcoll, - defuri: this.props.defuri, - version: this.props.version, - author: this.props.author, - title: this.props.title - }) + short: this.props.short, + defcoll: this.props.defcoll, + defuri: this.props.defuri, + version: this.props.version, + author: this.props.author, + title: this.props.title + }) this.fs.copy( this.templatePath('tests/mocha/app_spec.js'), @@ -479,19 +481,19 @@ module.exports = class extends Generator { this.fs.copyTpl( this.templatePath('tests/mocha/rest_spec.js'), this.destinationPath('test/mocha/rest_spec.js'), { - apptype: this.props.apptype[0], - short: this.props.short, - defcoll: this.props.defcoll - }) + apptype: this.props.apptype[0], + short: this.props.short, + defcoll: this.props.defcoll + }) this.fs.copyTpl( this.templatePath('tests/xqs/xqSuite.js'), this.destinationPath('test/xqs/xqSuite.js'), { - apptype: this.props.apptype[1], - short: this.props.short, - defcoll: this.props.defcoll, - version: this.props.version - }) + apptype: this.props.apptype[1], + short: this.props.short, + defcoll: this.props.defcoll, + version: this.props.version + }) // all application packages, … if (this.props.apptype[1] === 'application') { @@ -522,12 +524,12 @@ module.exports = class extends Generator { this.fs.copyTpl( this.templatePath('tests/integration/landing_spec.js'), this.destinationPath('test/cypress/integration/landing_spec.js'), { - apptype: this.props.apptype[0], - short: this.props.short, - defcoll: this.props.defcoll, - desc: this.props.desc, - mysec: this.props.mysec - }) + apptype: this.props.apptype[0], + short: this.props.short, + defcoll: this.props.defcoll, + desc: this.props.desc, + mysec: this.props.mysec + }) Object.assign(pkgJson.devDependencies, { cypress: pjson.devDependencies.cypress @@ -542,70 +544,70 @@ module.exports = class extends Generator { this.fs.copyTpl( this.templatePath('pages/error-page.html'), this.destinationPath('error-page.html'), { - apptype: this.props.apptype[0] - }) + apptype: this.props.apptype[0] + }) this.fs.copyTpl( this.templatePath('pages/index.html'), this.destinationPath('index.html'), { - apptype: this.props.apptype[0] - }) + apptype: this.props.apptype[0] + }) this.fs.copyTpl( this.templatePath('style.css'), this.destinationPath('resources/css/style.css'), { - apptype: this.props.apptype[0] - }) + apptype: this.props.apptype[0] + }) this.fs.copyTpl( this.templatePath('collection.xconf'), this.destinationPath('collection.xconf'), { - apptype: this.props.apptype[0], - index: this.props.index - }) + apptype: this.props.apptype[0], + index: this.props.index + }) // XQuery this.fs.copyTpl( this.templatePath('controller.xql'), this.destinationPath('controller.xql'), { - apptype: this.props.apptype[0], - mysec: this.props.mysec - }) + apptype: this.props.apptype[0], + mysec: this.props.mysec + }) this.fs.copyTpl( this.templatePath('view.xql'), this.destinationPath('modules/view.xql'), { - short: this.props.short, - defcoll: this.props.defcoll, - defuri: this.props.defuri, - apptype: this.props.apptype[0], - version: this.props.version - }) + short: this.props.short, + defcoll: this.props.defcoll, + defuri: this.props.defuri, + apptype: this.props.apptype[0], + version: this.props.version + }) this.fs.copyTpl( this.templatePath('app.xql'), this.destinationPath('modules/app.xql'), { - short: this.props.short, - defcoll: this.props.defcoll, - defuri: this.props.defuri, - apptype: this.props.apptype[0], - version: this.props.version, - author: this.props.author, - website: this.props.website, - title: this.props.title, - mysec: this.props.mysec - }) + short: this.props.short, + defcoll: this.props.defcoll, + defuri: this.props.defuri, + apptype: this.props.apptype[0], + version: this.props.version, + author: this.props.author, + website: this.props.website, + title: this.props.title, + mysec: this.props.mysec + }) this.fs.copyTpl( this.templatePath('config.xqm'), this.destinationPath('modules/config.xqm'), { - short: this.props.short, - defcoll: this.props.defcoll, - defuri: this.props.defuri, - apptype: this.props.apptype[0], - defview: this.props.defview, - index: this.props.index, - dataloc: this.props.dataloc, - datasrc: this.props.datasrc, - odd: this.props.odd - }) + short: this.props.short, + defcoll: this.props.defcoll, + defuri: this.props.defuri, + apptype: this.props.apptype[0], + defview: this.props.defview, + index: this.props.index, + dataloc: this.props.dataloc, + datasrc: this.props.datasrc, + odd: this.props.odd + }) // distinct contents (flexible) // see #28 @@ -614,9 +616,9 @@ module.exports = class extends Generator { this.fs.copyTpl( this.templatePath('exist-design/page.html'), this.destinationPath('templates/page.html'), { - title: this.props.title, - mysec: this.props.mysec - }) + title: this.props.title, + mysec: this.props.mysec + }) this.fs.copy( this.templatePath('exist-design/images/**'), this.destinationPath('resources/images/') @@ -626,9 +628,9 @@ module.exports = class extends Generator { this.fs.copyTpl( this.templatePath('exist-plain/page.html'), this.destinationPath('templates/page.html'), { - title: this.props.title, - mysec: this.props.mysec - }) + title: this.props.title, + mysec: this.props.mysec + }) break default: } @@ -640,10 +642,10 @@ module.exports = class extends Generator { this.fs.copyTpl( this.templatePath('pre-install.xql'), this.destinationPath('pre-install.xql'), { - version: this.props.version, - author: this.props.author, - website: this.props.website - } + version: this.props.version, + author: this.props.author, + website: this.props.website + } ) } // Post-install @@ -651,11 +653,11 @@ module.exports = class extends Generator { this.fs.copyTpl( this.templatePath('post-install.xql'), this.destinationPath('post-install.xql'), { - apptype: this.props.apptype[0], - version: this.props.version, - author: this.props.author, - website: this.props.website - }) + apptype: this.props.apptype[0], + version: this.props.version, + author: this.props.author, + website: this.props.website + }) } // Secure area (mysec) @@ -667,9 +669,9 @@ module.exports = class extends Generator { this.fs.copyTpl( this.templatePath('tests/integration/login-*_spec.js'), this.destinationPath('test/cypress/integration/'), { - defcoll: this.props.defcoll, - short: this.props.short - }) + defcoll: this.props.defcoll, + short: this.props.short + }) } // Github @@ -696,28 +698,28 @@ module.exports = class extends Generator { this.fs.copyTpl( this.templatePath('github/readme.md'), this.destinationPath('README.md'), { - apptype: this.props.apptype[0], - title: this.props.title, - desc: this.props.desc, - version: this.props.version, - ghuser: this.props.ghuser, - website: this.props.website, - author: this.props.author, - license: this.props.license[0], - badge: this.props.license[1], - badgelink: this.props.license[2], - ci: this.props.ci - }) + apptype: this.props.apptype[0], + title: this.props.title, + desc: this.props.desc, + version: this.props.version, + ghuser: this.props.ghuser, + website: this.props.website, + author: this.props.author, + license: this.props.license[0], + badge: this.props.license[1], + badgelink: this.props.license[2], + ci: this.props.ci + }) this.fs.copyTpl( this.templatePath('github/contributing.md'), this.destinationPath('.github/CONTRIBUTING.md'), { - title: this.props.title - }) + title: this.props.title + }) this.fs.copyTpl( this.templatePath('github/ISSUE_TEMPLATE.md'), this.destinationPath('.github/ISSUE_TEMPLATE/bug_report.md'), { - title: this.props.title - }) + title: this.props.title + }) // insert responses into pkgJson Object.assign(pkgJson, { homepage: 'https://github.com/' + this.props.ghuser + '/' + this.props.title.toLowerCase() + '#readme' @@ -734,13 +736,17 @@ module.exports = class extends Generator { // DOCKER if (this.props.docker) { + this.fs.copy( + this.templatePath('.dockerignore'), + this.destinationPath('.dockerignore') + ) this.fs.copyTpl( this.templatePath('Dockerfile'), this.destinationPath('Dockerfile'), { - dockertag: this.props.dockertag, - title: this.props.title, - version: this.props.version - }) + dockertag: this.props.dockertag, + title: this.props.title, + version: this.props.version + }) } // Atom @@ -748,12 +754,12 @@ module.exports = class extends Generator { this.fs.copyTpl( this.templatePath('.existdb.json'), this.destinationPath('.existdb.json'), { - short: this.props.short, - defcoll: this.props.defcoll, - instance: this.props.instance, - admin: this.props.admin, - adminpw: this.props.adminpw - }) + short: this.props.short, + defcoll: this.props.defcoll, + instance: this.props.instance, + admin: this.props.admin, + adminpw: this.props.adminpw + }) } // CI @@ -762,15 +768,15 @@ module.exports = class extends Generator { this.fs.copyTpl( this.templatePath('ci/.travis.yml'), this.destinationPath('.travis.yml'), { - apptype: this.props.apptype[1] - }) + apptype: this.props.apptype[1] + }) break default: this.fs.copyTpl( this.templatePath('ci/exist.yml'), this.destinationPath('.github/workflows/exist.yml'), { - apptype: this.props.apptype[1] - } + apptype: this.props.apptype[1] + } ) } @@ -778,7 +784,7 @@ module.exports = class extends Generator { this.fs.writeJSON(this.destinationPath('package.json'), pkgJson) } - install() { + install () { this.installDependencies({ npm: true, bower: false, @@ -786,7 +792,7 @@ module.exports = class extends Generator { }) } - end() { + end () { if (this.props.github) { this.spawnCommandSync('git', ['init']) this.spawnCommandSync('git', ['add', '--all']) diff --git a/generators/app/templates/.dockerignore b/generators/app/templates/.dockerignore new file mode 100644 index 00000000..5fea1ca4 --- /dev/null +++ b/generators/app/templates/.dockerignore @@ -0,0 +1,5 @@ +.git/ + +.existdb.json + +yo-rc.json \ No newline at end of file diff --git a/generators/app/templates/build.xml b/generators/app/templates/build.xml index 119954c6..1defd2a1 100644 --- a/generators/app/templates/build.xml +++ b/generators/app/templates/build.xml @@ -19,7 +19,7 @@ - + diff --git a/test/generated-pkg/app-eXide-plain.js b/test/generated-pkg/app-eXide-plain.js index ba7b2e90..8c6818e5 100644 --- a/test/generated-pkg/app-eXide-plain.js +++ b/test/generated-pkg/app-eXide-plain.js @@ -31,7 +31,7 @@ describe('eXide plain app', function () { describe('plain package has', function () { it('recommended files', function (done) { - assert.file(['expath-pkg.xml', 'modules/config.xqm', 'test/xqs/test-runner.xq', 'controller.xql', 'Dockerfile']) + assert.file(['expath-pkg.xml', 'modules/config.xqm', 'test/xqs/test-runner.xq', 'controller.xql', '.dockerignore']) done() }) From 582ed355b042625807f3f62ae2335235764ecce5 Mon Sep 17 00:00:00 2001 From: Duncan Paterson Date: Fri, 5 Feb 2021 10:18:09 +0100 Subject: [PATCH 05/20] doc(readme): opening command ns fix --- README.md | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 76d8fda5..104409a0 100644 --- a/README.md +++ b/README.md @@ -49,17 +49,20 @@ mkdir myApp cd myApp ``` -Then run the generator. If you installed from source or GitHub, +Then run the generator: +- If you installed from a fork or from GitHub. -```bash -yo exist -``` + ```bash + yo exist + ``` -or if you installed from npm: +- If you installed from npm or from a clone of this repo. -```bash -yo @existdb/exist -``` + ```bash + yo @existdb/exist + ``` + +If you are unsure about which command is right simply run `yo` to see the list of currently installed generators. [![asciicast](https://asciinema.org/a/MqB6TyzdyBJImItHLsfC99Ufj.png)](https://asciinema.org/a/MqB6TyzdyBJImItHLsfC99Ufj) From 637d038876dbedf48532701af20057fbfbfd644c Mon Sep 17 00:00:00 2001 From: Duncan Paterson Date: Tue, 2 Feb 2021 16:24:17 +0100 Subject: [PATCH 06/20] chore(various): prepare gulp builds add inlines, template file, and test hints see Make builder configurable #563 supersedes #582 --- generators/app/index.js | 16 +++++++--------- generators/app/templates/gulpfile.js | 5 +++++ test/generated-pkg/app-empty.js | 2 ++ 3 files changed, 14 insertions(+), 9 deletions(-) create mode 100644 generators/app/templates/gulpfile.js diff --git a/generators/app/index.js b/generators/app/index.js index ead8b8d9..4ba2619c 100644 --- a/generators/app/index.js +++ b/generators/app/index.js @@ -6,9 +6,6 @@ const prettyData = require('gulp-pretty-data') const stripBom = require('gulp-stripbom') const pjson = require('../../package.json') -// Var isodate = (new Date()).toISOString(); - -// Potential location for teipub defaults. see https://github.com/enquirer/enquirer/issues/15 module.exports = class extends Generator { initializing () { this.props = {} @@ -77,10 +74,10 @@ module.exports = class extends Generator { value: ['empty', 'library'] }] }, - // TODO: [yo] Make these options meaningful + // TODO: [gulp] line-o promp user for build system // { // type: 'checkbox', - // choices: ['ant', 'gulp', 'maven', 'gradle'], + // choices: ['ant', 'gulp'], // name: 'builder', // message: 'How would you like to build your app?', // default: 'ant' @@ -330,7 +327,7 @@ module.exports = class extends Generator { }] // TODO: [yo]: js, css, gulp, funcdoc, - // TODO: [gulp] https://github.com/bnjjj/generator-gulpfile-advanced + // TODO: TODO: [gulp] line-o we could also extend this module https://github.com/bnjjj/generator-gulpfile-advanced return this.prompt(prompts).then(props => { // To access props later use this.props.someAnswer; @@ -401,10 +398,10 @@ module.exports = class extends Generator { }, repository: '' } - // Applies to all (without prompts) - // TODO #56 html -> xhtml - // EXPATH + // Applies to all (build, expath-pkg, repo, xqs) + // TODO #56 html -> xhtml + // TODO: [gulp] line-o here build.xml is copied for all outputs by default needs to become conditional this.fs.copyTpl( this.templatePath('build.xml'), this.destinationPath('build.xml'), { @@ -798,6 +795,7 @@ module.exports = class extends Generator { this.spawnCommandSync('git', ['add', '--all']) this.spawnCommandSync('git', ['commit', '-q', '-m', '\'initial scaffolding by Yeoman\'']) } + // TODO: [gulp] line-o make conditional on selected build tool this.spawnCommandSync('ant', '-q') console.log(yosay('I believe we\'re done here.')) diff --git a/generators/app/templates/gulpfile.js b/generators/app/templates/gulpfile.js new file mode 100644 index 00000000..be028cb9 --- /dev/null +++ b/generators/app/templates/gulpfile.js @@ -0,0 +1,5 @@ +// TODO: line-o tell me what you want what you really really … +// see https://docs.google.com/document/d/1UdSWERC9rCSYIYjTGgCr3avce47h5OeLFR4tGKYXZlM/edit#heading=h.ei4sqy3ojpkl +// see https://github.com/line-o/gulp-exist-example/blob/main/gulpfile.js +// see https://github.com/eXist-db/documentation/blob/master/Gulpfile.js +// see #563 diff --git a/test/generated-pkg/app-empty.js b/test/generated-pkg/app-empty.js index a142ed48..d2cbbe71 100644 --- a/test/generated-pkg/app-empty.js +++ b/test/generated-pkg/app-empty.js @@ -6,6 +6,8 @@ const fs = require('fs-extra') describe('empty package', function () { this.timeout(15000) + // TODO: #563 [gulp] line-o let's make this the test application for pure gulp build + // We should also add a app-lib-gulp.js test package. before(async function () { await helpers.run(path.join(__dirname, '../../generators/app')) .withPrompts({ From 13c81e4626ea27b8ccfcf5226dcb6a9107f2fc1d Mon Sep 17 00:00:00 2001 From: Duncan Paterson Date: Sat, 6 Feb 2021 10:08:45 +0100 Subject: [PATCH 07/20] chore(.exist.json): refactor json not yet at the latest hotness --- generators/app/templates/.existdb.json | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/generators/app/templates/.existdb.json b/generators/app/templates/.existdb.json index d44528d6..c1730280 100644 --- a/generators/app/templates/.existdb.json +++ b/generators/app/templates/.existdb.json @@ -3,20 +3,19 @@ "localhost": { "server": "<%- instance %>", "user": "<%- admin %>", - "password": "<%- adminpw %>" + "password": "<%- adminpw %>", + "root": "/db/<%- defcoll %>/<%- short %>" } }, "sync": { "server": "localhost", - "root": "/db/<%- defcoll %>/<%- short %>", "active": true, "ignore": [ ".existdb.json", ".git/**", "node_modules/**", - "bower_components/**", "build/**", - "webtest/**", + ".vscode/**", "README.md", "yo-rc.json" ] From 0008fd62ffcce61a0381f0976ab49d592bf3010e Mon Sep 17 00:00:00 2001 From: Duncan Paterson Date: Sat, 6 Feb 2021 15:07:05 +0100 Subject: [PATCH 08/20] feat(gulp): activate builder prompt hybrid (for backwards compatibility) gulp (for pure JS builds) ant (supports java) see #563 --- generators/app/index.js | 188 +++++---- generators/app/templates/build.xml | 28 -- generators/app/templates/builder/build.xml | 45 ++ generators/app/templates/builder/gulpfile.js | 255 ++++++++++++ generators/app/templates/gulpfile.js | 5 - package-lock.json | 416 ++++++++++++++++++- package.json | 5 + test/generated-pkg/app-eXide-default.js | 6 + test/generated-pkg/app-empty.js | 10 +- 9 files changed, 833 insertions(+), 125 deletions(-) delete mode 100644 generators/app/templates/build.xml create mode 100644 generators/app/templates/builder/build.xml create mode 100644 generators/app/templates/builder/gulpfile.js delete mode 100644 generators/app/templates/gulpfile.js diff --git a/generators/app/index.js b/generators/app/index.js index 4ba2619c..8ecdee0e 100644 --- a/generators/app/index.js +++ b/generators/app/index.js @@ -74,14 +74,6 @@ module.exports = class extends Generator { value: ['empty', 'library'] }] }, - // TODO: [gulp] line-o promp user for build system - // { - // type: 'checkbox', - // choices: ['ant', 'gulp'], - // name: 'builder', - // message: 'How would you like to build your app?', - // default: 'ant' - // }, { when: response => { return response.apptype[1] === 'application' @@ -129,7 +121,14 @@ module.exports = class extends Generator { message: 'Pick the release status', default: 'SNAPSHOT' }, - // TODO: [teipup] autoanswer pre,post, setperm, (license?) see# + { + type: 'checkbox', + choices: ['ant', 'gulp', 'hybrid'], + name: 'builder', + message: 'How would you like to build your app?', + default: 'ant', + store: true + }, { type: 'confirm', name: 'pre', @@ -267,7 +266,7 @@ module.exports = class extends Generator { type: 'list', choices: ['travis', 'GitHub Action'], name: 'ci', - message: 'Whats your CI service', + message: 'Pick a CI service provider', default: 'GitHub Action', store: true }, @@ -401,49 +400,37 @@ module.exports = class extends Generator { // EXPATH // Applies to all (build, expath-pkg, repo, xqs) // TODO #56 html -> xhtml - // TODO: [gulp] line-o here build.xml is copied for all outputs by default needs to become conditional - this.fs.copyTpl( - this.templatePath('build.xml'), - this.destinationPath('build.xml'), { - apptype: this.props.apptype[0], - title: this.props.title, - github: this.props.github, - desc: this.props.desc, - docker: this.props.docker, - dockerfiles: ', Dockerfile, .dockerignore', - gitfiles: ', README.md, **/.git*/**' - }) this.fs.copyTpl( this.templatePath('repo.xml'), this.destinationPath('repo.xml'), { - desc: this.props.desc, - short: this.props.short, - author: this.props.author, apptype: this.props.apptype[1], - status: this.props.status, - pre: this.props.pre, - prexq: 'pre-install.xql', + author: this.props.author, + desc: this.props.desc, + group: this.props.group, + license: this.props.license[0], + mode: this.props.mode, + owner: this.props.owner, post: this.props.post, postxq: 'post-install.xql', + pre: this.props.pre, + prexq: 'pre-install.xql', setperm: this.props.setperm, - website: this.props.website, - license: this.props.license[0], - owner: this.props.owner, + short: this.props.short, + status: this.props.status, userpw: this.props.userpw, - group: this.props.group, - mode: this.props.mode + website: this.props.website }) this.fs.copyTpl( this.templatePath('expath-pkg.xml'), this.destinationPath('expath-pkg.xml'), { - short: this.props.short, + apptype: this.props.apptype[0], defcoll: this.props.defcoll, defuri: this.props.defuri, - version: this.props.version, desc: this.props.desc, - apptype: this.props.apptype[0] + short: this.props.short, + version: this.props.version }) // Unit Test @@ -451,23 +438,23 @@ module.exports = class extends Generator { this.templatePath('tests/xqs/test-suite.xql'), this.destinationPath('test/xqs/test-suite.xql'), { apptype: this.props.apptype[0], - short: this.props.short, + author: this.props.author, defcoll: this.props.defcoll, defuri: this.props.defuri, + short: this.props.short, + title: this.props.title, version: this.props.version, - author: this.props.author, - website: this.props.website, - title: this.props.title + website: this.props.website }) this.fs.copyTpl( this.templatePath('tests/xqs/test-runner.xq'), this.destinationPath('test/xqs/test-runner.xq'), { - short: this.props.short, + author: this.props.author, defcoll: this.props.defcoll, defuri: this.props.defuri, - version: this.props.version, - author: this.props.author, - title: this.props.title + short: this.props.short, + title: this.props.title, + version: this.props.version }) this.fs.copy( @@ -479,16 +466,16 @@ module.exports = class extends Generator { this.templatePath('tests/mocha/rest_spec.js'), this.destinationPath('test/mocha/rest_spec.js'), { apptype: this.props.apptype[0], - short: this.props.short, - defcoll: this.props.defcoll + defcoll: this.props.defcoll, + short: this.props.short }) this.fs.copyTpl( this.templatePath('tests/xqs/xqSuite.js'), this.destinationPath('test/xqs/xqSuite.js'), { apptype: this.props.apptype[1], - short: this.props.short, defcoll: this.props.defcoll, + short: this.props.short, version: this.props.version }) @@ -522,10 +509,10 @@ module.exports = class extends Generator { this.templatePath('tests/integration/landing_spec.js'), this.destinationPath('test/cypress/integration/landing_spec.js'), { apptype: this.props.apptype[0], - short: this.props.short, defcoll: this.props.defcoll, desc: this.props.desc, - mysec: this.props.mysec + mysec: this.props.mysec, + short: this.props.short }) Object.assign(pkgJson.devDependencies, { @@ -573,37 +560,34 @@ module.exports = class extends Generator { this.fs.copyTpl( this.templatePath('view.xql'), this.destinationPath('modules/view.xql'), { - short: this.props.short, + apptype: this.props.apptype[0], defcoll: this.props.defcoll, defuri: this.props.defuri, - apptype: this.props.apptype[0], + short: this.props.short, version: this.props.version }) this.fs.copyTpl( this.templatePath('app.xql'), this.destinationPath('modules/app.xql'), { - short: this.props.short, - defcoll: this.props.defcoll, - defuri: this.props.defuri, apptype: this.props.apptype[0], - version: this.props.version, author: this.props.author, - website: this.props.website, + defcoll: this.props.defcoll, + defuri: this.props.defuri, + mysec: this.props.mysec, + short: this.props.short, title: this.props.title, - mysec: this.props.mysec + version: this.props.version, + website: this.props.website }) this.fs.copyTpl( this.templatePath('config.xqm'), this.destinationPath('modules/config.xqm'), { - short: this.props.short, + apptype: this.props.apptype[0], defcoll: this.props.defcoll, defuri: this.props.defuri, - apptype: this.props.apptype[0], defview: this.props.defview, index: this.props.index, - dataloc: this.props.dataloc, - datasrc: this.props.datasrc, - odd: this.props.odd + short: this.props.short }) // distinct contents (flexible) @@ -634,13 +618,67 @@ module.exports = class extends Generator { } // Prompt based + // Builder + if (this.props.builder !== 'gulp') { + this.fs.copyTpl( + this.templatePath('builder/build.xml'), + this.destinationPath('build.xml'), { + apptype: this.props.apptype[0], + builder: this.props.builder, + desc: this.props.desc, + docker: this.props.docker, + dockerfiles: ', Dockerfile, .dockerignore', + github: this.props.github, + gitfiles: ', README.md, **/.git*/**', + title: this.props.title + }) + } + + switch (this.props.builder) { + case 'ant': + break + case 'gulp': + this.fs.copyTpl( + this.templatePath('builder/gulpfile.js'), + this.destinationPath('gulpfile.js'), { + apptype: this.props.apptype[1] + } + ) + Object.assign(pkgJson.devDependencies, { + '@existdb/gulp-exist': pjson.devDependencies['@existdb/gulp-exist'], + '@existdb/gulp-replace-tmpl': pjson.devDependencies, + del: pjson.devDependencies.del, + gulp: pjson.devDependencies.gulp, + 'gulp-autoprefixer': pjson.devDependencies['gulp-autoprefixer'], + 'gulp-concat': pjson.devDependencies['gulp-concat'], + 'gulp-cssnano': pjson.devDependencies['gulp-cssnano'], + 'gulp-flatmap': pjson.devDependencies['gulp-flatmap'], + 'gulp-header': pjson.devDependencies['gulp-header'], + 'gulp-muxml': pjson.devDependencies['gulp-muxml'], + 'gulp-optimize-js': pjson.devDependencies['gulp-optimize-js'], + 'gulp-rename': pjson.devDependencies['gulp-rename'], + 'gulp-sass': pjson.devDependencies['gulp-sass'], + 'gulp-sourcemaps': pjson.devDependencies['gulp-sourcemaps'], + 'gulp-standard': pjson.devDependencies['gulp-standard'], + 'gulp-svgmin': pjson.devDependencies['gulp-svgmin'], + 'gulp-uglify': pjson.devDependencies['gulp-uglify'], + 'gulp-zip': pjson.devDependencies['gulp-zip'], + lazypipe: pjson.devDependencies.lazypipe + }) + Object.assign(pkgJson.scripts, { + build: 'gulp build', + deploy: 'gulp install' + }) + break + default: + } // Pre-install if (this.props.pre) { this.fs.copyTpl( this.templatePath('pre-install.xql'), this.destinationPath('pre-install.xql'), { - version: this.props.version, author: this.props.author, + version: this.props.version, website: this.props.website } ) @@ -651,8 +689,8 @@ module.exports = class extends Generator { this.templatePath('post-install.xql'), this.destinationPath('post-install.xql'), { apptype: this.props.apptype[0], - version: this.props.version, author: this.props.author, + version: this.props.version, website: this.props.website }) } @@ -696,16 +734,16 @@ module.exports = class extends Generator { this.templatePath('github/readme.md'), this.destinationPath('README.md'), { apptype: this.props.apptype[0], - title: this.props.title, - desc: this.props.desc, - version: this.props.version, - ghuser: this.props.ghuser, - website: this.props.website, author: this.props.author, - license: this.props.license[0], badge: this.props.license[1], badgelink: this.props.license[2], - ci: this.props.ci + ci: this.props.ci, + desc: this.props.desc, + ghuser: this.props.ghuser, + license: this.props.license[0], + title: this.props.title, + version: this.props.version, + website: this.props.website }) this.fs.copyTpl( this.templatePath('github/contributing.md'), @@ -751,11 +789,11 @@ module.exports = class extends Generator { this.fs.copyTpl( this.templatePath('.existdb.json'), this.destinationPath('.existdb.json'), { - short: this.props.short, - defcoll: this.props.defcoll, - instance: this.props.instance, admin: this.props.admin, - adminpw: this.props.adminpw + adminpw: this.props.adminpw, + defcoll: this.props.defcoll, + short: this.props.short, + instance: this.props.instance }) } diff --git a/generators/app/templates/build.xml b/generators/app/templates/build.xml deleted file mode 100644 index 1defd2a1..00000000 --- a/generators/app/templates/build.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - <%- desc %> - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/generators/app/templates/builder/build.xml b/generators/app/templates/builder/build.xml new file mode 100644 index 00000000..d68b04da --- /dev/null +++ b/generators/app/templates/builder/build.xml @@ -0,0 +1,45 @@ + + + <%- desc %> + + + + + + + + + <%_ if (builder === 'hybrid') { %> + + + + <%_ } else { %> + + <% } -%> + + + + + <%_ if (builder === 'hybrid') { %> + + + + + <%_ } else { %> + + <% } -%> + + + + + <%_ if (builder === 'hybrid') { %> + + <%_ } else { %> + + <% } -%> + + + + + + diff --git a/generators/app/templates/builder/gulpfile.js b/generators/app/templates/builder/gulpfile.js new file mode 100644 index 00000000..18f1270b --- /dev/null +++ b/generators/app/templates/builder/gulpfile.js @@ -0,0 +1,255 @@ +// TODO: line-o tell me what you want what you really really … +// see https://docs.google.com/document/d/1UdSWERC9rCSYIYjTGgCr3avce47h5OeLFR4tGKYXZlM/edit#heading=h.ei4sqy3ojpkl +// see https://github.com/eeditiones/roaster/blob/master/gulpfile.js +// see https://github.com/eXist-db/documentation/blob/master/Gulpfile.js +// see #563 + +/** + * Settings + * Turn on/off build features + */ + +const settings = { + clean: true, + scripts: true, + polyfills: false, + styles: true, + svgs: true, + copy: true, + vendor: true + } + +/** + * Gulp Packages + */ + +// General +const { + gulp, + src, + dest, + watch, + series, + parallel +} = require('gulp') +const { createClient } = require('@existdb/gulp-exist') +const del = require('del') +const flatmap = require('gulp-flatmap') +const header = require('gulp-header') +const lazypipe = require('lazypipe') +const muxml = require('gulp-muxml') +const zip = require("gulp-zip") +const rename = require('gulp-rename') +const replace = require('@existdb/gulp-replace-tmpl') // Do we need this still when starting from here ? + + +// Scripts +const standard = require('gulp-standard') +const concat = require('gulp-concat') +const uglify = require('gulp-uglify') +const optimizejs = require('gulp-optimize-js') + +// Styles +const sass = require('gulp-sass') +const prefix = require('gulp-autoprefixer') +const minify = require('gulp-cssnano') +const sourcemaps = require('gulp-sourcemaps') + +// SVGs +const svgmin = require('gulp-svgmin') + +const paths = { + input: 'src/', + output: 'dist/xar/' +} + +// read metadata from local files +const { version, license } = require('./package.json') +const { package, servers } = require('./.existdb.json') + +// .tmpl replacements to include +// first value wins +const replacements = [package, {version, license}] // s.a. + +// Connection Info +const serverInfo = servers.localhost +const { port, hostname } = new URL(serverInfo.server) +const connectionOptions = { + basic_auth: { + user: serverInfo.user, + pass: serverInfo.password + }, + host: hostname, + port +} + +// construct the current xar name from available data +const packageName = () => `${package.target}-${version}.xar` +// TODO: check if this is really what we want, modifications in these need to trigger sync +const static = 'src/**/*.{xml,html,xq,xquery,xql,xqm,xsl,xconf}' + + + +/** + * Use the `delete` module directly, instead of using gulp-rimraf + */ +function clean (cb) { + del(['dist'], cb); +} +exports.clean = clean + +/** +* replace placeholders +* in src/repo.xml.tmpl and +* output to build/repo.xml +*/ +function templates () { +return src('src/*.tmpl') + .pipe(replace(replacements, {debug:true})) + .pipe(rename(path => { path.extname = "" })) + .pipe(dest('dist/xar/')) +} +exports.templates = templates + +function watchTemplates () { + watch('src/*.tmpl', series(templates)) +} +exports["watch:tmpl"] = watchTemplates + +/** + * compile SCSS styles and put them into 'build/app/css' + */ +function styles () { + return src('src/scss/**/*.scss') + .pipe(sass().on('error', sass.logError)) + .pipe(dest('dist/xar/resources/styles')); +} +exports.styles = styles + +function watchStyles () { + watch('src/scss/**/*.scss', series(styles)) +} +exports["watch:styles"] = watchStyles + +/** +* minify EcmaSript files and put them into 'build/app/js' +*/ +function minifyEs () { + return src('src/js/**/*.js') + .pipe(uglify()) + .pipe(dest('dist/xar/resources/scripts')) +} +exports.minify = minifyEs + +function watchEs () { + watch('src/js/**/*.js', series(minifyEs)) +} +exports["watch:es"] = watchEs + +/** + * compile SCSS styles and put them into 'build/app/css' + */ +function styles () { + return src('src/scss/**/*.scss') + .pipe(sass().on('error', sass.logError)) + .pipe(dest('dist/xar/resources/styles')); +} +exports.styles = styles + +function watchStyles () { + watch('src/scss/**/*.scss', series(styles)) +} +exports["watch:styles"] = watchStyles + +/** +* minify EcmaSript files and put them into 'build/app/js' +*/ +function minifyEs () { + return src('src/js/**/*.js') + .pipe(uglify()) + .pipe(dest('dist/xar/resources/styles')) +} +exports.minify = minifyEs + +function watchEs () { + watch('src/js/**/*.js', series(minifyEs)) +} +exports["watch:es"] = watchEs + +/** +* copy html templates, XSL stylesheet, XMLs and XQueries to 'build' +*/ +function copyStatic () { + return src(static).pipe(dest('dist/xar/')) +} +exports.copy = copyStatic + +function watchStatic () { + watch(static, series(copyStatic)); +} +exports["watch:static"] = watchStatic + +/** + * Upload all files in the build folder to existdb. + * This function will only upload what was changed + * since the last run (see gulp documentation for lastRun). + */ +function deploy () { + return src('build/**/*', { + base: 'dist/xar', + since: lastRun(deploy) + }) + .pipe(existClient.dest({target})) +} + +function watchBuild () { + watch('dist/xar/**/*', series(deploy)) +} + +/** + * create XAR package in repo root + */ +function xar () { + return src('dist/xar/**/*', {base: 'dist'}) + .pipe(zip(packageName())) + .pipe(dest('.')) +} + +/** +* upload and install the latest built XAR +*/ +function installXar () { + return src(packageName()) + .pipe(existClient.install({ packageUri })) +} + +// composed tasks +const build = series( + clean, + styles, + minifyEs, + templates, + copyStatic +) +const watchAll = parallel( + watchStyles, + watchEs, + watchStatic, + watchTemplates, + watchBuild +) + +exports.build = build +exports.watch = watchAll + +exports.deploy = series(build, deploy) +exports.xar = series(build, xar) +exports.install = series(build, xar, installXar) + +// main task for day to day development +exports.default = series(build, deploy, watchAll) + + +// Todo: conditional library package tasks go here + +// \ No newline at end of file diff --git a/generators/app/templates/gulpfile.js b/generators/app/templates/gulpfile.js deleted file mode 100644 index be028cb9..00000000 --- a/generators/app/templates/gulpfile.js +++ /dev/null @@ -1,5 +0,0 @@ -// TODO: line-o tell me what you want what you really really … -// see https://docs.google.com/document/d/1UdSWERC9rCSYIYjTGgCr3avce47h5OeLFR4tGKYXZlM/edit#heading=h.ei4sqy3ojpkl -// see https://github.com/line-o/gulp-exist-example/blob/main/gulpfile.js -// see https://github.com/eXist-db/documentation/blob/master/Gulpfile.js -// see #563 diff --git a/package-lock.json b/package-lock.json index 62d85a8e..17539e3f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1348,6 +1348,92 @@ } } }, + "@existdb/gulp-exist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@existdb/gulp-exist/-/gulp-exist-4.0.0.tgz", + "integrity": "sha512-exs1ZhqZ1vo6ihnosOxWiBSzy5votBzqTLILTBp1sso5MtGn8QlyxTUaLNXZ6dVbn+ilCmU4Z2qchpoevhWpLg==", + "dev": true, + "requires": { + "@existdb/node-exist": "^3.0.1", + "fancy-log": "^1.3.2", + "gulp": "^4.0.2", + "lodash.assign": "^4.2.0", + "plugin-error": "^1.0.1", + "through2": "^4.0.2", + "vinyl": "^2.2.1" + }, + "dependencies": { + "ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "requires": { + "ansi-wrap": "^0.1.0" + } + }, + "plugin-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.2" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dev": true, + "requires": { + "readable-stream": "3" + } + } + } + }, + "@existdb/gulp-replace-tmpl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@existdb/gulp-replace-tmpl/-/gulp-replace-tmpl-1.0.0.tgz", + "integrity": "sha512-FCaSePZoibT4gshORFTkRe3uyYtsEYxr4lkEpoEAD4d6VGdoks7adfv44dVwjBUQqY2HnLmVBskXXpn3RlEACg==", + "dev": true, + "requires": { + "gulp-replace": "^1.0.0" + } + }, + "@existdb/node-exist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@existdb/node-exist/-/node-exist-3.0.1.tgz", + "integrity": "sha512-otZiT+SfpZBWJUOrKo9ETr47AcKebJZxDmFFdMHCaC/TfpuqD6HmvllZwsEx7xW++MCt/6MHcqALblimMlID0A==", + "dev": true, + "requires": { + "lodash.assign": "^4.0.2", + "mime": "^2.3.1", + "xmlrpc": "^1.3.1" + }, + "dependencies": { + "mime": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.0.tgz", + "integrity": "sha512-ft3WayFSFUVBuJj7BMLKAQcSlItKtfjsKDDsii3rqFDAZ7t11zRe8ASw/GlmivGwVUYtwkQrxiGGpL6gFvB0ag==", + "dev": true + } + } + }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -3179,6 +3265,21 @@ "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" }, + "autoprefixer": { + "version": "9.8.6", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.6.tgz", + "integrity": "sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==", + "dev": true, + "requires": { + "browserslist": "^4.12.0", + "caniuse-lite": "^1.0.30001109", + "colorette": "^1.2.1", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^7.0.32", + "postcss-value-parser": "^4.1.0" + } + }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -3461,6 +3562,19 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "browserslist": { + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.3.tgz", + "integrity": "sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001181", + "colorette": "^1.2.1", + "electron-to-chromium": "^1.3.649", + "escalade": "^3.1.1", + "node-releases": "^1.1.70" + } + }, "bser": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", @@ -3562,23 +3676,12 @@ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "caniuse-lite": { + "version": "1.0.30001185", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001185.tgz", + "integrity": "sha512-Fpi4kVNtNvJ15H0F6vwmXtb3tukv3Zg3qhKkOGUq7KJ1J6b9kf4dnNgtEAFXhRsJo0gNj9W60+wBvn0JcTvdTg==", "dev": true }, - "camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - } - }, "capture-exit": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", @@ -4015,6 +4118,12 @@ "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" }, + "colorette": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz", + "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==", + "dev": true + }, "colors": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", @@ -5011,6 +5120,12 @@ "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz", "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==" }, + "electron-to-chromium": { + "version": "1.3.657", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.657.tgz", + "integrity": "sha512-/9ROOyvEflEbaZFUeGofD+Tqs/WynbSTbNgNF+/TJJxH1ePD/e6VjZlDJpW3FFFd3nj5l3Hd8ki2vRwy+gyRFw==", + "dev": true + }, "elegant-spinner": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", @@ -6883,6 +6998,53 @@ } } }, + "gulp-autoprefixer": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/gulp-autoprefixer/-/gulp-autoprefixer-7.0.1.tgz", + "integrity": "sha512-QJGEmHw+bEt7FSqvmbAUTxbCuNLJYx4sz3ox9WouYqT/7j5FH5CQ8ZnpL1M7H5npX1bUJa7lUVY1w20jXxhOxg==", + "dev": true, + "requires": { + "autoprefixer": "^9.6.1", + "fancy-log": "^1.3.2", + "plugin-error": "^1.0.1", + "postcss": "^7.0.17", + "through2": "^3.0.1", + "vinyl-sourcemaps-apply": "^0.2.1" + }, + "dependencies": { + "ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "requires": { + "ansi-wrap": "^0.1.0" + } + }, + "plugin-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.2" + } + }, + "through2": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", + "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "2 || 3" + } + } + } + }, "gulp-pretty-data": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/gulp-pretty-data/-/gulp-pretty-data-0.1.2.tgz", @@ -6962,6 +7124,42 @@ } } }, + "gulp-rename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-2.0.0.tgz", + "integrity": "sha512-97Vba4KBzbYmR5VBs9mWmK+HwIf5mj+/zioxfZhOKeXtx5ZjBk57KFlePf5nxq9QsTtFl0ejnHE3zTC9MHXqyQ==", + "dev": true + }, + "gulp-replace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-1.0.0.tgz", + "integrity": "sha512-lgdmrFSI1SdhNMXZQbrC75MOl1UjYWlOWNbNRnz+F/KHmgxt3l6XstBoAYIdadwETFyG/6i+vWUSCawdC3pqOw==", + "dev": true, + "requires": { + "istextorbinary": "2.2.1", + "readable-stream": "^2.0.1", + "replacestream": "^4.0.0" + }, + "dependencies": { + "editions": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/editions/-/editions-1.3.4.tgz", + "integrity": "sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg==", + "dev": true + }, + "istextorbinary": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.2.1.tgz", + "integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==", + "dev": true, + "requires": { + "binaryextensions": "2", + "editions": "^1.3.3", + "textextensions": "2" + } + } + } + }, "gulp-stripbom": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/gulp-stripbom/-/gulp-stripbom-1.0.5.tgz", @@ -7098,6 +7296,61 @@ } } }, + "gulp-zip": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/gulp-zip/-/gulp-zip-5.0.2.tgz", + "integrity": "sha512-rZd0Ppuc8Bf7J2/WzcdNaeb+lcEXf1R8mV/PJ9Kdu7PmnInWVeLSmiXIka/2QSe6uhAsGVFAMffWSaMzAPGTBg==", + "dev": true, + "requires": { + "get-stream": "^5.1.0", + "plugin-error": "^1.0.1", + "through2": "^3.0.1", + "vinyl": "^2.1.0", + "yazl": "^2.5.1" + }, + "dependencies": { + "ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "requires": { + "ansi-wrap": "^0.1.0" + } + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "plugin-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.2" + } + }, + "through2": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", + "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "2 || 3" + } + } + } + }, "gulplog": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", @@ -11037,6 +11290,12 @@ } } }, + "node-releases": { + "version": "1.1.70", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.70.tgz", + "integrity": "sha512-Slf2s69+2/uAD79pVVQo8uSiC34+g8GWY8UH2Qtqv34ZfhYrxpYpfzs9Js9d6O0mbDmALuxaTlplnBTnSELcrw==", + "dev": true + }, "nodesecurity-npm-utils": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/nodesecurity-npm-utils/-/nodesecurity-npm-utils-6.0.0.tgz", @@ -11060,6 +11319,12 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true + }, "normalize-url": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-5.3.0.tgz", @@ -14978,6 +15243,12 @@ } } }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "dev": true + }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", @@ -15533,6 +15804,92 @@ "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" }, + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-value-parser": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", + "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", + "dev": true + }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -15877,6 +16234,17 @@ "remove-trailing-separator": "^1.1.0" } }, + "replacestream": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/replacestream/-/replacestream-4.0.3.tgz", + "integrity": "sha512-AC0FiLS352pBBiZhd4VXB1Ab/lh0lEgpP+GGvZqbQh8a5cmXVoTe5EX/YeTFArnp4SRGTHh1qCHu9lGs1qG8sA==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.3", + "object-assign": "^4.0.1", + "readable-stream": "^2.0.2" + } + }, "request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", @@ -18308,6 +18676,15 @@ } } }, + "vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", + "dev": true, + "requires": { + "source-map": "^0.5.1" + } + }, "w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", @@ -18821,6 +19198,15 @@ "fd-slicer": "~1.1.0" } }, + "yazl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", + "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", + "dev": true, + "requires": { + "buffer-crc32": "~0.2.3" + } + }, "yeoman-assert": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yeoman-assert/-/yeoman-assert-3.1.1.tgz", diff --git a/package.json b/package.json index 00687ed6..f5923a04 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,8 @@ ], "devDependencies": { "@babel/core": "^7.12.13", + "@existdb/gulp-exist": "^4.0.0", + "@existdb/gulp-replace-tmpl": "^1.0.0", "chai": "^4.3.0", "chai-xml": "^0.4.0", "coveralls": "^3.1.0", @@ -43,6 +45,9 @@ "fs-extra": "^9.1.0", "glob": "^7.1.6", "gulp": "^4.0.2", + "gulp-autoprefixer": "^7.0.1", + "gulp-rename": "^2.0.0", + "gulp-zip": "^5.0.2", "jest-cli": "^26.6.3", "mocha": "^8.2.1", "node-exist": "^0.3.1", diff --git a/test/generated-pkg/app-eXide-default.js b/test/generated-pkg/app-eXide-default.js index 57432465..4d196db4 100644 --- a/test/generated-pkg/app-eXide-default.js +++ b/test/generated-pkg/app-eXide-default.js @@ -16,6 +16,7 @@ describe('eXide style …', function () { pre: true, post: true, license: ['MIT', 'MIT', 'https://opensource.org/licenses/MIT'], + builder: 'ant', github: false, setperm: false, ci: 'travis', @@ -45,6 +46,11 @@ describe('eXide style …', function () { assert.fileContent('repo.xml', /foo<\/target>/) done() }) + + it('does not call npm via ant', function (done) { + assert.noFileContent('build.xml', 'npm') + done() + }) }) describe('markup files are well-formed', function () { diff --git a/test/generated-pkg/app-empty.js b/test/generated-pkg/app-empty.js index d2cbbe71..f176d70c 100644 --- a/test/generated-pkg/app-empty.js +++ b/test/generated-pkg/app-empty.js @@ -18,15 +18,16 @@ describe('empty package', function () { pre: false, post: false, license: ['MIT', 'MIT', 'https://opensource.org/licenses/MIT'], + builder: 'gulp', github: false, atom: false }) - assert.noFile(['modules/app.xql', 'templates/page.html', 'test/cypress/integration/login-ok_spec.js', 'index.html']) + assert.noFile(['modules/app.xql', 'templates/page.html', 'test/cypress/integration/login-ok_spec.js', 'index.html', 'build.xml']) }) describe('empty has', function () { it('recommended files', function (done) { - assert.file(['repo.xml', 'test/mocha/app_spec.js', 'test/xqs/test-runner.xq']) + assert.file(['repo.xml', 'test/mocha/app_spec.js', 'test/xqs/test-runner.xq', 'gulpfile.js']) done() }) @@ -49,6 +50,11 @@ describe('empty package', function () { assert.noFileContent('test/xqs/test-runner.xq', 'import module namespace app') done() }) + + it('build is enabled via npm script', function (done) { + assert.fileContent('package.json', 'gulp build') + done() + }) }) describe('markup files are well-formed', function () { From ebb96bfb5d35848dedafccde8a28207427eec189 Mon Sep 17 00:00:00 2001 From: Duncan Paterson Date: Sat, 6 Feb 2021 15:20:39 +0100 Subject: [PATCH 09/20] refactor(templates): group xq files in collection --- generators/app/index.js | 12 ++++++------ generators/app/templates/{ => xq}/app.xql | 0 generators/app/templates/{ => xq}/config.xqm | 0 generators/app/templates/{ => xq}/controller.xql | 0 generators/app/templates/{ => xq}/post-install.xql | 0 generators/app/templates/{ => xq}/pre-install.xql | 0 generators/app/templates/{ => xq}/view.xql | 0 7 files changed, 6 insertions(+), 6 deletions(-) rename generators/app/templates/{ => xq}/app.xql (100%) rename generators/app/templates/{ => xq}/config.xqm (100%) rename generators/app/templates/{ => xq}/controller.xql (100%) rename generators/app/templates/{ => xq}/post-install.xql (100%) rename generators/app/templates/{ => xq}/pre-install.xql (100%) rename generators/app/templates/{ => xq}/view.xql (100%) diff --git a/generators/app/index.js b/generators/app/index.js index 8ecdee0e..0fe762ee 100644 --- a/generators/app/index.js +++ b/generators/app/index.js @@ -551,14 +551,14 @@ module.exports = class extends Generator { // XQuery this.fs.copyTpl( - this.templatePath('controller.xql'), + this.templatePath('xq/controller.xql'), this.destinationPath('controller.xql'), { apptype: this.props.apptype[0], mysec: this.props.mysec }) this.fs.copyTpl( - this.templatePath('view.xql'), + this.templatePath('xq/view.xql'), this.destinationPath('modules/view.xql'), { apptype: this.props.apptype[0], defcoll: this.props.defcoll, @@ -567,7 +567,7 @@ module.exports = class extends Generator { version: this.props.version }) this.fs.copyTpl( - this.templatePath('app.xql'), + this.templatePath('xq/app.xql'), this.destinationPath('modules/app.xql'), { apptype: this.props.apptype[0], author: this.props.author, @@ -580,7 +580,7 @@ module.exports = class extends Generator { website: this.props.website }) this.fs.copyTpl( - this.templatePath('config.xqm'), + this.templatePath('xq/config.xqm'), this.destinationPath('modules/config.xqm'), { apptype: this.props.apptype[0], defcoll: this.props.defcoll, @@ -675,7 +675,7 @@ module.exports = class extends Generator { // Pre-install if (this.props.pre) { this.fs.copyTpl( - this.templatePath('pre-install.xql'), + this.templatePath('xq/pre-install.xql'), this.destinationPath('pre-install.xql'), { author: this.props.author, version: this.props.version, @@ -686,7 +686,7 @@ module.exports = class extends Generator { // Post-install if (this.props.post) { this.fs.copyTpl( - this.templatePath('post-install.xql'), + this.templatePath('xq/post-install.xql'), this.destinationPath('post-install.xql'), { apptype: this.props.apptype[0], author: this.props.author, diff --git a/generators/app/templates/app.xql b/generators/app/templates/xq/app.xql similarity index 100% rename from generators/app/templates/app.xql rename to generators/app/templates/xq/app.xql diff --git a/generators/app/templates/config.xqm b/generators/app/templates/xq/config.xqm similarity index 100% rename from generators/app/templates/config.xqm rename to generators/app/templates/xq/config.xqm diff --git a/generators/app/templates/controller.xql b/generators/app/templates/xq/controller.xql similarity index 100% rename from generators/app/templates/controller.xql rename to generators/app/templates/xq/controller.xql diff --git a/generators/app/templates/post-install.xql b/generators/app/templates/xq/post-install.xql similarity index 100% rename from generators/app/templates/post-install.xql rename to generators/app/templates/xq/post-install.xql diff --git a/generators/app/templates/pre-install.xql b/generators/app/templates/xq/pre-install.xql similarity index 100% rename from generators/app/templates/pre-install.xql rename to generators/app/templates/xq/pre-install.xql diff --git a/generators/app/templates/view.xql b/generators/app/templates/xq/view.xql similarity index 100% rename from generators/app/templates/view.xql rename to generators/app/templates/xq/view.xql From 28b561382bb763ab3449eb326ad149dc8851b584 Mon Sep 17 00:00:00 2001 From: Duncan Paterson Date: Sat, 6 Feb 2021 22:55:52 +0100 Subject: [PATCH 10/20] chore(gulpfile): avoid repeathing path defs treeshaking moar todos see Make builder configurable #563 --- generators/app/index.js | 2 - generators/app/templates/builder/gulpfile.js | 208 +++++++++++------- .../tests/integration/login-fail_spec.js | 40 ++-- .../tests/integration/login-ok_spec.js | 40 ++-- .../app/templates/tests/mocha/app_spec.js | 2 +- 5 files changed, 175 insertions(+), 117 deletions(-) diff --git a/generators/app/index.js b/generators/app/index.js index 0fe762ee..79af6c83 100644 --- a/generators/app/index.js +++ b/generators/app/index.js @@ -655,11 +655,9 @@ module.exports = class extends Generator { 'gulp-flatmap': pjson.devDependencies['gulp-flatmap'], 'gulp-header': pjson.devDependencies['gulp-header'], 'gulp-muxml': pjson.devDependencies['gulp-muxml'], - 'gulp-optimize-js': pjson.devDependencies['gulp-optimize-js'], 'gulp-rename': pjson.devDependencies['gulp-rename'], 'gulp-sass': pjson.devDependencies['gulp-sass'], 'gulp-sourcemaps': pjson.devDependencies['gulp-sourcemaps'], - 'gulp-standard': pjson.devDependencies['gulp-standard'], 'gulp-svgmin': pjson.devDependencies['gulp-svgmin'], 'gulp-uglify': pjson.devDependencies['gulp-uglify'], 'gulp-zip': pjson.devDependencies['gulp-zip'], diff --git a/generators/app/templates/builder/gulpfile.js b/generators/app/templates/builder/gulpfile.js index 18f1270b..781e2536 100644 --- a/generators/app/templates/builder/gulpfile.js +++ b/generators/app/templates/builder/gulpfile.js @@ -9,15 +9,56 @@ * Turn on/off build features */ +// TODO: make these meaningful const settings = { - clean: true, - scripts: true, - polyfills: false, - styles: true, - svgs: true, - copy: true, - vendor: true - } + clean: true, + scripts: true, + polyfills: false, + styles: true, + svgs: true, + copy: true, + vendor: true +} + +// TODO flexible hybrid vs pure gulp +// Gulp +const paths = { + input: 'src/main/', + output: 'dist/xar/', + scripts: { + input: 'src/main/js/*', + // polyfills: '.polyfill.js', + output: 'dist/xar/resources/scripts/' + }, + styles: { + input: 'src/main/styles/sass/*.{scss,sass}', + output: 'dist/xar/resources/styles/' + }, + svgs: { + input: 'src/main/img/*.svg', + output: 'dist/xar/resources/images/' + }, +} + +// TODO: Hybrid (no src) stick with old layout +// Hybrid +// const paths = { +// input: 'src/main/', +// output: 'dist/xar/', +// scripts: { +// input: 'src/main/js/*', +// // polyfills: '.polyfill.js', +// output: 'dist/xar/resources/scripts/' +// }, +// styles: { +// input: 'src/main/styles/sass/*.{scss,sass}', +// output: 'dist/xar/resources/styles/' +// }, +// svgs: { +// input: 'src/main/img/*.svg', +// output: 'dist/xar/resources/images/' +// }, +// } /** * Gulp Packages @@ -44,10 +85,8 @@ const replace = require('@existdb/gulp-replace-tmpl') // Do we need this still w // Scripts -const standard = require('gulp-standard') const concat = require('gulp-concat') const uglify = require('gulp-uglify') -const optimizejs = require('gulp-optimize-js') // Styles const sass = require('gulp-sass') @@ -56,36 +95,37 @@ const minify = require('gulp-cssnano') const sourcemaps = require('gulp-sourcemaps') // SVGs -const svgmin = require('gulp-svgmin') - -const paths = { - input: 'src/', - output: 'dist/xar/' -} +const svgmin = require('gulp-svgmin') // read metadata from local files -const { version, license } = require('./package.json') -const { package, servers } = require('./.existdb.json') +const pkg = require('./package.json') +const { version, license } = pkg +const existJSON = require('./.existdb.json') +const replacements = [existJSON.package, { version, license }] // .tmpl replacements to include // first value wins -const replacements = [package, {version, license}] // s.a. +const replacements = [pkg, { version, license }] // s.a. // Connection Info -const serverInfo = servers.localhost -const { port, hostname } = new URL(serverInfo.server) +const packageUri = existJSON.package.ns +const serverInfo = existJSON.servers.localhost +const target = serverInfo.root + const connectionOptions = { basic_auth: { user: serverInfo.user, pass: serverInfo.password - }, - host: hostname, - port + } } +const existClient = createClient(connectionOptions); // construct the current xar name from available data -const packageName = () => `${package.target}-${version}.xar` +const packageName = () => `${existJSON.package.target}-${pkg.version}.xar` // TODO: check if this is really what we want, modifications in these need to trigger sync +// - xml / xconf / odd should be prettied +// - html should be... +// - xq / xsl ... ? const static = 'src/**/*.{xml,html,xq,xquery,xql,xqm,xsl,xconf}' @@ -93,8 +133,8 @@ const static = 'src/**/*.{xml,html,xq,xquery,xql,xqm,xsl,xconf}' /** * Use the `delete` module directly, instead of using gulp-rimraf */ -function clean (cb) { - del(['dist'], cb); +function clean(cb) { + del([paths.output], cb); } exports.clean = clean @@ -103,15 +143,15 @@ exports.clean = clean * in src/repo.xml.tmpl and * output to build/repo.xml */ -function templates () { -return src('src/*.tmpl') - .pipe(replace(replacements, {debug:true})) - .pipe(rename(path => { path.extname = "" })) - .pipe(dest('dist/xar/')) +function templates() { + return src('src/*.tmpl') + .pipe(replace(replacements, { debug: true })) + .pipe(rename(path => { path.extname = "" })) + .pipe(dest(paths.output)) } exports.templates = templates -function watchTemplates () { +function watchTemplates() { watch('src/*.tmpl', series(templates)) } exports["watch:tmpl"] = watchTemplates @@ -119,72 +159,92 @@ exports["watch:tmpl"] = watchTemplates /** * compile SCSS styles and put them into 'build/app/css' */ -function styles () { - return src('src/scss/**/*.scss') - .pipe(sass().on('error', sass.logError)) - .pipe(dest('dist/xar/resources/styles')); +function styles() { + return src(paths.styles.input) + .pipe(sourcemaps.init()) + .pipe(sass({ + outputStyle: 'expanded', + sourceComments: true + }).on('error', sass.logError)) + .pipe(prefix({ + browsers: ['last 2 version', '> 0.25%'], + cascade: true, + remove: true + })) + .pipe(rename({ + suffix: '.min' + })) + .pipe(minify({ + discardComments: { + removeAll: true + } + })) + .pipe(sourcemaps.write('.')) + .pipe(dest(paths.styles.output)); } exports.styles = styles -function watchStyles () { - watch('src/scss/**/*.scss', series(styles)) +function watchStyles() { + watch(paths.styles.input, series(styles)) } exports["watch:styles"] = watchStyles /** * minify EcmaSript files and put them into 'build/app/js' */ -function minifyEs () { - return src('src/js/**/*.js') - .pipe(uglify()) - .pipe(dest('dist/xar/resources/scripts')) +function minifyEs() { + return src(paths.scripts.input) + .pipe(uglify()) + .pipe(dest(paths.scripts.output)) } exports.minify = minifyEs -function watchEs () { - watch('src/js/**/*.js', series(minifyEs)) +function watchEs() { + watch(paths.scripts.input, series(minifyEs)) } exports["watch:es"] = watchEs /** * compile SCSS styles and put them into 'build/app/css' */ -function styles () { - return src('src/scss/**/*.scss') - .pipe(sass().on('error', sass.logError)) - .pipe(dest('dist/xar/resources/styles')); +function styles() { + return src(paths.styles.input) + .pipe(sass().on('error', sass.logError)) + .pipe(dest(paths.styles.output)); } exports.styles = styles -function watchStyles () { - watch('src/scss/**/*.scss', series(styles)) +function watchStyles() { + watch(paths.styles.input, series(styles)) } exports["watch:styles"] = watchStyles /** * minify EcmaSript files and put them into 'build/app/js' */ -function minifyEs () { - return src('src/js/**/*.js') - .pipe(uglify()) - .pipe(dest('dist/xar/resources/styles')) +function minifyEs() { + return src(paths.scripts.input) + .pipe(uglify()) + .pipe(dest(paths.styles.output)) } exports.minify = minifyEs -function watchEs () { - watch('src/js/**/*.js', series(minifyEs)) +function watchEs() { + watch(paths.scripts.input, series(minifyEs)) } exports["watch:es"] = watchEs /** * copy html templates, XSL stylesheet, XMLs and XQueries to 'build' */ -function copyStatic () { - return src(static).pipe(dest('dist/xar/')) + +// TODO add xml prettiprinting, css nano, etc from docs. probably split into multiple tasks +function copyStatic() { + return src(static).pipe(dest(paths.output)) } exports.copy = copyStatic -function watchStatic () { +function watchStatic() { watch(static, series(copyStatic)); } exports["watch:static"] = watchStatic @@ -194,33 +254,33 @@ exports["watch:static"] = watchStatic * This function will only upload what was changed * since the last run (see gulp documentation for lastRun). */ -function deploy () { - return src('build/**/*', { - base: 'dist/xar', - since: lastRun(deploy) - }) - .pipe(existClient.dest({target})) +function deploy() { + return src(paths.output + '**/*', { + base: paths.output, + since: lastRun(deploy) + }) + .pipe(existClient.dest({ target })) } -function watchBuild () { - watch('dist/xar/**/*', series(deploy)) +function watchBuild() { + watch(paths.output + '**/*', series(deploy)) } /** * create XAR package in repo root */ -function xar () { - return src('dist/xar/**/*', {base: 'dist'}) - .pipe(zip(packageName())) - .pipe(dest('.')) +function xar() { + return src(paths.output + '**/*', { base: 'dist' }) + .pipe(zip(packageName())) + .pipe(dest('.')) } /** * upload and install the latest built XAR */ -function installXar () { +function installXar() { return src(packageName()) - .pipe(existClient.install({ packageUri })) + .pipe(existClient.install({ packageUri })) } // composed tasks diff --git a/generators/app/templates/tests/integration/login-fail_spec.js b/generators/app/templates/tests/integration/login-fail_spec.js index f1314b23..868aa6d3 100644 --- a/generators/app/templates/tests/integration/login-fail_spec.js +++ b/generators/app/templates/tests/integration/login-fail_spec.js @@ -1,25 +1,25 @@ /* global cy */ describe('On a protected pages when not logged in', function () { - it('the page should load ', function () { - cy.visit('/exist/<%- defcoll %>/<%- short %>/admin/index.html') - .get('.alert') - .contains('This is a protected page.') - }) + it('the page should load ', function () { + cy.visit('/exist/<%- defcoll %>/<%- short %>/admin/index.html') + .get('.alert') + .contains('This is a protected page.') + }) - it('login should fail with bad credentials', function () { - cy.contains('Login').click() - cy.get('.modal-content') - .find('input[name=user]').type('baduser{enter}') - cy.get('body') - .contains('This is a protected page.') - }) + it('login should fail with bad credentials', function () { + cy.contains('Login').click() + cy.get('.modal-content') + .find('input[name=user]').type('baduser{enter}') + cy.get('body') + .contains('This is a protected page.') + }) - it('Navigation Bar should show guest user', function () { - cy.get('.navbar-right > :nth-child(1) > a') - .contains('Hello Guest') - }) + it('Navigation Bar should show guest user', function () { + cy.get('.navbar-right > :nth-child(1) > a') + .contains('Hello Guest') + }) - after('logout', function () { - cy.get(':nth-child(2) > .btn').click() - }) -}) \ No newline at end of file + after('logout', function () { + cy.get(':nth-child(2) > .btn').click() + }) +}) diff --git a/generators/app/templates/tests/integration/login-ok_spec.js b/generators/app/templates/tests/integration/login-ok_spec.js index fe1eb606..d72fb7ff 100644 --- a/generators/app/templates/tests/integration/login-ok_spec.js +++ b/generators/app/templates/tests/integration/login-ok_spec.js @@ -1,25 +1,25 @@ /* global cy */ describe('On a protected page', function () { - it('the page should load ', function () { - cy.visit('/exist/<%- defcoll %>/<%- short %>/admin/index.html') - .get('.alert') - .contains('This is a protected page.') - }) + it('the page should load ', function () { + cy.visit('/exist/<%- defcoll %>/<%- short %>/admin/index.html') + .get('.alert') + .contains('This is a protected page.') + }) - it('login should accept admin user', function () { - cy.contains('Login').click() - cy.get('.modal-content') - .find('input[name=user]').type('admin{enter}') - cy.get('body') - .contains('You are now logged in.') - }) + it('login should accept admin user', function () { + cy.contains('Login').click() + cy.get('.modal-content') + .find('input[name=user]').type('admin{enter}') + cy.get('body') + .contains('You are now logged in.') + }) - it('navigation bar shows the admin user is logged in', function () { - cy.get('.navbar-right > :nth-child(1) > a') - .contains('Hello admin') - }) + it('navigation bar shows the admin user is logged in', function () { + cy.get('.navbar-right > :nth-child(1) > a') + .contains('Hello admin') + }) - after('logout', function () { - cy.get(':nth-child(2) > .btn').click() - }) -}) \ No newline at end of file + after('logout', function () { + cy.get(':nth-child(2) > .btn').click() + }) +}) diff --git a/generators/app/templates/tests/mocha/app_spec.js b/generators/app/templates/tests/mocha/app_spec.js index 247b3227..9b2184a5 100644 --- a/generators/app/templates/tests/mocha/app_spec.js +++ b/generators/app/templates/tests/mocha/app_spec.js @@ -136,7 +136,7 @@ describe('file system checks', function () { const parsed = new xmldoc.XmlDocument(exRepo) var repoLic = parsed.childNamed('license').val } - + const lic = [repoLic, pkgLic].filter(Boolean) let i = 0 // console.log(lic) From 4f50c15e639ac7e13568f3b31c3dfb5d35d9f5b4 Mon Sep 17 00:00:00 2001 From: Duncan Paterson Date: Mon, 8 Feb 2021 14:47:09 +0100 Subject: [PATCH 11/20] feature(shared-resources): deprecate shared resources treeshaking BREAKING CHANGE: Shared resources are deprecated. Templating is handled by an independent xq library Frontend code reuses the existing npm infrastructure. see #36 --- generators/app/index.js | 109 +- .../app/templates/exist-design/page.html | 10 +- .../app/templates/exist-plain/page.html | 10 +- generators/app/templates/expath-pkg.xml | 2 +- .../images => img/exist-design}/bgmenu.gif | Bin .../images => img/exist-design}/bgmenuhi.gif | Bin .../images => img/exist-design}/body-base.gif | Bin .../images => img/exist-design}/body.gif | Bin .../images => img/exist-design}/bold.gif | Bin .../images => img/exist-design}/code.gif | Bin .../exist-design}/delete-icon.png | Bin .../images => img/exist-design}/existdb.png | Bin .../exist-design}/glyphicons-halflings.png | Bin .../exist-design}/grey-box-bot.gif | Bin .../exist-design}/grey-box-rpt.gif | Bin .../exist-design}/grey-box-top.gif | Bin .../images => img/exist-design}/header.gif | Bin .../exist-design}/horizontal.gif | Bin .../images => img/exist-design}/italic.gif | Bin .../exist-design}/nav-dropdown.gif | Bin .../exist-design}/nav-dropdown.png | Bin .../images => img/exist-design}/nav.gif | Bin .../exist-design}/page-edit-icon.png | Bin .../app/templates/img/exist_icon_16x16.ico | Bin 0 -> 1150 bytes generators/app/templates/js/loadsource.js | 45 + .../app/templates/mysec/admin/controller.xql | 7 - generators/app/templates/styles/exist-2.2.css | 469 + .../app/templates/{ => styles}/style.css | 0 generators/app/templates/xq/app.xql | 2 +- generators/app/templates/xq/config.xqm | 2 +- generators/app/templates/xq/controller.xql | 8 - generators/app/templates/xq/view.xql | 2 +- package-lock.json | 18121 +++++----------- package.json | 12 - test/util/consistency.js | 12 - 35 files changed, 6273 insertions(+), 12538 deletions(-) rename generators/app/templates/{exist-design/images => img/exist-design}/bgmenu.gif (100%) rename generators/app/templates/{exist-design/images => img/exist-design}/bgmenuhi.gif (100%) rename generators/app/templates/{exist-design/images => img/exist-design}/body-base.gif (100%) rename generators/app/templates/{exist-design/images => img/exist-design}/body.gif (100%) rename generators/app/templates/{exist-design/images => img/exist-design}/bold.gif (100%) rename generators/app/templates/{exist-design/images => img/exist-design}/code.gif (100%) rename generators/app/templates/{exist-design/images => img/exist-design}/delete-icon.png (100%) rename generators/app/templates/{exist-design/images => img/exist-design}/existdb.png (100%) rename generators/app/templates/{exist-design/images => img/exist-design}/glyphicons-halflings.png (100%) rename generators/app/templates/{exist-design/images => img/exist-design}/grey-box-bot.gif (100%) rename generators/app/templates/{exist-design/images => img/exist-design}/grey-box-rpt.gif (100%) rename generators/app/templates/{exist-design/images => img/exist-design}/grey-box-top.gif (100%) rename generators/app/templates/{exist-design/images => img/exist-design}/header.gif (100%) rename generators/app/templates/{exist-design/images => img/exist-design}/horizontal.gif (100%) rename generators/app/templates/{exist-design/images => img/exist-design}/italic.gif (100%) rename generators/app/templates/{exist-design/images => img/exist-design}/nav-dropdown.gif (100%) rename generators/app/templates/{exist-design/images => img/exist-design}/nav-dropdown.png (100%) rename generators/app/templates/{exist-design/images => img/exist-design}/nav.gif (100%) rename generators/app/templates/{exist-design/images => img/exist-design}/page-edit-icon.png (100%) create mode 100644 generators/app/templates/img/exist_icon_16x16.ico create mode 100644 generators/app/templates/js/loadsource.js create mode 100644 generators/app/templates/styles/exist-2.2.css rename generators/app/templates/{ => styles}/style.css (100%) diff --git a/generators/app/index.js b/generators/app/index.js index 79af6c83..d2d01d28 100644 --- a/generators/app/index.js +++ b/generators/app/index.js @@ -4,7 +4,6 @@ const chalk = require('chalk') const yosay = require('yosay') const prettyData = require('gulp-pretty-data') const stripBom = require('gulp-stripbom') -const pjson = require('../../package.json') module.exports = class extends Generator { initializing () { @@ -378,15 +377,6 @@ module.exports = class extends Generator { homepage: '', bugs: '', keywords: ['exist', 'exist-db', 'xml', 'xql', 'xquery'], - devDependencies: { - chai: pjson.devDependencies.chai, - 'chai-xml': pjson.devDependencies['chai-xml'], - 'fs-extra': pjson.devDependencies['fs-extra'], - mocha: pjson.devDependencies.mocha, - supertest: pjson.devDependencies.supertest, - xmldoc: pjson.devDependencies.xmldoc, - 'yeoman-assert': pjson.devDependencies['yeoman-assert'] - }, author: { name: this.props.author, email: this.props.email @@ -397,6 +387,15 @@ module.exports = class extends Generator { }, repository: '' } + + this.npmInstall(['chai'], { 'save-dev': true }) + this.npmInstall(['chai-xml'], { 'save-dev': true }) + this.npmInstall(['fs-extra'], { 'save-dev': true }) + this.npmInstall(['mocha'], { 'save-dev': true }) + this.npmInstall(['supertest'], { 'save-dev': true }) + this.npmInstall(['xmldoc'], { 'save-dev': true }) + this.npmInstall(['yeoman-assert'], { 'save-dev': true }) + // EXPATH // Applies to all (build, expath-pkg, repo, xqs) // TODO #56 html -> xhtml @@ -515,9 +514,7 @@ module.exports = class extends Generator { short: this.props.short }) - Object.assign(pkgJson.devDependencies, { - cypress: pjson.devDependencies.cypress - }) + this.npmInstall(['cypress'], { 'save-dev': true }) Object.assign(pkgJson.scripts, { cypress: 'cypress run' @@ -537,7 +534,7 @@ module.exports = class extends Generator { apptype: this.props.apptype[0] }) this.fs.copyTpl( - this.templatePath('style.css'), + this.templatePath('styles/style.css'), this.destinationPath('resources/css/style.css'), { apptype: this.props.apptype[0] }) @@ -589,6 +586,19 @@ module.exports = class extends Generator { index: this.props.index, short: this.props.short }) + // #36 shared-resources + this.fs.copy( + this.templatePath('img/exist_icon_16x16.ico'), + this.destinationPath('resources/images/exist_icon_16x16.ico') + ) + + this.fs.copy( + this.templatePath('js/**'), + this.destinationPath('resources/scripts/') + ) + + this.npmInstall(['jquery@1']) + this.npmInstall(['bootstrap@3']) // distinct contents (flexible) // see #28 @@ -601,9 +611,13 @@ module.exports = class extends Generator { mysec: this.props.mysec }) this.fs.copy( - this.templatePath('exist-design/images/**'), + this.templatePath('img/exist-design/**'), this.destinationPath('resources/images/') ) + this.fs.copy( + this.templatePath('styles/exist-2.2.css'), + this.destinationPath('resources/styles/exist-2.2.css') + ) break case 'plain': this.fs.copyTpl( @@ -644,25 +658,24 @@ module.exports = class extends Generator { apptype: this.props.apptype[1] } ) - Object.assign(pkgJson.devDependencies, { - '@existdb/gulp-exist': pjson.devDependencies['@existdb/gulp-exist'], - '@existdb/gulp-replace-tmpl': pjson.devDependencies, - del: pjson.devDependencies.del, - gulp: pjson.devDependencies.gulp, - 'gulp-autoprefixer': pjson.devDependencies['gulp-autoprefixer'], - 'gulp-concat': pjson.devDependencies['gulp-concat'], - 'gulp-cssnano': pjson.devDependencies['gulp-cssnano'], - 'gulp-flatmap': pjson.devDependencies['gulp-flatmap'], - 'gulp-header': pjson.devDependencies['gulp-header'], - 'gulp-muxml': pjson.devDependencies['gulp-muxml'], - 'gulp-rename': pjson.devDependencies['gulp-rename'], - 'gulp-sass': pjson.devDependencies['gulp-sass'], - 'gulp-sourcemaps': pjson.devDependencies['gulp-sourcemaps'], - 'gulp-svgmin': pjson.devDependencies['gulp-svgmin'], - 'gulp-uglify': pjson.devDependencies['gulp-uglify'], - 'gulp-zip': pjson.devDependencies['gulp-zip'], - lazypipe: pjson.devDependencies.lazypipe - }) + this.npmInstall(['@existdb/gulp-exist'], { 'save-dev': true }) + this.npmInstall(['@existdb/gulp-replace-tmpl'], { 'save-dev': true }) + this.npmInstall(['del'], { 'save-dev': true }) + this.npmInstall(['gulp'], { 'save-dev': true }) + this.npmInstall(['gulp-autoprefixer'], { 'save-dev': true }) + this.npmInstall(['gulp-concat'], { 'save-dev': true }) + this.npmInstall(['gulp-cssnano'], { 'save-dev': true }) + this.npmInstall(['gulp-flatmap'], { 'save-dev': true }) + this.npmInstall(['gulp-header'], { 'save-dev': true }) + this.npmInstall(['gulp-muxml'], { 'save-dev': true }) + this.npmInstall(['gulp-rename'], { 'save-dev': true }) + this.npmInstall(['gulp-sass'], { 'save-dev': true }) + this.npmInstall(['gulp-sourcemaps'], { 'save-dev': true }) + this.npmInstall(['gulp-svgmin'], { 'save-dev': true }) + this.npmInstall(['gulp-uglify'], { 'save-dev': true }) + this.npmInstall(['gulp-zip'], { 'save-dev': true }) + this.npmInstall(['lazypipe'], { 'save-dev': true }) + Object.assign(pkgJson.scripts, { build: 'gulp build', deploy: 'gulp install' @@ -818,18 +831,34 @@ module.exports = class extends Generator { } install () { - this.installDependencies({ - npm: true, - bower: false, - yarn: false - }) + this.npmInstall() } end () { + // TODO insert new project layout here? + // #513 could run cypress here + + // #36 Shared-resources + // TODO: test successful move of vendor scripts into resources + // if (this.props.apptype[0] !== 'empty') { + // this.fs.copyDestination ( + // this.destinationRoot('node_modules/bootstrap/dist/js/bootstrap.min.js'), + // this.destinationPath('resources/scripts/bootstrap.min.js') + // ) + // this.fs.copyDestination ( + // this.destinationRoot('node_modules/jquery/dist/jquery.min.js'), + // this.destinationPath('resources/scripts/jquery.min.js') + // ) + // this.fs.copyDestination( + // this.destinationRoot('node_modules/bootstrap/dist/css/bootstrap.min.css'), + // this.destinationPath('resources/styles/bootstrap.min.css') + // ) + // } + if (this.props.github) { this.spawnCommandSync('git', ['init']) this.spawnCommandSync('git', ['add', '--all']) - this.spawnCommandSync('git', ['commit', '-q', '-m', '\'initial scaffolding by Yeoman\'']) + this.spawnCommandSync('git', ['commit', '-q', '-m', '\'chore(init): scaffolding by Yeoman\'']) } // TODO: [gulp] line-o make conditional on selected build tool this.spawnCommandSync('ant', '-q') diff --git a/generators/app/templates/exist-design/page.html b/generators/app/templates/exist-design/page.html index 90560958..73f23dd5 100755 --- a/generators/app/templates/exist-design/page.html +++ b/generators/app/templates/exist-design/page.html @@ -4,12 +4,12 @@ <%- title %> - - + + -