UNPKG

@sap/cds-dk

Version:

Command line client and development toolkit for the SAP Cloud Application Programming Model

100 lines (82 loc) 3.44 kB
const cds = require('../../../cds') const { read, write, exists, copy, path:{join, relative}, readdir, rimraf } = cds.utils const { mkdir, symlink } = require('fs/promises') const { renderAndCopy } = require('../../template') const projectReader = require('../../projectReader') const npmPackageRegex = /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/i module.exports = class ExtensionProjectTemplate extends require('../../plugin') { static help() { return 'Extension project' } options() { return { 'base': { type: 'string', short: 'p', help: `The project to extend.` } } } async run() { let { base, force } = cds.cli.options if (typeof base === 'string' && !base.match(npmPackageRegex)) throw `Illegal package name: ${base}` if (typeof base !== 'string' || !base?.length) base = '@capire/bookshop' const pkgJson = exists('package.json') ? await read('package.json') : { name: 'my-extension-project' } if (!pkgJson.extends || force) { pkgJson.extends = base } if (!pkgJson.workspaces?.includes('.base')) { pkgJson.workspaces ??= [] pkgJson.workspaces.push('.base') } await write('package.json', pkgJson, { spaces: 2 }) if (!exists('.base/package.json') || force) { await write('.base/package.json', {name: base}) } await nodeModulesLink(base) // remove empty and irrelevant folders await Promise.all([ rmIfEmpty('db') ]) } async addSample() { const proj = projectReader.readProject() const base = proj.extendsApp if (!base) throw 'No project to extend found in package.json. Create a new extension project with "cds init extension"' const projectSimple = base.replace(/^.*?\//, '') const extensionNamespace = `${namespacify(proj.appName)}.${namespacify(projectSimple)}` const { force } = cds.cli.options if (!exists('.base/index.cds') || force) { await copy(join(__dirname, 'files/.base/index.cds'), '.base/index.cds') } if (!exists('app/extension.cds') || force) { await renderAndCopy(join(__dirname, 'files/app'), 'app', { basePackage: base, extensionNamespace }) } if (!exists('test/data') || force) { await copy(join(__dirname, 'files/test/data/my.bookshop-Books.csv'), 'test/data/my.bookshop-Books.csv') await copy(join(__dirname, 'files/test/data/Authors.csv'), `test/data/${extensionNamespace}-x_Authors.csv`) } } // async finalize() { // console.log(`For information on project "Piper" and its pipelines see ${URLS.PIPELINE_HELP}`); // } } function namespacify(s) { return s.replace(/[/.-]/g, '_').replace(/[@]/g, '').toLowerCase() } async function rmIfEmpty(s) { exists(s) && !(await readdir(s)).length && await rimraf(s) } // Allow subsequent templates like `cds add handler` to resolve the model w/o `npm i`. // So create a symlink from node_modules to .base, anticipating what `npm i` would do. async function nodeModulesLink(base) { const link = join(cds.root, 'node_modules', base) if (exists(link)) return const scope = base.indexOf('/') > 0 && base.split('/')[0] // @scope/pkg const target = join(cds.root, 'node_modules', scope||'') await mkdir(target, { recursive: true }) const relTarget = relative(target, join(cds.root, '.base')) // console.log(`> linking ${relTarget} to ${link}`) await symlink(relTarget, link, 'junction') }