@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,228 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateList = exports.promptForAccountChoice = exports.betterList = exports.fetchAccountList = exports.saveList = void 0;
|
|
4
|
+
const pathHelpers = require("../lib/pathHelpers");
|
|
5
|
+
const promptHelpers_1 = require("../lib/promptHelpers");
|
|
6
|
+
const projectJsonHelpers = require("../lib/projectJsonHelpers");
|
|
7
|
+
const onErrorHelper = require("../lib/onErrorHelper");
|
|
8
|
+
const spawnSuitecloud = require("../lib/spawnSuitecloudChild");
|
|
9
|
+
const tempFileHelper = require("../lib/tempFileHelper");
|
|
10
|
+
const spawnSuitecloudChild_1 = require("../lib/spawnSuitecloudChild");
|
|
11
|
+
/**
|
|
12
|
+
* @description - save the list of account details as json
|
|
13
|
+
*/
|
|
14
|
+
const saveList = () => {
|
|
15
|
+
const origin = 'saveList';
|
|
16
|
+
return {
|
|
17
|
+
_origin: origin,
|
|
18
|
+
isStackable: true,
|
|
19
|
+
beforeExecuting: async (options) => {
|
|
20
|
+
return options;
|
|
21
|
+
},
|
|
22
|
+
onCompleted: async (options) => {
|
|
23
|
+
if (spawnSuitecloud.isChildProcess())
|
|
24
|
+
await tempFileHelper.makeTempFile(tempFileHelper.FileNames.accountManagementList, JSON.stringify(options));
|
|
25
|
+
return options;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
exports.saveList = saveList;
|
|
30
|
+
/** @internal */
|
|
31
|
+
const makeList = (data) => {
|
|
32
|
+
return Object.entries(data).map(([key, value]) => ({
|
|
33
|
+
authid: key,
|
|
34
|
+
domain: value.hostInfo?.hostName || value?.domain || null,
|
|
35
|
+
accountInfo: {
|
|
36
|
+
companyId: value.accountInfo?.companyId,
|
|
37
|
+
companyName: value.accountInfo?.companyName,
|
|
38
|
+
roleName: value.accountInfo?.roleName,
|
|
39
|
+
entityId: value.accountInfo?.entityId,
|
|
40
|
+
},
|
|
41
|
+
auth: {
|
|
42
|
+
certificateId: value.certificateInfo?.certificateId,
|
|
43
|
+
// only available in 2.0
|
|
44
|
+
privatekeyPath: value.certificateInfo?.privateKeyPath || 'no longer available >2.0',
|
|
45
|
+
expiration: value.token?.expirationDate,
|
|
46
|
+
partialPrivateKey: value.certificateInfo?.privateKey
|
|
47
|
+
? value.certificateInfo.privateKey.substring(0, 30) + '...'
|
|
48
|
+
: 'not available'
|
|
49
|
+
}
|
|
50
|
+
}));
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* @description - Filters an account list for those relevant to the given account
|
|
54
|
+
* @example ```js
|
|
55
|
+
* authid: "ACMEINC-DEV",
|
|
56
|
+
* domain: "654321-sb1.app.netsuite.com",
|
|
57
|
+
* accountInfo: {
|
|
58
|
+
* companyId:"654321_SB1",
|
|
59
|
+
* companyName:"Acme, Inc (SB2)",
|
|
60
|
+
* roleName: "Administrator",
|
|
61
|
+
* entityId: "1324546",
|
|
62
|
+
* };
|
|
63
|
+
* auth: {
|
|
64
|
+
* certificateId: "aEB5fUYumwJbnvP09kR",
|
|
65
|
+
* privatekeyPath: "/Users/geraldgillespie/.keys/sdfgg.pem",
|
|
66
|
+
* expiration: "2025-03-05T14:29.3961Z",
|
|
67
|
+
* }
|
|
68
|
+
* ```
|
|
69
|
+
* @returns {Promise<ReturnType<makeList>>}
|
|
70
|
+
*/
|
|
71
|
+
const fetchAccountList = async () => {
|
|
72
|
+
// prompt for account
|
|
73
|
+
const exitCode = await spawnSuitecloud.createAsync({
|
|
74
|
+
command: 'account:manageauth',
|
|
75
|
+
args: ['--list'],
|
|
76
|
+
interact: true,
|
|
77
|
+
});
|
|
78
|
+
// now read the list from the temp file
|
|
79
|
+
const listJson = await tempFileHelper.consumeTempFile(tempFileHelper.FileNames.accountManagementList);
|
|
80
|
+
const { _data: data, _actionExecuted } = JSON.parse(listJson);
|
|
81
|
+
if (_actionExecuted === 'list')
|
|
82
|
+
return makeList(data);
|
|
83
|
+
return [];
|
|
84
|
+
};
|
|
85
|
+
exports.fetchAccountList = fetchAccountList;
|
|
86
|
+
const betterList = () => {
|
|
87
|
+
const origin = 'betterList';
|
|
88
|
+
return {
|
|
89
|
+
_origin: origin,
|
|
90
|
+
isStackable: true,
|
|
91
|
+
onCompleted: async (options) => {
|
|
92
|
+
if (!(0, spawnSuitecloudChild_1.isChildProcess)() && ['list', 'info'].includes(options._actionExecuted)) {
|
|
93
|
+
const list = options._data.authId
|
|
94
|
+
? makeList(
|
|
95
|
+
// @ts-expect-error yes it does
|
|
96
|
+
{ [options._data.authId]: options._data }) : // @ts-expect-error yes it does
|
|
97
|
+
makeList(options._data);
|
|
98
|
+
process.stdout.write((0, promptHelpers_1.goColor)('HIGHLIGHT', '\n', JSON.stringify(list, null, 2)));
|
|
99
|
+
}
|
|
100
|
+
return options;
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
exports.betterList = betterList;
|
|
105
|
+
/**
|
|
106
|
+
* @description - Prompts for account choice. This provides both verification and literal choice. If the choice does not match the current
|
|
107
|
+
* context then an error is forced -- this is because SDF does not recognize a change in the account after launching.
|
|
108
|
+
* @returns {*}
|
|
109
|
+
*/
|
|
110
|
+
const promptForAccountChoice = () => {
|
|
111
|
+
const origin = 'promptForAccountChoice';
|
|
112
|
+
return {
|
|
113
|
+
_origin: origin,
|
|
114
|
+
beforeExecuting: async (options) => {
|
|
115
|
+
if (options?.arguments?.runhooks === 'quiet')
|
|
116
|
+
return options;
|
|
117
|
+
process.stdout.write((0, promptHelpers_1.goColor)('HIGHLIGHT', '\n', options));
|
|
118
|
+
if (!Reflect.has({ ...options?.arguments }, 'authid')) {
|
|
119
|
+
throw onErrorHelper.makeError(origin, new Error(`${options.command} is missing authid. Perhaps you should not stack ${origin} here`));
|
|
120
|
+
}
|
|
121
|
+
if (options?.arguments?.calledfromcomparefiles && /\btemp\b.\bFileCabinet\b/.test(options.projectPath))
|
|
122
|
+
return options;
|
|
123
|
+
if (spawnSuitecloud.isChildProcess())
|
|
124
|
+
return options;
|
|
125
|
+
// "native" prompt
|
|
126
|
+
if (options?.arguments?.authid === 'prompt')
|
|
127
|
+
return options;
|
|
128
|
+
const isNewVersion = Boolean(options?.arguments?.authid && options?.executionPath);
|
|
129
|
+
if (isNewVersion)
|
|
130
|
+
return options;
|
|
131
|
+
try {
|
|
132
|
+
const unfilteredList = await (0, exports.fetchAccountList)();
|
|
133
|
+
const accountFromFolder = pathHelpers.getRootOfAccount(process.cwd(), true);
|
|
134
|
+
process.stdout.write((0, promptHelpers_1.goColor)('SUBTLE', '\n', JSON.stringify({ accountFromFolder }, null, 2)));
|
|
135
|
+
const filteredList = unfilteredList.filter((entry) => {
|
|
136
|
+
return entry.accountInfo.companyId.toLowerCase().startsWith(accountFromFolder.toLowerCase());
|
|
137
|
+
});
|
|
138
|
+
// process.stdout.write(goColor('SUBTLE', '\n', {filteredListForAccount}));
|
|
139
|
+
if (filteredList.length === 0) {
|
|
140
|
+
throw onErrorHelper.makeError(origin, new Error('No current authids match the given authid ' + options.arguments.authid));
|
|
141
|
+
}
|
|
142
|
+
const choices = {};
|
|
143
|
+
const displayChoices = {};
|
|
144
|
+
filteredList.forEach((d) => {
|
|
145
|
+
const [, two] = d.domain.split(/[-.]/);
|
|
146
|
+
const key = two === 'app' ? 'prod' : two;
|
|
147
|
+
displayChoices[key] = [(0, promptHelpers_1.goColor)('INFO', d.authid), (0, promptHelpers_1.goColor)('SUBTLE', `(${d.domain})`)].join(' ');
|
|
148
|
+
choices[key] = d.authid;
|
|
149
|
+
});
|
|
150
|
+
const defaultAuthId = Object.values(choices).find((c) => {
|
|
151
|
+
// console.log('accountFromFolder', choices,displayChoices,{c}, options);
|
|
152
|
+
return options.arguments.authid.toLowerCase() === c.toLowerCase();
|
|
153
|
+
}) || 'QUIT';
|
|
154
|
+
const chosenId = await (0, promptHelpers_1.promptChoices)({
|
|
155
|
+
choices,
|
|
156
|
+
displayChoices,
|
|
157
|
+
default: defaultAuthId,
|
|
158
|
+
// premessage
|
|
159
|
+
question: `Which Account to use? ${(0, promptHelpers_1.goColor)('SUBTLE', `default account is: ${defaultAuthId}`)}`,
|
|
160
|
+
}).catch((error) => {
|
|
161
|
+
process.stdout.write((0, promptHelpers_1.goColor)('BAD', '\n', error));
|
|
162
|
+
throw onErrorHelper.makeError(origin, new Error('Error in choices'));
|
|
163
|
+
});
|
|
164
|
+
if (chosenId &&
|
|
165
|
+
filteredList.flatMap((id) => {
|
|
166
|
+
if (!id?.domain)
|
|
167
|
+
return [];
|
|
168
|
+
return !id?.domain.includes('-') ? [id.authid] : [];
|
|
169
|
+
}).length > 0) {
|
|
170
|
+
// @ts-expect-error the type needs this
|
|
171
|
+
options._isProd = filteredList.some((x) => (x.authid === chosenId && /\d{5}\.app\./.test(x.domain)));
|
|
172
|
+
}
|
|
173
|
+
process.stdout.write((0, promptHelpers_1.goColor)('SUBTLE', '\nYou chose ', JSON.stringify(chosenId, null, 2)));
|
|
174
|
+
if (chosenId && chosenId === options?.arguments?.authid)
|
|
175
|
+
return options;
|
|
176
|
+
if (Reflect.has({ ...options.arguments }, 'authid') && chosenId) {
|
|
177
|
+
// update the current project.json
|
|
178
|
+
await projectJsonHelpers.updateProjectJson({ defaultAuthId: chosenId }, [process.cwd()]);
|
|
179
|
+
process.stdout.write((0, promptHelpers_1.goColor)('GOOD', '\n', `Account has been switched (in project.json) to \`${chosenId}\`. Please start the task again ✅`));
|
|
180
|
+
process.exit(0); // kill(process.pid);
|
|
181
|
+
}
|
|
182
|
+
if (!chosenId)
|
|
183
|
+
throw onErrorHelper.makeError(origin, new Error('Could not find an account to match ' + options?.arguments?.authid || 'unknown'));
|
|
184
|
+
}
|
|
185
|
+
catch (e) {
|
|
186
|
+
// console.error(e);
|
|
187
|
+
throw onErrorHelper.makeError(origin, e);
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
onError: async (error) => {
|
|
191
|
+
console.log(error);
|
|
192
|
+
await (0, promptHelpers_1.promptUser)({ message: 'pause oc' });
|
|
193
|
+
return onErrorHelper.detectOriginAndReturn(origin, error, (error) => {
|
|
194
|
+
if (`${error}`?.includes('This error is a necessary evil')) {
|
|
195
|
+
process.stdout.write((0, promptHelpers_1.goColor)('GOOD', '\n', error, '\n'));
|
|
196
|
+
}
|
|
197
|
+
else if (`${error}`.includes('No account has been set up for this project') ||
|
|
198
|
+
error.includes('No current authids')) {
|
|
199
|
+
//TODO
|
|
200
|
+
const rootFolderName = pathHelpers.getRootOfAccount(process.cwd(), true);
|
|
201
|
+
const pad = [10, '*'];
|
|
202
|
+
process.stdout.write((0, promptHelpers_1.goColor)('NONE', (0, promptHelpers_1.goColor)('BAD', '\n', ' '.padStart(...pad), error), (0, promptHelpers_1.goColor)('WARN', '\n', ' '.padStart(...pad), rootFolderName), (0, promptHelpers_1.goColor)('GOOD', '\n', ' '.padStart(...pad), 'Run '), (0, promptHelpers_1.goColor)('HIGHLIGHT', 'suitecloud account:setup:ci'), (0, promptHelpers_1.goColor)('GOOD', ' to re-use your tokens'), '\n'));
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
process.stdout.write((0, promptHelpers_1.goColor)('BAD', '\n', error, '\n'));
|
|
206
|
+
}
|
|
207
|
+
return '';
|
|
208
|
+
});
|
|
209
|
+
},
|
|
210
|
+
isStackable: true
|
|
211
|
+
};
|
|
212
|
+
};
|
|
213
|
+
exports.promptForAccountChoice = promptForAccountChoice;
|
|
214
|
+
/**
|
|
215
|
+
* @description -
|
|
216
|
+
* @param options
|
|
217
|
+
*/
|
|
218
|
+
const validateList = (options) => {
|
|
219
|
+
return {
|
|
220
|
+
_origin: 'validateList',
|
|
221
|
+
onCompleted: (options) => {
|
|
222
|
+
// TODO
|
|
223
|
+
},
|
|
224
|
+
isStackable: true,
|
|
225
|
+
};
|
|
226
|
+
};
|
|
227
|
+
exports.validateList = validateList;
|
|
228
|
+
//# sourceMappingURL=accountManageauth.js.map
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file /Users/geraldgillespie/code/nsaccounts/sdf/commands/accountSetup
|
|
3
|
+
* @author Gerald Gillespie <gerald.gillespie@fullscript.com>
|
|
4
|
+
*/
|
|
5
|
+
import { SdfCommand } from "#root/index";
|
|
6
|
+
type AccountSetupBeforeExecutingOptions<C = 'account:setup:ci' | 'account:setup'> = {
|
|
7
|
+
projectPath: string;
|
|
8
|
+
command: C;
|
|
9
|
+
arguments: {
|
|
10
|
+
authid: string;
|
|
11
|
+
} & (C extends 'account:setup:ci' ? {
|
|
12
|
+
account?: string;
|
|
13
|
+
privatekeypath?: string;
|
|
14
|
+
certificateid?: string;
|
|
15
|
+
domain?: string;
|
|
16
|
+
} : {
|
|
17
|
+
account?: undefined;
|
|
18
|
+
privatekeypath?: undefined;
|
|
19
|
+
certificateid?: undefined;
|
|
20
|
+
domain?: undefined;
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* @description - domain is not always required normally but here it is -- it make switching account easier
|
|
25
|
+
*/
|
|
26
|
+
export declare const getDefaults: () => {
|
|
27
|
+
_origin: string;
|
|
28
|
+
beforeExecuting: (options: AccountSetupBeforeExecutingOptions) => AccountSetupBeforeExecutingOptions<"account:setup:ci" | "account:setup">;
|
|
29
|
+
isStackable: boolean;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* @description - Forces that accounts have a certain naming convention
|
|
33
|
+
*
|
|
34
|
+
*/
|
|
35
|
+
export declare const forceAccountInName: () => {
|
|
36
|
+
_origin: string;
|
|
37
|
+
beforeExecuting: <C extends "account:setup:ci" | "account:setup">(options: AccountSetupBeforeExecutingOptions<C>) => AccountSetupBeforeExecutingOptions<C>;
|
|
38
|
+
onCompleted: (options: any) => any;
|
|
39
|
+
onError: (err: any) => Promise<any>;
|
|
40
|
+
isStackable: boolean;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* @description - prompt to choose from currently used auth
|
|
44
|
+
*/
|
|
45
|
+
export declare const chooseExistingCertificate: () => SdfCommand;
|
|
46
|
+
export declare const promptForAccount: () => SdfCommand;
|
|
47
|
+
/**
|
|
48
|
+
* @description - account (not folder)
|
|
49
|
+
*/
|
|
50
|
+
export declare const promptForAuthId: () => SdfCommand;
|
|
51
|
+
/**
|
|
52
|
+
* @description - Authid must be unique
|
|
53
|
+
* - Accountid technically does not need to be unique
|
|
54
|
+
*/
|
|
55
|
+
export declare const askToReplace: () => SdfCommand;
|
|
56
|
+
export {};
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @file /Users/geraldgillespie/code/nsaccounts/sdf/commands/accountSetup
|
|
4
|
+
* @author Gerald Gillespie <gerald.gillespie@fullscript.com>
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.askToReplace = exports.promptForAuthId = exports.promptForAccount = exports.chooseExistingCertificate = exports.forceAccountInName = exports.getDefaults = void 0;
|
|
8
|
+
const promptHelpers_1 = require("../lib/promptHelpers");
|
|
9
|
+
const pathHelpers_1 = require("../lib/pathHelpers");
|
|
10
|
+
const nodePath = require("node:path");
|
|
11
|
+
const spawnSuitecloud = require("../lib/spawnSuitecloudChild");
|
|
12
|
+
const accountManageauth_1 = require("../commands/accountManageauth");
|
|
13
|
+
const safeCommands_1 = require("../safeCommands");
|
|
14
|
+
const onErrorHelper = require("../lib/onErrorHelper");
|
|
15
|
+
const validators_1 = require("../lib/validators");
|
|
16
|
+
const handleRootProjectJson = require('../lib/handleRootProjectJson');
|
|
17
|
+
/**
|
|
18
|
+
* @description - domain is not always required normally but here it is -- it make switching account easier
|
|
19
|
+
*/
|
|
20
|
+
const getDefaults = () => {
|
|
21
|
+
return {
|
|
22
|
+
_origin: 'getDefaults',
|
|
23
|
+
beforeExecuting: (options) => {
|
|
24
|
+
Object.assign(options.arguments, handleRootProjectJson.readDefaultsFromJson(['privatekeypath', 'certificateid']));
|
|
25
|
+
// domain if missing
|
|
26
|
+
if (!options.arguments?.domain)
|
|
27
|
+
throw new Error('getDefaults:You must provide the domain argument always. Even for production. e.g. 1352643.app.netsuite.com');
|
|
28
|
+
return options;
|
|
29
|
+
},
|
|
30
|
+
isStackable: true,
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
exports.getDefaults = getDefaults;
|
|
34
|
+
/**
|
|
35
|
+
* @description - Forces that accounts have a certain naming convention
|
|
36
|
+
*
|
|
37
|
+
*/
|
|
38
|
+
const forceAccountInName = () => {
|
|
39
|
+
const origin = 'forceAccountInName';
|
|
40
|
+
return {
|
|
41
|
+
_origin: origin,
|
|
42
|
+
beforeExecuting: (options) => {
|
|
43
|
+
const { authid, account } = options.arguments;
|
|
44
|
+
const [firstAuthIdBit] = authid.split(/\W/);
|
|
45
|
+
const [firstAcctBit] = account.split('_');
|
|
46
|
+
//TODO instead of process.cwd() should this be options.projectPath + defaultProjectFolder (from project.json)
|
|
47
|
+
const rootOfAccount = nodePath.basename((0, pathHelpers_1.getRootOfAccount)(process.cwd())).toLowerCase();
|
|
48
|
+
if (rootOfAccount !== firstAuthIdBit.toLowerCase())
|
|
49
|
+
throw onErrorHelper.makeError(origin, new Error('The new authid MUST begin with ' + rootOfAccount));
|
|
50
|
+
if (rootOfAccount !== firstAcctBit.toLowerCase())
|
|
51
|
+
throw onErrorHelper.makeError(origin, new Error('the new account MUST match ' + rootOfAccount));
|
|
52
|
+
return options;
|
|
53
|
+
},
|
|
54
|
+
onCompleted: (options) => {
|
|
55
|
+
return options;
|
|
56
|
+
},
|
|
57
|
+
onError: (err) => onErrorHelper.detectOriginAndReturn(origin, err, (error) => {
|
|
58
|
+
process.stdout.write((0, promptHelpers_1.goColor)('INFO', '\nTry From the account folder or root folder'));
|
|
59
|
+
return error;
|
|
60
|
+
}),
|
|
61
|
+
isStackable: true,
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
exports.forceAccountInName = forceAccountInName;
|
|
65
|
+
/**
|
|
66
|
+
* @description - prompt to choose from currently used auth
|
|
67
|
+
*/
|
|
68
|
+
const chooseExistingCertificate = () => {
|
|
69
|
+
const origin = 'chooseExistingCertificate';
|
|
70
|
+
return {
|
|
71
|
+
_origin: origin,
|
|
72
|
+
isStackable: true,
|
|
73
|
+
beforeExecuting: async (options) => {
|
|
74
|
+
// skip
|
|
75
|
+
if (options?.arguments?.certificateid)
|
|
76
|
+
return options;
|
|
77
|
+
// @ts-expect-error is fine
|
|
78
|
+
if (options?.arguments?.runhooks === 'quiet')
|
|
79
|
+
return options;
|
|
80
|
+
// generate and read the account list
|
|
81
|
+
const accountList = await (0, accountManageauth_1.fetchAccountList)();
|
|
82
|
+
const choices = [...new Set(accountList.map(({ auth }) => {
|
|
83
|
+
const { certificateId, privatekeyPath } = auth;
|
|
84
|
+
return JSON.stringify({
|
|
85
|
+
certificateId,
|
|
86
|
+
privatekeyPath
|
|
87
|
+
});
|
|
88
|
+
}))];
|
|
89
|
+
// present the data
|
|
90
|
+
const displayChoices = choices.map((c, i) => {
|
|
91
|
+
const d = JSON.parse(c);
|
|
92
|
+
return [
|
|
93
|
+
(0, promptHelpers_1.goColor)('INFO', d.certificateId),
|
|
94
|
+
(0, promptHelpers_1.goColor)('SUBTLE', d.privatekeyPath),
|
|
95
|
+
].join(' ');
|
|
96
|
+
});
|
|
97
|
+
// choice of private key pairs
|
|
98
|
+
let answer = await safeCommands_1.promptHelpers.promptChoices({
|
|
99
|
+
choices: choices,
|
|
100
|
+
displayChoices,
|
|
101
|
+
default: null,
|
|
102
|
+
question: `Which existing certificate would you like to use?`
|
|
103
|
+
});
|
|
104
|
+
// options.arguments.
|
|
105
|
+
const { certificateId, privatekeyPath } = JSON.parse(answer);
|
|
106
|
+
options.arguments.certificateid = certificateId;
|
|
107
|
+
options.arguments.privatekeypath = privatekeyPath;
|
|
108
|
+
return options;
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
exports.chooseExistingCertificate = chooseExistingCertificate;
|
|
113
|
+
const promptForAccount = () => {
|
|
114
|
+
const origin = 'promptForAccount';
|
|
115
|
+
return {
|
|
116
|
+
_origin: origin,
|
|
117
|
+
isStackable: true,
|
|
118
|
+
beforeExecuting: async (options) => {
|
|
119
|
+
// @ts-expect-error is fine
|
|
120
|
+
if (options?.arguments?.runhooks === 'quiet')
|
|
121
|
+
return options;
|
|
122
|
+
let answer = '';
|
|
123
|
+
const nag = async () => {
|
|
124
|
+
answer = await safeCommands_1.promptHelpers.promptUser({
|
|
125
|
+
message: 'What is the new account id? (e.g. TD765432 or 24635_RP)'
|
|
126
|
+
});
|
|
127
|
+
};
|
|
128
|
+
while (!(0, validators_1.isValidAccountName)(answer)) {
|
|
129
|
+
await nag();
|
|
130
|
+
}
|
|
131
|
+
options.arguments.account = answer.toUpperCase();
|
|
132
|
+
options.arguments.domain = answer.toLowerCase().replace('_', '-') + '.app.netsuite.com';
|
|
133
|
+
return options;
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
exports.promptForAccount = promptForAccount;
|
|
138
|
+
/**
|
|
139
|
+
* @description - account (not folder)
|
|
140
|
+
*/
|
|
141
|
+
const promptForAuthId = () => {
|
|
142
|
+
const origin = 'promptForAuthId';
|
|
143
|
+
return {
|
|
144
|
+
_origin: origin,
|
|
145
|
+
isStackable: true,
|
|
146
|
+
beforeExecuting: async (options) => {
|
|
147
|
+
// @ts-expect-error fine
|
|
148
|
+
if (options.arguments?.runhooks === 'quiet')
|
|
149
|
+
return options;
|
|
150
|
+
let answer = '';
|
|
151
|
+
const nag = async () => {
|
|
152
|
+
answer = await safeCommands_1.promptHelpers.promptUser({
|
|
153
|
+
message: 'What authId? (e.g. ACME-DEV)'
|
|
154
|
+
});
|
|
155
|
+
};
|
|
156
|
+
while (!(0, validators_1.isValidAuthId)(answer)) {
|
|
157
|
+
await nag();
|
|
158
|
+
}
|
|
159
|
+
options.arguments.authid = answer;
|
|
160
|
+
return options;
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
};
|
|
164
|
+
exports.promptForAuthId = promptForAuthId;
|
|
165
|
+
/**
|
|
166
|
+
* @description - Authid must be unique
|
|
167
|
+
* - Accountid technically does not need to be unique
|
|
168
|
+
*/
|
|
169
|
+
const askToReplace = () => {
|
|
170
|
+
const origin = 'promptForAuthId';
|
|
171
|
+
return {
|
|
172
|
+
_origin: origin,
|
|
173
|
+
isStackable: true,
|
|
174
|
+
beforeExecuting: async (options) => {
|
|
175
|
+
// @ts-expect-error ok
|
|
176
|
+
if (options?.arguments?.runhooks === 'quiet')
|
|
177
|
+
return options;
|
|
178
|
+
process.stdout.write(safeCommands_1.promptHelpers.goColor('INFO', '\nChecking for conflicts...'));
|
|
179
|
+
// check if authid is already in use
|
|
180
|
+
// generate and read the account list
|
|
181
|
+
const removeAccount = async (type, value, forced) => {
|
|
182
|
+
const accountList = await (0, accountManageauth_1.fetchAccountList)();
|
|
183
|
+
const conflict = accountList.find((d) => {
|
|
184
|
+
if (type === 'authid')
|
|
185
|
+
return d.authid === value;
|
|
186
|
+
if (type === 'companyId')
|
|
187
|
+
return d.accountInfo.companyId === value;
|
|
188
|
+
return false;
|
|
189
|
+
});
|
|
190
|
+
if (conflict) {
|
|
191
|
+
process.stdout.write(safeCommands_1.promptHelpers.goColor('SUBTLE', '\nConflict found ', JSON.stringify(conflict, null, 2)));
|
|
192
|
+
const choices = ['Replace'];
|
|
193
|
+
if (!forced)
|
|
194
|
+
choices.push('Continue');
|
|
195
|
+
let answer = await safeCommands_1.promptHelpers.promptChoices({
|
|
196
|
+
choices,
|
|
197
|
+
displayChoices: choices,
|
|
198
|
+
question: `Would you like to replace the existing account? ${conflict.authid}`,
|
|
199
|
+
default: 'Quit',
|
|
200
|
+
});
|
|
201
|
+
if (answer === choices[0]) {
|
|
202
|
+
await spawnSuitecloud.createAsync({
|
|
203
|
+
command: 'account:manageauth',
|
|
204
|
+
args: ['--remove', options.arguments.authid],
|
|
205
|
+
interact: true,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
await removeAccount('authid', options.arguments.authid, true);
|
|
211
|
+
if (options.arguments.account)
|
|
212
|
+
await removeAccount('companyId', options.arguments.account);
|
|
213
|
+
return options;
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
};
|
|
217
|
+
exports.askToReplace = askToReplace;
|
|
218
|
+
//# sourceMappingURL=accountSetup.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file commands/acspass/compiless.ts
|
|
3
|
+
* @author Gerald Gillespie <gerald.gillespie@fullscript.com>
|
|
4
|
+
*/
|
|
5
|
+
import { SdfCommand } from "../../index";
|
|
6
|
+
/**
|
|
7
|
+
* @description
|
|
8
|
+
* ./suitecloud.config.js watch -e ts --ignore module.d.ts
|
|
9
|
+
*/
|
|
10
|
+
export declare const compileSuiteScript: (ignore: string[]) => SdfCommand;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @file commands/acspass/compiless.ts
|
|
4
|
+
* @author Gerald Gillespie <gerald.gillespie@fullscript.com>
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.compileSuiteScript = void 0;
|
|
8
|
+
const onErrorHelper = require("../../lib/onErrorHelper");
|
|
9
|
+
const compileHelper = require("../../lib/compileHelper");
|
|
10
|
+
const assert = require("node:assert");
|
|
11
|
+
const nodePath = require("node:path");
|
|
12
|
+
const safeCommands_1 = require("../../safeCommands");
|
|
13
|
+
const updateModule = require("../../lib/updateModule");
|
|
14
|
+
const TsConfigName = 'tsconfig.json';
|
|
15
|
+
const passthroughCommand = 'custom:hook';
|
|
16
|
+
/**
|
|
17
|
+
* @description
|
|
18
|
+
* ./suitecloud.config.js watch -e ts --ignore module.d.ts
|
|
19
|
+
*/
|
|
20
|
+
const compileSuiteScript = (ignore) => {
|
|
21
|
+
const origin = 'compileSuiteScript';
|
|
22
|
+
return {
|
|
23
|
+
_origin: origin,
|
|
24
|
+
isStackable: true,
|
|
25
|
+
beforeExecuting: async (options) => {
|
|
26
|
+
assert(options.command === passthroughCommand);
|
|
27
|
+
if (options.arguments.option1 !== 'compiless')
|
|
28
|
+
return options;
|
|
29
|
+
await compileHelper.compileTsConfig(options.arguments.option2 || nodePath.join(process.cwd(), TsConfigName));
|
|
30
|
+
await updateModule.updateModuleTypeDef();
|
|
31
|
+
return options;
|
|
32
|
+
},
|
|
33
|
+
onError: async (error) => onErrorHelper.detectOriginAndReturn(origin, error, async (error) => {
|
|
34
|
+
await safeCommands_1.promptHelpers.promptUser({
|
|
35
|
+
message: `
|
|
36
|
+
${passthroughCommand} Usage for "compiless"
|
|
37
|
+
--option1 compiless - begin watching ts
|
|
38
|
+
-option2 <path> - alternate tsconfig file
|
|
39
|
+
`
|
|
40
|
+
});
|
|
41
|
+
return error;
|
|
42
|
+
})
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
exports.compileSuiteScript = compileSuiteScript;
|
|
46
|
+
//# sourceMappingURL=compiless.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file commands/customhook/watchss.ts
|
|
3
|
+
* Using nodemon to
|
|
4
|
+
* - watch TSC for a typical accounts project
|
|
5
|
+
* - spawns a child process
|
|
6
|
+
* @author Gerald Gillespie <gerald.gillespie@fullscript.com>
|
|
7
|
+
*/
|
|
8
|
+
import { SdfCommand } from "../../index";
|
|
9
|
+
/**
|
|
10
|
+
* @description
|
|
11
|
+
* @example sdf custom:hook --option1 watchss --option2 ignore --multi2 module.d.ts foo.d.ts
|
|
12
|
+
* ./suitecloud.config.js watch -e ts --ignore module.d.ts
|
|
13
|
+
*/
|
|
14
|
+
export declare const watchSuiteScript: (sdfFileName: string, ignore: string[]) => SdfCommand;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @file commands/customhook/watchss.ts
|
|
4
|
+
* Using nodemon to
|
|
5
|
+
* - watch TSC for a typical accounts project
|
|
6
|
+
* - spawns a child process
|
|
7
|
+
* @author Gerald Gillespie <gerald.gillespie@fullscript.com>
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.watchSuiteScript = void 0;
|
|
11
|
+
const onErrorHelper = require("../../lib/onErrorHelper");
|
|
12
|
+
const safeCommands_1 = require("../../safeCommands");
|
|
13
|
+
const cp = require("node:child_process");
|
|
14
|
+
const assert = require("node:assert");
|
|
15
|
+
const passthroughCommand = 'custom:hook';
|
|
16
|
+
const sdfExec = process.env['SUITECLOUD_EXE'] || 'sdf';
|
|
17
|
+
const SdfCompileCommand = `${sdfExec} ${passthroughCommand} --option1 compiless`;
|
|
18
|
+
/**
|
|
19
|
+
* @description
|
|
20
|
+
* @example sdf custom:hook --option1 watchss --option2 ignore --multi2 module.d.ts foo.d.ts
|
|
21
|
+
* ./suitecloud.config.js watch -e ts --ignore module.d.ts
|
|
22
|
+
*/
|
|
23
|
+
const watchSuiteScript = (sdfFileName, ignore) => {
|
|
24
|
+
const origin = 'watchSuiteScript';
|
|
25
|
+
return {
|
|
26
|
+
_origin: origin,
|
|
27
|
+
isStackable: true,
|
|
28
|
+
beforeExecuting: async (options) => {
|
|
29
|
+
assert(options.command === passthroughCommand);
|
|
30
|
+
if (options.arguments.option1 !== 'watchss')
|
|
31
|
+
return options;
|
|
32
|
+
//
|
|
33
|
+
const combinedIgnore = [...ignore];
|
|
34
|
+
const doIgnore = Boolean(options.arguments.option2);
|
|
35
|
+
if (doIgnore) {
|
|
36
|
+
// array must accompany the ignore
|
|
37
|
+
assert(Array.isArray(options.arguments.multi1));
|
|
38
|
+
combinedIgnore.push(...[options.arguments.multi1].flat());
|
|
39
|
+
}
|
|
40
|
+
const extraArgs = [];
|
|
41
|
+
if (combinedIgnore.length > 0)
|
|
42
|
+
extraArgs.push('--ignore', ...combinedIgnore);
|
|
43
|
+
process.stdout.write(safeCommands_1.promptHelpers.goColor('INFO', '\nlaunching compile via sdf', ...extraArgs));
|
|
44
|
+
const unAttachedNodemon = cp.spawn('nodemon', [
|
|
45
|
+
`--exec "${SdfCompileCommand}"`,
|
|
46
|
+
'-e',
|
|
47
|
+
'ts',
|
|
48
|
+
].concat(extraArgs).filter(Boolean), {
|
|
49
|
+
cwd: process.cwd(),
|
|
50
|
+
stdio: 'inherit',
|
|
51
|
+
shell: true
|
|
52
|
+
});
|
|
53
|
+
await new Promise((ok, no) => {
|
|
54
|
+
unAttachedNodemon.on('close', (e) => {
|
|
55
|
+
if (!e)
|
|
56
|
+
ok(0);
|
|
57
|
+
});
|
|
58
|
+
unAttachedNodemon.on('error', no);
|
|
59
|
+
});
|
|
60
|
+
return options;
|
|
61
|
+
},
|
|
62
|
+
onError: async (error) => onErrorHelper.detectOriginAndReturn(origin, error, async (error) => {
|
|
63
|
+
console.error({ error });
|
|
64
|
+
await safeCommands_1.promptHelpers.promptUser({
|
|
65
|
+
message: `
|
|
66
|
+
${passthroughCommand} Usage for "watchss"
|
|
67
|
+
--option1 watchss - begin watching ts
|
|
68
|
+
--flag2 - presence means to obey ignore list
|
|
69
|
+
--multi2 <files> - list of what to ignore if accompanied by the flag
|
|
70
|
+
`
|
|
71
|
+
});
|
|
72
|
+
return error;
|
|
73
|
+
})
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
exports.watchSuiteScript = watchSuiteScript;
|
|
77
|
+
//# sourceMappingURL=watchss.js.map
|