@suitegeezus/suitecloud-stacker 25.2.127
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.idea/compiler.xml +6 -0
- package/.idea/git_toolbox_blame.xml +6 -0
- package/.idea/git_toolbox_prj.xml +15 -0
- package/.idea/misc.xml +6 -0
- package/.idea/modules.xml +8 -0
- package/.idea/suitecloud-stacker.iml +9 -0
- package/.idea/vcs.xml +6 -0
- package/CONTRIBUTING.md +72 -0
- package/README.md +242 -0
- package/bin/updateModule.d.ts +6 -0
- package/bin/updateModule.js +12 -0
- package/commands/CONTRIBUTING.md +7 -0
- package/commands/accountManageauth.d.ts +93 -0
- package/commands/accountManageauth.js +228 -0
- package/commands/accountSetup.d.ts +56 -0
- package/commands/accountSetup.js +218 -0
- package/commands/customhook/compiless.d.ts +10 -0
- package/commands/customhook/compiless.js +46 -0
- package/commands/customhook/watchss.d.ts +14 -0
- package/commands/customhook/watchss.js +77 -0
- package/commands/fileImport.d.ts +31 -0
- package/commands/fileImport.js +503 -0
- package/commands/fileList.d.ts +19 -0
- package/commands/fileList.js +40 -0
- package/commands/fileUpload.d.ts +52 -0
- package/commands/fileUpload.js +355 -0
- package/commands/generic.d.ts +5 -0
- package/commands/generic.js +13 -0
- package/commands/objectImport.d.ts +32 -0
- package/commands/objectImport.js +287 -0
- package/commands/objectList.d.ts +13 -0
- package/commands/objectList.js +78 -0
- package/commands/projectCreate.d.ts +31 -0
- package/commands/projectCreate.js +506 -0
- package/commands/projectDeploy.d.ts +25 -0
- package/commands/projectDeploy.js +371 -0
- package/commands/projectPackage.d.ts +10 -0
- package/commands/projectPackage.js +32 -0
- package/commands/projectValidate.d.ts +21 -0
- package/commands/projectValidate.js +112 -0
- package/commands/sdfAcs_authmap.d.ts +15 -0
- package/commands/sdfAcs_authmap.js +26 -0
- package/commands/sdfAcs_clean.d.ts +20 -0
- package/commands/sdfAcs_clean.js +22 -0
- package/deleteManifest.cjs +11 -0
- package/demo.md +26 -0
- package/index.d.ts +284 -0
- package/lib/MakeJestTestsFromDeploy.d.ts +13 -0
- package/lib/MakeJestTestsFromDeploy.js +60 -0
- package/lib/addGitKeep.d.ts +5 -0
- package/lib/addGitKeep.js +40 -0
- package/lib/addSdfObjectDirs.d.ts +5 -0
- package/lib/addSdfObjectDirs.js +16 -0
- package/lib/callCli.d.ts +7 -0
- package/lib/callCli.js +26 -0
- package/lib/compileHelper.d.ts +44 -0
- package/lib/compileHelper.js +196 -0
- package/lib/deleteProjectJson.d.ts +6 -0
- package/lib/deleteProjectJson.js +16 -0
- package/lib/deployFileHelper.d.ts +77 -0
- package/lib/deployFileHelper.js +249 -0
- package/lib/handleRootProjectJson.d.ts +10 -0
- package/lib/handleRootProjectJson.js +30 -0
- package/lib/isProd.d.ts +9 -0
- package/lib/isProd.js +13 -0
- package/lib/logHelper.d.ts +5 -0
- package/lib/logHelper.js +13 -0
- package/lib/logger.d.ts +6 -0
- package/lib/logger.js +10 -0
- package/lib/makeDeployXml.d.ts +6 -0
- package/lib/makeDeployXml.js +30 -0
- package/lib/makeJest.d.ts +12 -0
- package/lib/makeJest.js +58 -0
- package/lib/makeManifestXml.d.ts +6 -0
- package/lib/makeManifestXml.js +21 -0
- package/lib/makeProjectJson.d.ts +6 -0
- package/lib/makeProjectJson.js +16 -0
- package/lib/onErrorHelper.d.ts +31 -0
- package/lib/onErrorHelper.js +93 -0
- package/lib/pathHelpers.d.ts +133 -0
- package/lib/pathHelpers.js +428 -0
- package/lib/pause.d.ts +6 -0
- package/lib/pause.js +10 -0
- package/lib/projectJsonHelpers.d.ts +29 -0
- package/lib/projectJsonHelpers.js +92 -0
- package/lib/promptHelpers.d.ts +77 -0
- package/lib/promptHelpers.js +195 -0
- package/lib/removeFiles.d.ts +20 -0
- package/lib/removeFiles.js +46 -0
- package/lib/sdf.d.ts +11 -0
- package/lib/sdf.js +158 -0
- package/lib/spawnSuitecloudChild.d.ts +30 -0
- package/lib/spawnSuitecloudChild.js +88 -0
- package/lib/switchAuth.d.ts +17 -0
- package/lib/switchAuth.js +23 -0
- package/lib/tempFileHelper.d.ts +29 -0
- package/lib/tempFileHelper.js +70 -0
- package/lib/updateModule.d.ts +10 -0
- package/lib/updateModule.js +79 -0
- package/lib/validators.d.ts +12 -0
- package/lib/validators.js +25 -0
- package/package.json +38 -0
- package/safeCommands.d.ts +95 -0
- package/safeCommands.js +959 -0
- package/sdf.config.js +15 -0
- package/sdf.exe.js +16 -0
- package/templates/customizations.projectroot.d.ts +74 -0
- package/templates/makeModuleTypeDef.d.ts +5 -0
- package/templates/makeModuleTypeDef.js +29 -0
- package/templates/sdfGitIgnore.txt +42 -0
- package/templates/suitecloud.config.js +17 -0
- package/templates/tsconfig.ss21.projectroot.json +64 -0
- package/types/colors.d.ts +43 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @file sdf/lib/promptHelpers.ts
|
|
4
|
+
* @author Gerald Gillespie <gerald.gillespie@fullscript.com>
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.promptChoices = exports.promptUserSync = exports.promptUser = exports.detectPrompt = exports.appendToPrevious = exports.goColor = void 0;
|
|
8
|
+
const readline = require('node:readline');
|
|
9
|
+
const SpawnSuitecloud = require("./spawnSuitecloudChild");
|
|
10
|
+
const Colors = {
|
|
11
|
+
WARN: "\u001B[38;5;214m" /* COLORS.ORANGE */,
|
|
12
|
+
BAD: "\u001B[31m" /* COLORS.RED */,
|
|
13
|
+
INFO: "\u001B[36m" /* COLORS.CYAN */,
|
|
14
|
+
HIGHLIGHT: "\u001B[33m" /* COLORS.YELLOW */,
|
|
15
|
+
GOOD: "\u001B[32m" /* COLORS.GREEN */, // '\x1b[32m', // green
|
|
16
|
+
NONE: "\u001B[0m" /* COLORS.RESET_ALL */, // '\x1b[0m', // reset
|
|
17
|
+
BOLD: "\u001B[1m" /* COLORS.BOLD */, // '\x1b[1m',
|
|
18
|
+
SUBTLE: "\u001B[90m" /* COLORS.BRIGHT_BLACK */, // `\x1b[90m` // grey
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* @description
|
|
22
|
+
* @param {Array<string|keyof typeof Colors>} colors
|
|
23
|
+
* @param {string[]} messages
|
|
24
|
+
* @param {boolean} skipReset
|
|
25
|
+
* @returns {string}
|
|
26
|
+
*/
|
|
27
|
+
exports.goColor = ((colors, ...messages) => {
|
|
28
|
+
let skip = typeof messages[messages.length - 1] === 'boolean' ? messages.pop() : false;
|
|
29
|
+
const msgStrings = messages.map((m) => {
|
|
30
|
+
switch (true) {
|
|
31
|
+
case m === null:
|
|
32
|
+
return null;
|
|
33
|
+
case typeof m === 'object':
|
|
34
|
+
return JSON.stringify(m);
|
|
35
|
+
default:
|
|
36
|
+
return String(m);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
// @ts-expect-error is good
|
|
40
|
+
return `${skip ? '' : Colors.NONE}${[colors].flat().map((c) => Colors?.[c]).join('')}${msgStrings.join('')}${skip ? '' : Colors.NONE}`;
|
|
41
|
+
});
|
|
42
|
+
const QuestionPrompt = (0, exports.goColor)('SUBTLE', 'ANSWER: ');
|
|
43
|
+
/**
|
|
44
|
+
* @description
|
|
45
|
+
* @param {string} previousMessage
|
|
46
|
+
* @param {string} toAppend
|
|
47
|
+
* @returns {string}
|
|
48
|
+
*/
|
|
49
|
+
const appendToPrevious = (previousMessage, toAppend) => {
|
|
50
|
+
readline.moveCursor(process.stdout, 0, -1);
|
|
51
|
+
// Position the cursor at the end of the previous line by using its length
|
|
52
|
+
readline.cursorTo(process.stdout, previousMessage.length);
|
|
53
|
+
process.stdout.write(toAppend);
|
|
54
|
+
};
|
|
55
|
+
exports.appendToPrevious = appendToPrevious;
|
|
56
|
+
/**
|
|
57
|
+
* @description -
|
|
58
|
+
* @param line
|
|
59
|
+
* @returns {boolean}
|
|
60
|
+
*/
|
|
61
|
+
const detectPrompt = (line) => {
|
|
62
|
+
// console.log(line === QuestionPrompt? 'ischild': '');
|
|
63
|
+
return line === (0, exports.goColor)('SUBTLE', 'ANSWER: ');
|
|
64
|
+
};
|
|
65
|
+
exports.detectPrompt = detectPrompt;
|
|
66
|
+
/**
|
|
67
|
+
* @param {{message: string; timeout?: number;}} options
|
|
68
|
+
* @param {(string)=>any} [callback]
|
|
69
|
+
* @returns {Promise<string|null>}
|
|
70
|
+
*/
|
|
71
|
+
const promptUser = async ({ message, timeout }, callback) => {
|
|
72
|
+
const rl = readline.createInterface({
|
|
73
|
+
input: process.stdin,
|
|
74
|
+
output: process.stdout,
|
|
75
|
+
prompt: QuestionPrompt
|
|
76
|
+
});
|
|
77
|
+
console.log(`\n${(0, exports.goColor)('BOLD', message || 'Hit Enter to continue')}`);
|
|
78
|
+
// Display the prompt
|
|
79
|
+
rl.prompt();
|
|
80
|
+
return new Promise((resolve, reject) => {
|
|
81
|
+
rl.once('line', (line) => {
|
|
82
|
+
console.log((0, exports.goColor)('SUBTLE', 'You pressed:', line, false));
|
|
83
|
+
resolve(line);
|
|
84
|
+
});
|
|
85
|
+
if (typeof timeout === 'number') {
|
|
86
|
+
setTimeout(() => {
|
|
87
|
+
resolve(null);
|
|
88
|
+
}, timeout);
|
|
89
|
+
}
|
|
90
|
+
rl.once('close', (e) => {
|
|
91
|
+
console.log((0, exports.goColor)('SUBTLE', 'Exiting'));
|
|
92
|
+
if (e)
|
|
93
|
+
reject(e);
|
|
94
|
+
});
|
|
95
|
+
}).then((answer) => {
|
|
96
|
+
rl.close();
|
|
97
|
+
return (typeof callback === 'function' ? callback(answer) : answer);
|
|
98
|
+
}).catch((err) => {
|
|
99
|
+
if (typeof callback === 'function')
|
|
100
|
+
return callback(err);
|
|
101
|
+
else
|
|
102
|
+
throw (err);
|
|
103
|
+
});
|
|
104
|
+
};
|
|
105
|
+
exports.promptUser = promptUser;
|
|
106
|
+
const promptUserSync = ({ message, timeout }, callback) => {
|
|
107
|
+
const rl = readline.createInterface({
|
|
108
|
+
input: process.stdin,
|
|
109
|
+
output: process.stdout,
|
|
110
|
+
prompt: (0, exports.goColor)('SUBTLE', '> ')
|
|
111
|
+
});
|
|
112
|
+
console.log(`\n${(0, exports.goColor)('BOLD', message || 'Hit Enter to continue')}`);
|
|
113
|
+
// Display the prompt
|
|
114
|
+
rl.prompt();
|
|
115
|
+
rl.once('line', (line) => {
|
|
116
|
+
console.log((0, exports.goColor)('SUBTLE', 'You pressed:', line, false));
|
|
117
|
+
rl.close();
|
|
118
|
+
});
|
|
119
|
+
if (typeof timeout === 'number') {
|
|
120
|
+
setTimeout(() => {
|
|
121
|
+
rl.close();
|
|
122
|
+
}, timeout);
|
|
123
|
+
}
|
|
124
|
+
rl.once('close', (e) => {
|
|
125
|
+
console.log((0, exports.goColor)('SUBTLE', 'Exiting'));
|
|
126
|
+
if (e)
|
|
127
|
+
throw e;
|
|
128
|
+
});
|
|
129
|
+
};
|
|
130
|
+
exports.promptUserSync = promptUserSync;
|
|
131
|
+
/**
|
|
132
|
+
* @description - pass in a array of strings to be presented with a numbered choice list
|
|
133
|
+
* 0 is always "QUIT" (even if not presented) and the program will exit with code 0 (coincidence on the number)
|
|
134
|
+
* "-1" is always the default -- this helps with automation
|
|
135
|
+
*
|
|
136
|
+
* @param {{choices: string[]}} options
|
|
137
|
+
* @returns {Promise<string>}
|
|
138
|
+
*/
|
|
139
|
+
const promptChoices = async (options) => {
|
|
140
|
+
const { choices, question, displayChoices, childDefault } = options;
|
|
141
|
+
if (typeof childDefault !== 'undefined' && SpawnSuitecloud.isChildProcess())
|
|
142
|
+
return options.childDefault;
|
|
143
|
+
if (displayChoices.length !== choices.length)
|
|
144
|
+
throw new Error(`displayChoices must match choices`);
|
|
145
|
+
let answer;
|
|
146
|
+
if ((Array.isArray(choices) !== Array.isArray(displayChoices))
|
|
147
|
+
|| choices?.length !== displayChoices?.length) {
|
|
148
|
+
throw new Error(`displayChoices must be of same structure and length as choices`);
|
|
149
|
+
}
|
|
150
|
+
// const choices: Array<typeof nature> = ['path','regex'];
|
|
151
|
+
if (Reflect.get(choices, 'Q'))
|
|
152
|
+
throw new Error('choices cannot contain index of "Q"');
|
|
153
|
+
let maxKeyLength = 0;
|
|
154
|
+
const reIndexChoices = Array.isArray(choices) ? [undefined, ...choices] : choices;
|
|
155
|
+
const printChoices = (Array.isArray(displayChoices)
|
|
156
|
+
? ['QUIT', ...displayChoices].map((c, i) => [(i === 0 ? 'Q' : String(i)), c])
|
|
157
|
+
: Object.entries({ ...{ 'Q': 'FORCE QUIT' + (0, exports.goColor)('SUBTLE', ' skips cleanup -- not recommend') }, ...displayChoices }))
|
|
158
|
+
.sort(([a, y], [b, z]) => {
|
|
159
|
+
maxKeyLength = Math.max(maxKeyLength, a.length);
|
|
160
|
+
return (a === 'Q' ? -1 : 0);
|
|
161
|
+
})
|
|
162
|
+
.map(([i, c]) => `${(0, exports.goColor)('HIGHLIGHT', i.padEnd(maxKeyLength, ' '))}: ${(0, exports.goColor)('INFO', c)}`);
|
|
163
|
+
const nag = async (msg) => {
|
|
164
|
+
if (typeof msg === 'string')
|
|
165
|
+
process.stdout.write((0, exports.goColor)('SUBTLE', '\nYou entered:', msg));
|
|
166
|
+
if (options.premessage)
|
|
167
|
+
process.stdout.write((0, exports.goColor)('SUBTLE', '\n', options.premessage));
|
|
168
|
+
answer = await (0, exports.promptUser)({
|
|
169
|
+
message: `${question} \n${printChoices.join('\n')}`,
|
|
170
|
+
});
|
|
171
|
+
};
|
|
172
|
+
while (
|
|
173
|
+
// @ts-expect-error that's ok
|
|
174
|
+
!reIndexChoices[answer] &&
|
|
175
|
+
!['Q', '-1', '0'].includes(String(answer))) {
|
|
176
|
+
// console.log({reIndexChoices, answer});
|
|
177
|
+
await nag(String(answer));
|
|
178
|
+
}
|
|
179
|
+
if (
|
|
180
|
+
// intentional quit
|
|
181
|
+
['Q', '0'].includes(String(answer))
|
|
182
|
+
// implied quit
|
|
183
|
+
|| (String(answer) === '-1' && ['Q', 'QUIT'].includes(String(options?.default || 0)))) {
|
|
184
|
+
process.stdout.write((0, exports.goColor)('WARN', '\nYou chose to Quit ✅\n'));
|
|
185
|
+
process.exit(1);
|
|
186
|
+
}
|
|
187
|
+
return (String(answer) === '-1' && options.default
|
|
188
|
+
? options.default
|
|
189
|
+
: Array.isArray(choices)
|
|
190
|
+
? reIndexChoices[Number.parseInt(String(answer), 10)]
|
|
191
|
+
: choices[answer]);
|
|
192
|
+
throw new Error('misconfigured question');
|
|
193
|
+
};
|
|
194
|
+
exports.promptChoices = promptChoices;
|
|
195
|
+
//# sourceMappingURL=promptHelpers.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file sdf/lib/removeFiles.ts
|
|
3
|
+
* @author Gerald Gillespie <gerald.gillespie@fullscript.com>
|
|
4
|
+
*/
|
|
5
|
+
type FilesList = 'manifest.xml' | 'deploy.xml' | 'project.json' | 'tsconfig.json' | 'jest.config.js' | '.project.json';
|
|
6
|
+
/**
|
|
7
|
+
* @description - Deletes files from the list
|
|
8
|
+
* - optional backup with .bak extension
|
|
9
|
+
* @param options
|
|
10
|
+
* @param {boolean|string} [options.doBackup] - A non-empty short string can be used as the extension. Default is .bak
|
|
11
|
+
* @param {string} options.root
|
|
12
|
+
* @param {string[]} options.fileNames
|
|
13
|
+
* @returns {string[]} - State of the deletes
|
|
14
|
+
*/
|
|
15
|
+
declare const removeFiles: (options: {
|
|
16
|
+
fileNames: (FilesList | string)[];
|
|
17
|
+
root: string;
|
|
18
|
+
doBackup?: boolean | string;
|
|
19
|
+
}) => (string | null)[];
|
|
20
|
+
export = removeFiles;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @file sdf/lib/removeFiles.ts
|
|
4
|
+
* @author Gerald Gillespie <gerald.gillespie@fullscript.com>
|
|
5
|
+
*/
|
|
6
|
+
const fs = require("node:fs");
|
|
7
|
+
const nodePath = require("node:path");
|
|
8
|
+
const promptHelpers = require("./promptHelpers");
|
|
9
|
+
const promptHelpers_1 = require("./promptHelpers");
|
|
10
|
+
const filesList = ['manifest.xml', 'deploy.xml', 'project.json', '.project.json', 'tsconfig.json', 'jest.config.js'];
|
|
11
|
+
/**
|
|
12
|
+
* @description - Deletes files from the list
|
|
13
|
+
* - optional backup with .bak extension
|
|
14
|
+
* @param options
|
|
15
|
+
* @param {boolean|string} [options.doBackup] - A non-empty short string can be used as the extension. Default is .bak
|
|
16
|
+
* @param {string} options.root
|
|
17
|
+
* @param {string[]} options.fileNames
|
|
18
|
+
* @returns {string[]} - State of the deletes
|
|
19
|
+
*/
|
|
20
|
+
const removeFiles = (options) => {
|
|
21
|
+
const { fileNames, root, doBackup } = options;
|
|
22
|
+
return fileNames.map((name) => {
|
|
23
|
+
const path = nodePath.join(root, name);
|
|
24
|
+
if (![...filesList].includes(name))
|
|
25
|
+
return null;
|
|
26
|
+
const extension = typeof doBackup === 'string' && /^\w{2,4}$/.test(doBackup)
|
|
27
|
+
? `.${doBackup}`
|
|
28
|
+
: doBackup ? '.bak' : '';
|
|
29
|
+
try {
|
|
30
|
+
if (doBackup)
|
|
31
|
+
fs.cpSync(path, path + extension);
|
|
32
|
+
process.stdout.write(promptHelpers.goColor('INFO', '\nremoving ', (0, promptHelpers_1.goColor)('SUBTLE', ' ', path, ' ')));
|
|
33
|
+
fs.rmSync(path);
|
|
34
|
+
return path;
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
const { message } = error;
|
|
38
|
+
if (/no such file/.test(message))
|
|
39
|
+
return path;
|
|
40
|
+
process.stdout.write(promptHelpers.goColor('INFO', '\nfailed to remove ', path, '\n', promptHelpers.goColor('BAD', message)));
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
module.exports = removeFiles;
|
|
46
|
+
//# sourceMappingURL=removeFiles.js.map
|
package/lib/sdf.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file sdf/lib/sdf.ts
|
|
3
|
+
* @author Gerald Gillespie <gerald.gillespie@fullscript.com>
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* @description - Extract arguments and create a native command and execute it.
|
|
7
|
+
* - Note that native SDF supports having a colon and that is not recommended here.
|
|
8
|
+
* @param {string[]} commandLineArguments
|
|
9
|
+
* @returns {void}
|
|
10
|
+
*/
|
|
11
|
+
export declare const executeCommand: (commandLineArguments: string[]) => void;
|
package/lib/sdf.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @file sdf/lib/sdf.ts
|
|
4
|
+
* @author Gerald Gillespie <gerald.gillespie@fullscript.com>
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.executeCommand = void 0;
|
|
8
|
+
const makeProjectJson = require("./makeProjectJson");
|
|
9
|
+
const spawnNativeSdf = require("./callCli");
|
|
10
|
+
const removeFiles = require("./removeFiles");
|
|
11
|
+
const sdfAcsAuthMap = require("../commands/sdfAcs_authmap");
|
|
12
|
+
const nodePath = require("node:path");
|
|
13
|
+
const commandsThatNativelyNeedAuthId = ['account:setup', 'account:setup:ci'];
|
|
14
|
+
const commandsThatWithGrace = ['account:manageauth', '-h', '--help', '--version'];
|
|
15
|
+
const passThroughCommands = ['--version', '-h', '--help', '-i'];
|
|
16
|
+
const printSdfAcsHelp = () => {
|
|
17
|
+
console.log('\n');
|
|
18
|
+
[
|
|
19
|
+
['sdfAcs:clean', 'removes native manifest, deploy and project.json files'],
|
|
20
|
+
].forEach(([a, b]) => console.log([a.padEnd(30), b].join('')));
|
|
21
|
+
console.log('\n');
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* @description - Extract the command arguments that are not-native to suitecloud-cli
|
|
25
|
+
* - Passthrough the rest.
|
|
26
|
+
* @param {string[]} commandLineArguments - From the original call
|
|
27
|
+
* @returns {Record<string,string|true>}
|
|
28
|
+
*/
|
|
29
|
+
const handleCommandLine = (commandLineArguments) => {
|
|
30
|
+
return commandLineArguments.reduce((accumulator, argument, index, original) => {
|
|
31
|
+
// commands
|
|
32
|
+
if (/:/.test(argument) && index === 0)
|
|
33
|
+
return {
|
|
34
|
+
...accumulator,
|
|
35
|
+
[argument]: null,
|
|
36
|
+
};
|
|
37
|
+
// skip values
|
|
38
|
+
if (!argument.startsWith("-"))
|
|
39
|
+
return accumulator;
|
|
40
|
+
let property = argument;
|
|
41
|
+
// arguments with no value means the next argument is a property and the implied value is true
|
|
42
|
+
let [nextArgument] = [original[index + 1]].filter((n) => !n || !n.startsWith('-'));
|
|
43
|
+
// after filtering if we have a nextArgument the value must be true
|
|
44
|
+
let value = typeof nextArgument === 'undefined' ? true : nextArgument;
|
|
45
|
+
return {
|
|
46
|
+
...accumulator,
|
|
47
|
+
[property]: value,
|
|
48
|
+
};
|
|
49
|
+
}, {});
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* @description - Extract arguments and create a native command and execute it.
|
|
53
|
+
* - Note that native SDF supports having a colon and that is not recommended here.
|
|
54
|
+
* @param {string[]} commandLineArguments
|
|
55
|
+
* @returns {void}
|
|
56
|
+
*/
|
|
57
|
+
const executeCommand = (commandLineArguments) => {
|
|
58
|
+
// quick backup straight up
|
|
59
|
+
const filesToRemove = ['manifest.xml', 'deploy.xml', 'project.json'];
|
|
60
|
+
const removed = removeFiles({
|
|
61
|
+
fileNames: ['manifest.xml', 'deploy.xml', 'project.json'],
|
|
62
|
+
root: process.cwd(),
|
|
63
|
+
doBackup: true
|
|
64
|
+
});
|
|
65
|
+
const { '--authid': authidFolder, '--debug': debug, ...remaining } = handleCommandLine(commandLineArguments);
|
|
66
|
+
if (debug)
|
|
67
|
+
console.log({ commandLineArguments });
|
|
68
|
+
// handle a ':' being used in the real authid
|
|
69
|
+
const splitAuthIdFolder = typeof authidFolder === 'string' ? authidFolder.split(':') : [];
|
|
70
|
+
const folder = splitAuthIdFolder.pop();
|
|
71
|
+
const authid = splitAuthIdFolder.join(':') || folder;
|
|
72
|
+
if (debug)
|
|
73
|
+
console.log({ remaining, authid, folder });
|
|
74
|
+
const [command, ...nativeArguments] = Object.entries(remaining).flat().filter((a) => (typeof a === 'string'));
|
|
75
|
+
switch (true) {
|
|
76
|
+
case command === '-h':
|
|
77
|
+
case command === '--help':
|
|
78
|
+
printSdfAcsHelp();
|
|
79
|
+
break;
|
|
80
|
+
case command === 'sdfAcs:authmap':
|
|
81
|
+
// use 'dist' here because it does not matter and that should always exist
|
|
82
|
+
makeProjectJson(nodePath.join(process.cwd(), '.project.json'), 'foo', 'dist', Boolean(debug));
|
|
83
|
+
makeProjectJson(nodePath.join(process.cwd(), 'project.json'), 'foo', 'dist', Boolean(debug));
|
|
84
|
+
sdfAcsAuthMap({ authid, folder }).then((result) => {
|
|
85
|
+
const message = typeof result === 'boolean' ? `That Mapping Is${result ? '' : ' NOT'} Supported!!` : `${result}`;
|
|
86
|
+
console.log(message);
|
|
87
|
+
removeFiles({
|
|
88
|
+
fileNames: ['project.json', '.project.json', 'deploy.xml', 'manifest.xml'],
|
|
89
|
+
root: nodePath.join(process.cwd(), 'dist'),
|
|
90
|
+
doBackup: false
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
return;
|
|
94
|
+
case command === 'sdfAcs:clean':
|
|
95
|
+
if (folder)
|
|
96
|
+
removed.push(...removeFiles({
|
|
97
|
+
fileNames: ['manifest.xml', 'deploy.xml', 'project.json'],
|
|
98
|
+
root: nodePath.join(process.cwd(), folder),
|
|
99
|
+
doBackup: true
|
|
100
|
+
}));
|
|
101
|
+
console.log('Removed', removed.filter(Boolean));
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const hasHelpOrVersion = !passThroughCommands.includes(command) &&
|
|
105
|
+
nativeArguments.some((n) => passThroughCommands.includes(n));
|
|
106
|
+
const filteredArguments = nativeArguments.filter((n) => passThroughCommands.includes(n));
|
|
107
|
+
let sdfProcess;
|
|
108
|
+
if (hasHelpOrVersion && !authid && !folder) {
|
|
109
|
+
if (debug)
|
|
110
|
+
console.log('skipping project json', 'passing', { filteredArguments });
|
|
111
|
+
spawnNativeSdf([command, ...filteredArguments]);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
// most commands need an authid and a folder
|
|
115
|
+
if (!commandsThatWithGrace.includes(command) && (!authid || !folder))
|
|
116
|
+
throw new Error('Missing required argument');
|
|
117
|
+
// restore this property for authid
|
|
118
|
+
if (commandsThatNativelyNeedAuthId.includes(command))
|
|
119
|
+
nativeArguments.push('--authid', authid);
|
|
120
|
+
// before calling native, store the authid and the folder in a temporary project.json
|
|
121
|
+
if (debug)
|
|
122
|
+
console.log('making project jsons', folder);
|
|
123
|
+
makeProjectJson(nodePath.join(process.cwd(), '.project.json'), authid, folder, Boolean(debug));
|
|
124
|
+
makeProjectJson(nodePath.join(process.cwd(), 'project.json'), authid, folder, Boolean(debug));
|
|
125
|
+
sdfProcess = hasHelpOrVersion
|
|
126
|
+
? spawnNativeSdf([command, ...nativeArguments])
|
|
127
|
+
: spawnNativeSdf([command, ...nativeArguments]);
|
|
128
|
+
sdfProcess.on('close', (err) => {
|
|
129
|
+
console.log('\nSDFENDSDFENDSDFENDSDFENDSDFENDSDFENDSDFENDSDFENDSDFENDSDFENDSDFENDSDFEND');
|
|
130
|
+
if (debug)
|
|
131
|
+
console.log(err);
|
|
132
|
+
const removed = [];
|
|
133
|
+
// can do deletes here
|
|
134
|
+
if (folder)
|
|
135
|
+
removed.push(...removeFiles({
|
|
136
|
+
fileNames: ['manifest.xml', 'deploy.xml', 'project.json', '.project.json'],
|
|
137
|
+
root: nodePath.join(process.cwd(), folder),
|
|
138
|
+
doBackup: false
|
|
139
|
+
}));
|
|
140
|
+
else
|
|
141
|
+
removed.push(...removeFiles({
|
|
142
|
+
fileNames: ['manifest.xml', 'deploy.xml'],
|
|
143
|
+
root: nodePath.join(process.cwd()),
|
|
144
|
+
doBackup: false
|
|
145
|
+
}));
|
|
146
|
+
removed.push(...removeFiles({
|
|
147
|
+
fileNames: ['project.json', '.project.json'],
|
|
148
|
+
root: nodePath.join(process.cwd()),
|
|
149
|
+
doBackup: false
|
|
150
|
+
}));
|
|
151
|
+
if (debug)
|
|
152
|
+
console.log('removing files', removed);
|
|
153
|
+
else
|
|
154
|
+
console.log('cleaning up', removed.length);
|
|
155
|
+
});
|
|
156
|
+
};
|
|
157
|
+
exports.executeCommand = executeCommand;
|
|
158
|
+
//# sourceMappingURL=sdf.js.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file /Users/geraldgillespie/code/nsaccounts/sdf/lib/spawnSuitecloudChild
|
|
3
|
+
* @author Gerald Gillespie <gerald.gillespie@fullscript.com>
|
|
4
|
+
*/
|
|
5
|
+
export declare const getChildEnv: () => string;
|
|
6
|
+
/**
|
|
7
|
+
* @description - whether the process is a child process or not
|
|
8
|
+
* @returns {boolean}
|
|
9
|
+
*/
|
|
10
|
+
export declare const isChildProcess: () => boolean;
|
|
11
|
+
/**
|
|
12
|
+
* @description - a suitecloud child process run in the current-working directory
|
|
13
|
+
* will re-evaluate the same suitecloud.config.js that the outer process evaluated.
|
|
14
|
+
* You must design for this. Such as being re-prompted for the same questions, etc.
|
|
15
|
+
* - if you are piping stdout then you will need to interact with these choices programmatically.
|
|
16
|
+
* - if you inherit stdout then the user will be prompted (but it may be repetitive)
|
|
17
|
+
*
|
|
18
|
+
* @param {{onPrompt: Function}} options - a handler where you will get a handle to stdin to interact with the prompt.
|
|
19
|
+
* @returns {Promise<number>}
|
|
20
|
+
*/
|
|
21
|
+
export declare const createAsync: (options: {
|
|
22
|
+
command: string;
|
|
23
|
+
args: string[];
|
|
24
|
+
interact: boolean;
|
|
25
|
+
ultraQuiet?: boolean;
|
|
26
|
+
cwd?: string;
|
|
27
|
+
onData?: (lines: string[]) => void;
|
|
28
|
+
onPrompt?: (lines: string[], stdin: any) => void;
|
|
29
|
+
onMessage?: (lines: string) => void;
|
|
30
|
+
}) => Promise<number>;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @file /Users/geraldgillespie/code/nsaccounts/sdf/lib/spawnSuitecloudChild
|
|
4
|
+
* @author Gerald Gillespie <gerald.gillespie@fullscript.com>
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.createAsync = exports.isChildProcess = exports.getChildEnv = void 0;
|
|
8
|
+
const cp = require("node:child_process");
|
|
9
|
+
const promptHelpers = require("./promptHelpers");
|
|
10
|
+
const sdfExec = process.env['SUITECLOUD_EXE'] || 'sdf';
|
|
11
|
+
const CONSTANTS = {
|
|
12
|
+
get ENV_IS_CHILD_TO_SDF() {
|
|
13
|
+
return 'IS_CHILD_TO_SDF';
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
const getChildEnv = () => CONSTANTS.ENV_IS_CHILD_TO_SDF;
|
|
17
|
+
exports.getChildEnv = getChildEnv;
|
|
18
|
+
/**
|
|
19
|
+
* @description - whether the process is a child process or not
|
|
20
|
+
* @returns {boolean}
|
|
21
|
+
*/
|
|
22
|
+
const isChildProcess = () => Boolean(process.env[(0, exports.getChildEnv)()]);
|
|
23
|
+
exports.isChildProcess = isChildProcess;
|
|
24
|
+
/**
|
|
25
|
+
* @description - a suitecloud child process run in the current-working directory
|
|
26
|
+
* will re-evaluate the same suitecloud.config.js that the outer process evaluated.
|
|
27
|
+
* You must design for this. Such as being re-prompted for the same questions, etc.
|
|
28
|
+
* - if you are piping stdout then you will need to interact with these choices programmatically.
|
|
29
|
+
* - if you inherit stdout then the user will be prompted (but it may be repetitive)
|
|
30
|
+
*
|
|
31
|
+
* @param {{onPrompt: Function}} options - a handler where you will get a handle to stdin to interact with the prompt.
|
|
32
|
+
* @returns {Promise<number>}
|
|
33
|
+
*/
|
|
34
|
+
const createAsync = async (options) => new Promise((ok, no) => {
|
|
35
|
+
process.stdout.write(promptHelpers.goColor('WARN', `\ninvoking suitecloud w/ \`${options.command}\``));
|
|
36
|
+
const innerProcess = cp.spawn(sdfExec, [
|
|
37
|
+
options.command, // 'file:list',
|
|
38
|
+
// authId, etc should already be in the args list
|
|
39
|
+
...options.args // ['--folder',options.folder]
|
|
40
|
+
], {
|
|
41
|
+
stdio: [
|
|
42
|
+
'inherit',
|
|
43
|
+
options.interact ? 'inherit' : 'pipe',
|
|
44
|
+
'inherit',
|
|
45
|
+
],
|
|
46
|
+
cwd: options.cwd || process.cwd(),
|
|
47
|
+
env: { ...process.env, [(0, exports.getChildEnv)()]: String(process.pid) }
|
|
48
|
+
});
|
|
49
|
+
// process.stdout.write(['\n','processes', process.pid, process.ppid, innerProcess.pid].join(' '));
|
|
50
|
+
let lines = 0;
|
|
51
|
+
if (!options.interact) {
|
|
52
|
+
innerProcess.stdout.on('data', data => {
|
|
53
|
+
const dStrings = data.toString().split(/\r?\n/);
|
|
54
|
+
lines += dStrings.length;
|
|
55
|
+
if (!options.ultraQuiet) {
|
|
56
|
+
process.stdout.write(promptHelpers.goColor('INFO', '...', lines || ''));
|
|
57
|
+
}
|
|
58
|
+
if (typeof options.onMessage === 'function') {
|
|
59
|
+
options.onMessage(promptHelpers.goColor('INFO', '...', lines || ''));
|
|
60
|
+
}
|
|
61
|
+
//console.log({dStrings});
|
|
62
|
+
// detect prompt
|
|
63
|
+
const isPrompt = dStrings.find((l) => promptHelpers.detectPrompt(l));
|
|
64
|
+
if (typeof options.onPrompt === 'function')
|
|
65
|
+
options.onPrompt(dStrings, innerProcess.stdin);
|
|
66
|
+
if (typeof options.onData === 'function')
|
|
67
|
+
options.onData(dStrings);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
innerProcess.on('error', (e) => {
|
|
71
|
+
if (!options.ultraQuiet)
|
|
72
|
+
process.stdout.write(promptHelpers.goColor('BAD', '\n', e));
|
|
73
|
+
if (typeof options.onMessage === 'function') {
|
|
74
|
+
options.onMessage(promptHelpers.goColor('BAD', '\n', e));
|
|
75
|
+
}
|
|
76
|
+
no(e);
|
|
77
|
+
});
|
|
78
|
+
innerProcess.on('close', (e) => {
|
|
79
|
+
if (e)
|
|
80
|
+
no(e);
|
|
81
|
+
ok(0);
|
|
82
|
+
});
|
|
83
|
+
}).catch(err => {
|
|
84
|
+
process.stdout.write(promptHelpers.goColor('BAD', 'error', err));
|
|
85
|
+
throw err;
|
|
86
|
+
});
|
|
87
|
+
exports.createAsync = createAsync;
|
|
88
|
+
//# sourceMappingURL=spawnSuitecloudChild.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file sdf/lib/switchAuth.ts
|
|
3
|
+
* - detect an authid property and extract it.
|
|
4
|
+
* ## authid implies:
|
|
5
|
+
* - a switch to a different directory based on the account tied to that auth
|
|
6
|
+
* - a switch to that auth
|
|
7
|
+
* @author Gerald Gillespie <gerald.gillespie@fullscript.com>
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* @description - Extracts and acts on an authid property
|
|
11
|
+
* @param options
|
|
12
|
+
* @returns {typeof options} - Similar object but without the authid
|
|
13
|
+
*/
|
|
14
|
+
declare const processAuthId: (options: object & {
|
|
15
|
+
authid: string;
|
|
16
|
+
}) => {};
|
|
17
|
+
export = processAuthId;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @file sdf/lib/switchAuth.ts
|
|
4
|
+
* - detect an authid property and extract it.
|
|
5
|
+
* ## authid implies:
|
|
6
|
+
* - a switch to a different directory based on the account tied to that auth
|
|
7
|
+
* - a switch to that auth
|
|
8
|
+
* @author Gerald Gillespie <gerald.gillespie@fullscript.com>
|
|
9
|
+
*/
|
|
10
|
+
const switchAuth = (options) => {
|
|
11
|
+
// handle project.json file
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* @description - Extracts and acts on an authid property
|
|
15
|
+
* @param options
|
|
16
|
+
* @returns {typeof options} - Similar object but without the authid
|
|
17
|
+
*/
|
|
18
|
+
const processAuthId = (options) => {
|
|
19
|
+
const { authid, ...remaining } = options;
|
|
20
|
+
return remaining;
|
|
21
|
+
};
|
|
22
|
+
module.exports = processAuthId;
|
|
23
|
+
//# sourceMappingURL=switchAuth.js.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file /Users/geraldgillespie/code/nsaccounts/sdf/lib/tempFileHelper
|
|
3
|
+
* @author Gerald Gillespie <gerald.gillespie@fullscript.com>
|
|
4
|
+
*/
|
|
5
|
+
export declare const FileNames: {
|
|
6
|
+
accountManagementList: string;
|
|
7
|
+
objectList: string;
|
|
8
|
+
fileList: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* @description - usually a temp file is:
|
|
12
|
+
* - created by an 'onCompleted' handler on a child process
|
|
13
|
+
* - consumed by a 'beforeExecuting' handler of a parent process
|
|
14
|
+
* - therefore watch out for file cleanup activities
|
|
15
|
+
* @param {string} fileName
|
|
16
|
+
* @param {string} data - serialized data
|
|
17
|
+
* @returns {Promise<string>} - the new file and path
|
|
18
|
+
*/
|
|
19
|
+
export declare const makeTempFile: (fileName: string, data: string) => Promise<string>;
|
|
20
|
+
/**
|
|
21
|
+
* @description - read and delete the temp file
|
|
22
|
+
* @param {string} fileName
|
|
23
|
+
* @returns {Promise<string>}
|
|
24
|
+
*/
|
|
25
|
+
export declare const consumeTempFile: (fileName: string) => Promise<string>;
|
|
26
|
+
/**
|
|
27
|
+
* @description - removes temp files
|
|
28
|
+
*/
|
|
29
|
+
export declare const removeTempFiles: (prefix?: string) => Promise<void>;
|