Browse Source

Added code generation from blueprints

production
guest 2 years ago
parent
commit
7907f87aba
2 changed files with 210 additions and 69 deletions
  1. 1
    1
      cliverse.js
  2. 209
    68
      index.js

+ 1
- 1
cliverse.js View File

@@ -41,7 +41,7 @@ function nodeShellExec() {
// D:\chess\instances\elixir_01\elxr/.elxr/run-1630002739610/download.bat https://github.com/git-for-windows/git/releases/download/v2.33.0.windows.2/Git-2.33.0.2-64-bit.exe D:\\chess\\instances\\elixir_01\\elxr/Downloads/Git-2.33.0.2-64-bit.exe
// D:\\chess\\instances\\elixir_01\\elxr/.elxr/run-1630002923584/download.bat https://github.com/git-for-windows/git/releases/download/v2.33.0.windows.2/Git-2.33.0.2-64-bit.exe D:\\chess\\instances\\elixir_01\\elxr/Downloads/Git-2.33.0.2-64-bit.exe
console.dir(args[2])
// console.dir(args[2])
console.dir(`${args[0]} ${args[1].join(' ') }`)

const child = spawn(...args);

+ 209
- 68
index.js View File

@@ -193,30 +193,86 @@ var globSync = require('glob').sync;
const { readdir } = require("fs").promises

// Directory shallow walk and do perform on each dir.
const dirs = async (perform, path) => {
for (const dir of await readdir(path || selectedinstance.root, { withFileTypes: true })) {
if (dir.isDirectory()) perform(dir)
const dirs = async (perform, src, target, options) => {
var rs = []
for (const dir of await readdir(src || selectedinstance.root, { withFileTypes: true })) {
if (dir.isDirectory()) rs.push( perform(dir, src, target, options) )
}
return any(rs)
}

var fsMove = async function(from, to, options) {
if(!options?.innernode) {
var exists = fs.existsSync(from);
var stats = exists && fs.statSync(from);
var isDirectory = exists && stats.isDirectory();
}
else {
var isDirectory = options.innernode.isDirectory()
}

if(!isDirectory) return fs.renameSync(from, to)
fs.mkdirSync(to, { recursive : true })

var rs = [];
for (const innernode of await readdir(from, { withFileTypes: true })) {
rs.push( fsMove( path.join(from, innernode.name), path.join(to, innernode.name), { innernode } ) )
}

return any(rs)
};



// PB : TODO -- Should return a bunch of promises to wait for...
var copyrecursive = function(src, dest, perform, args) {
var exists = fs.existsSync(src);
var stats = exists && fs.statSync(src);
var isDirectory = exists && stats.isDirectory();
if (isDirectory) {
fs.mkdirSync(dest);
dirs( function(childItemName) {
copyrecursive(path.join(src, childItemName),
path.join(dest, childItemName));
}, src )
// fs.readdirSync(src).forEach(function(childItemName) {
// copyrecursive(path.join(src, childItemName),
// path.join(dest, childItemName));
// });
} else {
fs.copyFileSync(src, dest);
var copyrecursive = async function(src, target, options) {
if(!options?.innernode) {
var exists = fs.existsSync(src);
var stats = exists && fs.statSync(src);
var isDirectory = exists && stats.isDirectory();
}
else {
var isDirectory = options.innernode.isDirectory()
}

if(!isDirectory) return fs.copyFileSync(src, target)
fs.mkdirSync(target, { recursive : true })

var rs = [];
for (const innernode of await readdir(src, { withFileTypes: true })) {
rs.push( copyrecursive( path.join(src, innernode.name), path.join(target, innernode.name), { innernode } )
// .then(()=>{
// return any(actions.map( a => ()=>a(dir, { isDirectory : true}) ))
// })
)
}

return any(rs)


// return fswalk( src, {}, [
// (src, options)=> {
// if(options.innernode.isDirectory()) fs.mkdirSync(options.target, { recursive : true })
// else fs.copyFileSync(src, options.target)
// }
// ])

// var exists = fs.existsSync(src);
// var stats = exists && fs.statSync(src);
// var isDirectory = exists && stats.isDirectory();
// if (isDirectory) {
// fs.mkdirSync(dest, { recursive : true });
// return dirs( function(childItemName) {
// return copyrecursive(path.join(src, childItemName.name),
// path.join(dest, childItemName.name));
// }, src )
// } else {
// fs.copyFileSync(src, dest);
// }
};

// var renamerecursive = function(from, to){
@@ -239,67 +295,129 @@ var copyrecursive = function(src, dest, perform, args) {
// }


var regexreplaceall = function(content, strOrregexp, substitutes){
var regexreplaceall = function(content, ps){
var repmatches
var replaced = content;
while (repmatches = strOrregexp.exec(content)) {
while (repmatches = ps.strOrregexp.exec(content)) {

if(content.length > 0) {
var replacement = repmatches[0]
for(var m = 1; m < repmatches.length; m++) {
replacement = replacement.replace(matches[i], substitutes[i-1])
replacement = replacement.replace(repmatches[m], ps.substitutes[m-1])
}
replaced.replace( repmatches[0], replacement )

replaced = replaced.replace( repmatches[0], replacement )
}
}
return replaced
}

// filesystem walk
const fswalk = async (pathToWalk, options, actions) => {
// options = options || { depthfirst : true }
if(!options.innernode) {
var exists = fs.existsSync(pathToWalk);
var stats = exists && fs.statSync(pathToWalk);
var isDirectory = exists && stats.isDirectory();
}
else {
var isDirectory = options.innernode.isDirectory()
}

if(!isDirectory) return any(actions.map( a => ()=>a( pathToWalk, utils.assign({}, options
, { pathToWalk, innernode : options.innernode || { isDirectory : function(){ return true } } }) ) ))
var rs = [];
for (const innernode of await readdir(pathToWalk, { withFileTypes: true })) {
rs.push( fswalk( path.join(pathToWalk, innernode.name), utils.assign({}, options, {pathToWalk, innernode }), actions )
// .then(()=>{
// return any(actions.map( a => ()=>a(innernode, { isDirectory : true}) ))
// })
)
}
// Wait for the walk to complete before renaming directories.
Array.prototype.push.apply(rs, actions.map( a => ()=>a( pathToWalk, utils.assign({}, options
, { pathToWalk, innernode : options.innernode || { isDirectory : function(){ return true } } } ) ) ))

return any(rs)
}

var fsrecurse = function(target, options, actions, root) {
var exists = fs.existsSync(target);
var stats = exists && fs.statSync(target);
var isDirectory = exists && stats.isDirectory();
if (isDirectory) {
dirs( function(childItemName) {
fsrecurse(path.join(target, childItemName)
var tasks = []
tasks.push( dirs( function(childItemName) {
return fsrecurse(path.join(target, childItemName.name)
, options, actions, root);
}, target )
}, target ))
return any(tasks)
} else {
var prevActionResult = null;
actions.forEach( (action) => prevActionResult = action.apply(null, target, options) )
return any( actions.map( (action) => prevActionResult = action.apply(null, target, options) ))
}
};

var fslink = function(target, options){ fs.linkSync( options.from, options.to ) }
// var fslink = function(to, options){ try { fs.linkSync( to, options.from ) } catch(e) { throw e } }
var fslink = function(to, options){ fs.symlinkSync( to, options.from /*, type = "junction"*/ ) }

var fsrename = function(target, options){
var replaced = target; // PB : TODO -- streaming and async..
// PB : TODO -- streaming and async.. target could be a stream a string or a filesystem item or a tree node...

var targetname = options.innernode?.name || path.parse(target).base;
var replaced = targetname;
options.patternsubstitutions.forEach( ps => { replaced = regexreplaceall( replaced, ps ) })
if(replaced && replaced !== target) fs.renameSync(target, replaced)
return replaced
if(replaced && replaced !== targetname) {
var tr = target.replace( targetname, replaced )
fs.renameSync(target, tr)
return tr;
}
else return replaced
}

var fscontentreplace = function( target, options ){
// do many replacements in one shot in the file.
if(options.processingtype === 'inplace' && options.sourcetype === 'filesystem' ) {
var content = fs.readFileSync(target) // PB : TODO -- streaming and async..
if(options.processingtype === 'inplace' && options.sourcetype === 'filesystem' && !options.innernode.isDirectory() ) {
var content = fs.readFileSync(target, { encoding: 'utf8' }) // PB : TODO -- streaming and async..
options.patternsubstitutions.forEach( ps => { content = regexreplaceall( content, ps ) })
fs.writeFileSync(target, content)
}
}

var templatelink = function(target, options){
var targetPath = target.replace(options.workingtarget, options.destinationroot);
var targetPathBaseDir = targetPath.split("/").pop()

var linkTobase = regexreplaceall( target, /(__link__)(__base__)-server-lib/, [ '', options.base] )
var linkFromName = regexreplaceall( target, /(__link____base__-server-lib)/, [ '' ] )
var linkToName = regexreplaceall( linkFromName, new Regexp(targetPathBaseDir), [ linkTobase ] )
var targetSubPath = target.replace(options.workingtarget + '/', '' );
var targetSubPathsplit = targetSubPath.split("/")
var targetPathBaseDir = `${targetSubPathsplit[0]}/${targetSubPathsplit[1]}`

var linkToSubPathReplacement = `${options.base}-server-lib/common`

// var rgxp = new RegExp(`(__link__)${options.base}-server-lib`, "g")
var rgxp = new RegExp(`(__link__${options.base}-server-lib)`, "g")
var linkToSubPath = targetSubPath
var b = target.match(rgxp)
var linkFromName = regexreplaceall( target, { strOrregexp : rgxp, substitutes : [ '' ] } )
linkFromName = linkFromName.replace(options.workingtarget, options.destinationroot)
if(linkTobase) { // Only if the pattern matches which is link instruction.
// PB : DONT DLELETE EVERYTHING ??? Only the linkable ones... Or use an add strategy without deleting...
fs.unlinkSync( target ); fslink( { from : linkFromName, to : linkToName } )
if( b ) {
// Only if the pattern matches which is link instruction.
linkToSubPath = regexreplaceall( linkToSubPath, { strOrregexp : rgxp, substitutes : [ '' ] } )
}
options.patternsubstitutions.forEach( ps => { linkToSubPath = regexreplaceall( linkToSubPath, ps ) })
var linkToName = `${options.destinationroot}/${linkToSubPath}`

if(b){
linkToSubPath = linkToSubPath.replace( targetPathBaseDir, linkToSubPathReplacement)

// PB : DONT DELETE EVERYTHING ??? Only the linkable ones... Or use an add strategy without deleting...
fs.unlinkSync( target );
fslink( `${options.destinationroot}/${linkToSubPath}`, { from : linkFromName } )
}
else {
fsMove( `${options.workingtarget}/${linkToSubPath}`, linkToName )
// fsMove( `${options.workingtarget}/${linkToSubPath}`, linkFromName )
}
}

@@ -2145,6 +2263,8 @@ var op = {

console.log('elxr g model [modelname] => generate a model named [modelname]');
console.log('elxr g vmodel [modelname] => generate a model named [modelname]');
console.log('elxr g vmodel [modelname] --server=true => generate only a server model named [modelname]');
console.log('elxr g vmodel [modelname] --all=true => default generate server and client model named [modelname]');
console.log('elxr g => regenerate all known models');
return
}
@@ -2247,6 +2367,7 @@ var op = {
}

, 'vmodel' : (options)=>{
// node --inspect-brk elxr/index.js g vmodel qlabresults --server=true
options = options || {
generate : processedArgs['all'] ? 'all' : processedArgs['server'] ? 'server' : processedArgs['client'] ? 'client' : null
}
@@ -2256,32 +2377,50 @@ var op = {
var name = processedArgs._[2];
if(!name) return 'No name specified for generation'
var templateverse = `${selectedinstance.root}/bbhverse/__universe__/vmodel`
// var templateverse = `${selectedinstance.root}/bbhverse/__universe__/vmodel/__base__-server-lib/common/lib`
var workingtarget = `${selectedinstance.root}/.elxr/run-${runtimestamp}/temp/vmodelworkingdir`
var destination = `${selectedinstance.root}`

// Create a tmp working copy for staging the changes.
copyrecursive(templateverse, workingtarget)
var patternsubstitutions = [ { strOrregexp : /(__name__)/, substitutes : [name]} ]
var options = { source : templateverse, target : workingtarget, destinationroot : destination, workingtarget
, processingtype : 'inplace', sourcetype : 'filesystem', patternsubstitutions }
fsrecurse( workingtarget, options
, [ function(workingtarget, options){
// A series of tasks to be executed on each pattern in patternsubstitutions.
return [
// PB : TODO -- Contentreplace is better addressed in memory instead of file IO so do all regexps in sequence in one shot and then rename.
(filename, options)=>{ fscontentreplace( filename, options ) }
, (from, options)=>{ fsrename( from, options ) }
].map( t => t(workingtarget, options) )
}]
)

// Post process links in place.
fsrecurse( workingtarget, options, [ templatelink ] )
return copyrecursive(templateverse, workingtarget).then( r => {

var base = 'chess' // -- The server base from where this instance was dervied from.
var patternsubstitutions = [
{ strOrregexp : /(__name__)/g, substitutes : [name]}
, { strOrregexp : /(__instance__)/g, substitutes : [selectedinstance.instanceName]}
, { strOrregexp : /(__base__)/g, substitutes : [base]}
, { strOrregexp : /(__microservice__)/g, substitutes : [selectedinstance.microservice || selectedinstance.instanceName]}
, { strOrregexp : /(__microclient__)/g, substitutes : [selectedinstance.microclient || `${selectedinstance.instanceName}-client` || 'client']} // PB : TODO -- elixir-client etc... use a config to find the microclient..
]
var options = { source : templateverse, target : workingtarget
, base , destinationroot : destination, workingtarget
, processingtype : 'inplace', sourcetype : 'filesystem', patternsubstitutions }
var actions = [
fswalk( workingtarget, options
, [ function(t, o){
// A series of tasks to be executed on each pattern in patternsubstitutions.
return any([
// PB : TODO -- Contentreplace is better addressed in memory instead of file IO so do all regexps in sequence in one shot and then rename.
()=>{ return fscontentreplace( t, o ) }
, ()=>{ return fsrename( t, o ) }
])
}] )
// Post process links in place.
, () => dirs((innernode, s, t, o ) => fswalk( path.join(workingtarget, innernode.name), utils.assign({}, o, { innernode }), [ templatelink ] )
, workingtarget, null, options)
// Move to the final destination. Whole tree should move only top level folders are required.
// , () => fswalk( workingtarget, options, [ fsrename ])
// , () => dirs( ( child, src, target, options )=>{ return fs.renameSync(path.join(src, child.name), path.join(target, child.name) ) }
// , workingtarget, destination )
]

return any(actions);
})
// Move to the final destination. Whole tree should move only top level folders are required.
dirs(( child )=>{ return fs.renameSync(path.join(workingtarget, child), path.join(destination, child) ) }, workingtarget )
}
}

@@ -4510,7 +4649,9 @@ var startElxr = function() {
, ...detectedinstanceoptions.slice(-2), promptkeys )
// promptkeys = utils.assign(promptkeys, clioverrides)

if(cmdprompts.instanceName) {
// startElxr requires instance // Independent cmds should have already been bypassed.
// if(cmdprompts.instanceName) {
// not an instanceless cmd.
console.dir(selectedinstance)
try {
@@ -4598,8 +4739,8 @@ var startElxr = function() {
initinstances(selectedinstance)
return selectedinstance
})
}
else return Promise.resolve(true)
// }
// else return Promise.resolve(true)
})
.then(()=>{
runconfig = { NODE_ENV: selectedinstance.node_env }

Loading…
Cancel
Save