mlcl 1.0.0
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/.eslintignore +31 -0
- package/.eslintrc.json +54 -0
- package/LICENSE +200 -0
- package/README.md +101 -0
- package/babel.config.json +10 -0
- package/build/API/authorization.js +107 -0
- package/build/API/client.js +11 -0
- package/build/API/index.js +8 -0
- package/build/API/molecule/index.js +11 -0
- package/build/API/molecule/types.js +6 -0
- package/build/API/resource/device/index.js +12 -0
- package/build/API/resource/device/types.js +6 -0
- package/build/API/resource/device/utilities/confirmSshKey.js +20 -0
- package/build/API/resource/device/utilities/index.js +7 -0
- package/build/API/resource/device/utilities/sendSshKey.js +64 -0
- package/build/API/resource/index.js +10 -0
- package/build/API/resource/molecule/index.js +12 -0
- package/build/API/resource/molecule/types.js +6 -0
- package/build/API/resource/molecule/utilities/getPlan.js +15 -0
- package/build/API/resource/molecule/utilities/index.js +6 -0
- package/build/API/resource/payment/index.js +9 -0
- package/build/API/resource/payment/plans.js +28 -0
- package/build/API/resource/payment/platform.js +7 -0
- package/build/API/resource/payment/platforms/apple/index.js +21 -0
- package/build/API/resource/payment/platforms/apple/plans/appleMonthly.js +17 -0
- package/build/API/resource/payment/platforms/apple/plans/appleYearly.js +18 -0
- package/build/API/resource/payment/platforms/apple/plans/index.js +7 -0
- package/build/API/resource/payment/platforms/google/index.js +21 -0
- package/build/API/resource/payment/platforms/google/plans/googleMonthly.js +17 -0
- package/build/API/resource/payment/platforms/google/plans/googleYearly.js +18 -0
- package/build/API/resource/payment/platforms/google/plans/index.js +7 -0
- package/build/API/resource/payment/platforms/index.js +8 -0
- package/build/API/resource/payment/platforms/stripe/index.js +25 -0
- package/build/API/resource/payment/platforms/stripe/plans/index.js +11 -0
- package/build/API/resource/payment/platforms/stripe/plans/stripeBusinessMolecule.js +21 -0
- package/build/API/resource/payment/platforms/stripe/plans/stripeMonthly.js +18 -0
- package/build/API/resource/payment/platforms/stripe/plans/stripeMonthlyMolecule.js +18 -0
- package/build/API/resource/payment/platforms/stripe/plans/stripeSingleUseMolecule.js +19 -0
- package/build/API/resource/payment/platforms/stripe/plans/stripeUnlimitedUseMolecule.js +19 -0
- package/build/API/resource/payment/platforms/stripe/plans/stripeYearly.js +19 -0
- package/build/API/resource/payment/types.js +6 -0
- package/build/API/resource/types.js +6 -0
- package/build/API/resource/user/index.js +15 -0
- package/build/API/resource/user/types.js +6 -0
- package/build/API/resource/user/utilities/getPlan.js +12 -0
- package/build/API/resource/user/utilities/index.js +7 -0
- package/build/API/resource/user/utilities/logIn.js +60 -0
- package/build/cli.js +15 -0
- package/build/commands/add-ssh-key.js +24 -0
- package/build/commands/buy.js +70 -0
- package/build/commands/clone.js +329 -0
- package/build/commands/index.js +17 -0
- package/build/commands/info.js +33 -0
- package/build/commands/login.js +20 -0
- package/build/commands/logout.js +23 -0
- package/build/commands/molecule/index.js +11 -0
- package/build/commands/molecule/types.js +6 -0
- package/build/commands/remove-ssh-key.js +36 -0
- package/build/commands/select.js +98 -0
- package/build/commands/set-api-key.js +73 -0
- package/build/commands/subscribe.js +74 -0
- package/build/commands/unsubscribe.js +59 -0
- package/build/commands/utilities/asyncExec.js +6 -0
- package/build/commands/utilities/branchExists.js +13 -0
- package/build/commands/utilities/branchExistsSync.js +12 -0
- package/build/commands/utilities/checkoutSelectionBranch.js +49 -0
- package/build/commands/utilities/cherryPick.js +20 -0
- package/build/commands/utilities/cloneRepo.js +9 -0
- package/build/commands/utilities/convertNpmToYarn.js +60 -0
- package/build/commands/utilities/convertTypeDocToJSDoc.js +51 -0
- package/build/commands/utilities/convertTypeScriptToJavaScript.js +451 -0
- package/build/commands/utilities/enableMergeDrivers.js +50 -0
- package/build/commands/utilities/getCurrentBranch.js +11 -0
- package/build/commands/utilities/getCurrentBranchSync.js +7 -0
- package/build/commands/utilities/getRepoRootPath.js +7 -0
- package/build/commands/utilities/getRepoRootPathSync.js +13 -0
- package/build/commands/utilities/index.js +16 -0
- package/build/commands/utilities/npm-to-yarn.js +41 -0
- package/build/commands/utilities/ts-to-js.js +344 -0
- package/build/commands/version.js +14 -0
- package/build/commands/x-merge-json.js +33 -0
- package/build/config.js +5 -0
- package/build/environment.js +80 -0
- package/build/index.js +23 -0
- package/build/logger.js +12 -0
- package/build/pkg.js +5 -0
- package/build/repoConfig copy.js +5 -0
- package/build/repoConfig.js +5 -0
- package/build/types/global.js +6 -0
- package/build/types/index.js +6 -0
- package/build/userConfig.js +5 -0
- package/build/utilities/__tests__/getErrorMessage.js +26 -0
- package/build/utilities/__tests__/timeAgo.js +39 -0
- package/build/utilities/checkVersion.js +29 -0
- package/build/utilities/getErrorMessage.js +15 -0
- package/build/utilities/index.js +13 -0
- package/build/utilities/readConfig.js +19 -0
- package/build/utilities/readRepoConfig copy.js +20 -0
- package/build/utilities/readRepoConfig.js +19 -0
- package/build/utilities/readUserConfig.js +20 -0
- package/build/utilities/synchronizeUserConfig.js +25 -0
- package/build/utilities/timeAgo.js +42 -0
- package/build/utilities/userLoggedIn.js +24 -0
- package/build/utilities/writeConfig.js +8 -0
- package/build/utilities/writeRepoConfig copy.js +9 -0
- package/build/utilities/writeRepoConfig.js +10 -0
- package/build/utilities/writeUserConfig.js +11 -0
- package/jest.config.json +11 -0
- package/package.json +56 -0
- package/src/API/authorization.ts +143 -0
- package/src/API/client.ts +12 -0
- package/src/API/index.ts +10 -0
- package/src/API/resource/device/index.ts +27 -0
- package/src/API/resource/device/types.ts +80 -0
- package/src/API/resource/device/utilities/confirmSshKey.ts +25 -0
- package/src/API/resource/device/utilities/index.ts +8 -0
- package/src/API/resource/device/utilities/sendSshKey.ts +80 -0
- package/src/API/resource/index.ts +12 -0
- package/src/API/resource/molecule/index.ts +30 -0
- package/src/API/resource/molecule/types.ts +332 -0
- package/src/API/resource/molecule/utilities/getPlan.ts +21 -0
- package/src/API/resource/molecule/utilities/index.ts +7 -0
- package/src/API/resource/payment/index.ts +12 -0
- package/src/API/resource/payment/plans.ts +32 -0
- package/src/API/resource/payment/platform.ts +11 -0
- package/src/API/resource/payment/platforms/apple/index.ts +25 -0
- package/src/API/resource/payment/platforms/apple/plans/appleMonthly.ts +19 -0
- package/src/API/resource/payment/platforms/apple/plans/appleYearly.ts +20 -0
- package/src/API/resource/payment/platforms/apple/plans/index.ts +9 -0
- package/src/API/resource/payment/platforms/google/index.ts +25 -0
- package/src/API/resource/payment/platforms/google/plans/googleMonthly.ts +19 -0
- package/src/API/resource/payment/platforms/google/plans/googleYearly.ts +20 -0
- package/src/API/resource/payment/platforms/google/plans/index.ts +9 -0
- package/src/API/resource/payment/platforms/index.ts +10 -0
- package/src/API/resource/payment/platforms/stripe/index.ts +29 -0
- package/src/API/resource/payment/platforms/stripe/plans/index.ts +12 -0
- package/src/API/resource/payment/platforms/stripe/plans/stripeBusinessMolecule.ts +23 -0
- package/src/API/resource/payment/platforms/stripe/plans/stripeMonthly.ts +20 -0
- package/src/API/resource/payment/platforms/stripe/plans/stripeMonthlyMolecule.ts +20 -0
- package/src/API/resource/payment/platforms/stripe/plans/stripeSingleUseMolecule.ts +21 -0
- package/src/API/resource/payment/platforms/stripe/plans/stripeUnlimitedUseMolecule.ts +21 -0
- package/src/API/resource/payment/platforms/stripe/plans/stripeYearly.ts +21 -0
- package/src/API/resource/payment/types.ts +201 -0
- package/src/API/resource/types.ts +169 -0
- package/src/API/resource/user/index.ts +29 -0
- package/src/API/resource/user/types.ts +131 -0
- package/src/API/resource/user/utilities/getPlan.ts +16 -0
- package/src/API/resource/user/utilities/index.ts +8 -0
- package/src/API/resource/user/utilities/logIn.ts +71 -0
- package/src/commands/add-ssh-key.ts +30 -0
- package/src/commands/buy.ts +83 -0
- package/src/commands/clone.ts +363 -0
- package/src/commands/index.ts +19 -0
- package/src/commands/info.ts +40 -0
- package/src/commands/login.ts +24 -0
- package/src/commands/logout.ts +27 -0
- package/src/commands/remove-ssh-key.ts +42 -0
- package/src/commands/subscribe.ts +84 -0
- package/src/commands/unsubscribe.ts +67 -0
- package/src/commands/utilities/asyncExec.ts +7 -0
- package/src/commands/utilities/branchExists.ts +15 -0
- package/src/commands/utilities/checkoutSelectionBranch.ts +62 -0
- package/src/commands/utilities/cherryPick.ts +23 -0
- package/src/commands/utilities/cloneRepo.ts +10 -0
- package/src/commands/utilities/convertNpmToYarn.ts +71 -0
- package/src/commands/utilities/convertTypeDocToJSDoc.ts +55 -0
- package/src/commands/utilities/convertTypeScriptToJavaScript.ts +526 -0
- package/src/commands/utilities/enableMergeDrivers.ts +55 -0
- package/src/commands/utilities/getCurrentBranch.ts +14 -0
- package/src/commands/utilities/getRepoRootPathSync.ts +13 -0
- package/src/commands/utilities/index.ts +17 -0
- package/src/commands/version.ts +22 -0
- package/src/commands/x-merge-json.ts +41 -0
- package/src/environment.ts +88 -0
- package/src/index.ts +30 -0
- package/src/logger.ts +29 -0
- package/src/pkg.ts +11 -0
- package/src/repoConfig.ts +6 -0
- package/src/types/global.ts +26 -0
- package/src/types/index.ts +53 -0
- package/src/types/process.env.d.ts +56 -0
- package/src/userConfig.ts +6 -0
- package/src/utilities/__tests__/getErrorMessage.ts +32 -0
- package/src/utilities/__tests__/timeAgo.ts +46 -0
- package/src/utilities/checkVersion.ts +31 -0
- package/src/utilities/getErrorMessage.ts +30 -0
- package/src/utilities/index.ts +14 -0
- package/src/utilities/readRepoConfig.ts +22 -0
- package/src/utilities/readUserConfig.ts +24 -0
- package/src/utilities/synchronizeUserConfig.ts +26 -0
- package/src/utilities/timeAgo.ts +39 -0
- package/src/utilities/userLoggedIn.ts +28 -0
- package/src/utilities/writeRepoConfig.ts +11 -0
- package/src/utilities/writeUserConfig.ts +13 -0
- package/tsconfig.json +25 -0
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { userConfig } from '../userConfig.js';
|
|
4
|
+
import { userLoggedIn } from '../utilities/userLoggedIn.js';
|
|
5
|
+
import { getPlan } from '../API/resource/molecule/utilities/getPlan.js';
|
|
6
|
+
import { confirmSshKey } from '../API/resource/device/utilities/confirmSshKey.js';
|
|
7
|
+
import * as API from '../API/index.js';
|
|
8
|
+
import { logger } from '../logger.js';
|
|
9
|
+
import { getErrorMessage } from '../utilities/getErrorMessage.js';
|
|
10
|
+
import { cloneRepo } from './utilities/cloneRepo.js';
|
|
11
|
+
import { checkoutSelectionBranch } from './utilities/checkoutSelectionBranch.js';
|
|
12
|
+
import { enableMergeDrivers } from './utilities/enableMergeDrivers.js';
|
|
13
|
+
import { cherryPick } from './utilities/cherryPick.js';
|
|
14
|
+
import { asyncExec } from './utilities/asyncExec.js';
|
|
15
|
+
import { convertTypeDocToJSDoc } from './utilities/convertTypeDocToJSDoc.js';
|
|
16
|
+
import { convertNpmToYarn } from './utilities/convertNpmToYarn.js';
|
|
17
|
+
import { convertTypeScriptToJavaScript } from './utilities/convertTypeScriptToJavaScript.js';
|
|
18
|
+
/**
|
|
19
|
+
* Adds the `clone` command to the program.
|
|
20
|
+
*/
|
|
21
|
+
export const clone = (program) => {
|
|
22
|
+
program.command(`clone`)
|
|
23
|
+
.description(`clones your Molecule into \`project-name-api\` and/or \`project-name-app\``)
|
|
24
|
+
.argument(`<id>`, `your Molecule's ID`)
|
|
25
|
+
.argument(`[projectName]`, `a directory for your Molecule, usually something like \`project-name\``)
|
|
26
|
+
.action(async (id = ``, projectName = ``) => {
|
|
27
|
+
if (!id) {
|
|
28
|
+
logger.warn(`Molecule ID is required.`);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const user = await userLoggedIn();
|
|
32
|
+
if (!user) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
logger.info(`Fetching your Molecule's clone information...`);
|
|
37
|
+
const { props, apiCommits, apiRepoUrl, appCommits, appRepoUrl, } = (await API.resource.molecule.readClone(id)).data;
|
|
38
|
+
const { name, apiSelectionHash, appSelectionHash, } = props;
|
|
39
|
+
if (((!apiSelectionHash || !apiRepoUrl)) && (!appSelectionHash || !appRepoUrl)) {
|
|
40
|
+
logger.warn(`Failed to fetch the necessary information to clone your Molecule. Please contact developer-support@molecule.dev so we can fix this.`);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const moleculePlan = getPlan(props);
|
|
44
|
+
if (moleculePlan?.capabilities.forMolecules && moleculePlan?.capabilities.premium) {
|
|
45
|
+
const deviceId = userConfig.userIdsToDeviceIds?.[user.id] || ``;
|
|
46
|
+
if (!deviceId) {
|
|
47
|
+
logger.warn(`No device ID for the current user. Try logging out and in again.`);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const confirmedSshKey = await confirmSshKey(deviceId, user.username);
|
|
51
|
+
if (!confirmedSshKey) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
projectName = projectName || name?.replace(/ /gi, `-`).replace(/[^A-z0-9-]/gi, ``).toLowerCase() || `your`;
|
|
56
|
+
const apiRepoPath = `${projectName}-api`;
|
|
57
|
+
const appRepoPath = `${projectName}-app`;
|
|
58
|
+
let apiError = false;
|
|
59
|
+
let appError = false;
|
|
60
|
+
if (apiSelectionHash && apiRepoUrl) {
|
|
61
|
+
let resetMergeDrivers = null;
|
|
62
|
+
const writeNewRepoConfig = async () => {
|
|
63
|
+
const repoConfigPath = path.join(apiRepoPath, `.mlclrc.json`);
|
|
64
|
+
logger.info(`Creating ${apiRepoPath}/.mlclrc.json...`);
|
|
65
|
+
try {
|
|
66
|
+
await fs.promises.access(repoConfigPath, fs.constants.R_OK | fs.constants.W_OK);
|
|
67
|
+
logger.info(`${apiRepoPath}/.mlclrc.json already exists on your machine!`);
|
|
68
|
+
apiError = true;
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
await fs.promises.writeFile(repoConfigPath, JSON.stringify({ id }, null, 2));
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
try {
|
|
75
|
+
await fs.promises.access(apiRepoPath, fs.constants.R_OK | fs.constants.W_OK);
|
|
76
|
+
logger.warn(`Error cloning API: ${apiRepoPath} already exists on your machine!`);
|
|
77
|
+
apiError = true;
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
try {
|
|
81
|
+
await cloneRepo(apiRepoUrl, apiRepoPath);
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
logger.warn(`Error cloning API: ${getErrorMessage(error) || `Unknown error`}`);
|
|
85
|
+
apiError = true;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
const createdEmptyBranch = await checkoutSelectionBranch(apiSelectionHash, apiRepoPath, `remotes/origin`);
|
|
90
|
+
if (!createdEmptyBranch) {
|
|
91
|
+
await writeNewRepoConfig();
|
|
92
|
+
logger.info(`API is ready.`);
|
|
93
|
+
}
|
|
94
|
+
else if (apiCommits?.length) {
|
|
95
|
+
const convert = {
|
|
96
|
+
typeScriptToJavaScript: props.selection.apiLanguage === `JavaScript`,
|
|
97
|
+
typeDocToJSDoc: props.selection.apiDocs === `JSDoc`,
|
|
98
|
+
npmToYarn: props.selection.apiPackageManager === `Yarn`,
|
|
99
|
+
};
|
|
100
|
+
logger.info(`You are the first to assemble this particular Molecule API!`);
|
|
101
|
+
resetMergeDrivers = enableMergeDrivers(apiRepoPath);
|
|
102
|
+
logger.info(`Cherry picking the relevant commits...`);
|
|
103
|
+
while (apiCommits.length) {
|
|
104
|
+
const commit = apiCommits.shift();
|
|
105
|
+
if (commit?.hash) {
|
|
106
|
+
logger.info(`Cherry picking ${commit.hash.substring(0, 7)} (${commit.subject || `Unknown commit??? This should never happen!!!`})`);
|
|
107
|
+
await cherryPick(commit.hash, apiRepoPath, `-x`);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
logger.info(`No commit to cherry pick??? This should never happen!!!`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
resetMergeDrivers();
|
|
114
|
+
if (convert.typeDocToJSDoc || convert.npmToYarn || convert.typeScriptToJavaScript) {
|
|
115
|
+
// Delete package-lock.json for any of these.
|
|
116
|
+
try {
|
|
117
|
+
const packageLockPath = path.join(apiRepoPath, `package-lock.json`);
|
|
118
|
+
await fs.promises.unlink(packageLockPath);
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (convert.typeDocToJSDoc) {
|
|
124
|
+
try {
|
|
125
|
+
logger.info(`Converting TypeDoc to JSDoc...`);
|
|
126
|
+
await convertTypeDocToJSDoc(apiRepoPath);
|
|
127
|
+
await asyncExec(`git -C "${apiRepoPath}" add --all`);
|
|
128
|
+
await asyncExec(`git -C "${apiRepoPath}" commit -m "convert typedoc to jsdoc"`);
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
logger.warn(`Error: ${getErrorMessage(error)}`);
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (convert.npmToYarn) {
|
|
136
|
+
try {
|
|
137
|
+
logger.info(`Converting NPM to Yarn...`);
|
|
138
|
+
await convertNpmToYarn(apiRepoPath);
|
|
139
|
+
await asyncExec(`git -C "${apiRepoPath}" add --all`);
|
|
140
|
+
await asyncExec(`git -C "${apiRepoPath}" commit -m "convert npm to yarn"`);
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
logger.warn(`Error: ${getErrorMessage(error)}`);
|
|
144
|
+
throw error;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (convert.typeScriptToJavaScript) {
|
|
148
|
+
try {
|
|
149
|
+
logger.info(`Converting TypeScript to JavaScript...`);
|
|
150
|
+
await convertTypeScriptToJavaScript(apiRepoPath);
|
|
151
|
+
await asyncExec(`git -C "${apiRepoPath}" add --all`);
|
|
152
|
+
await asyncExec(`git -C "${apiRepoPath}" commit -m "convert typescript to javascript"`);
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
logger.warn(`Error: ${getErrorMessage(error)}`);
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
await writeNewRepoConfig();
|
|
160
|
+
logger.info(`API is ready.`);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
logger.warn(`Created an empty branch but no commits to cherry pick.`);
|
|
164
|
+
apiError = true;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
if (resetMergeDrivers) {
|
|
169
|
+
resetMergeDrivers();
|
|
170
|
+
}
|
|
171
|
+
logger.warn(`Error assembling API: ${getErrorMessage(error) || `Unknown error`}`);
|
|
172
|
+
apiError = true;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (appSelectionHash && appRepoUrl) {
|
|
176
|
+
let resetMergeDrivers = null;
|
|
177
|
+
const writeNewRepoConfig = async () => {
|
|
178
|
+
const repoConfigPath = path.join(appRepoPath, `.mlclrc.json`);
|
|
179
|
+
logger.info(`Creating ${appRepoPath}/.mlclrc.json...`);
|
|
180
|
+
try {
|
|
181
|
+
await fs.promises.access(repoConfigPath, fs.constants.R_OK | fs.constants.W_OK);
|
|
182
|
+
logger.info(`${appRepoPath}/.mlclrc.json already exists on your machine!`);
|
|
183
|
+
appError = true;
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
await fs.promises.writeFile(repoConfigPath, JSON.stringify({ id }, null, 2));
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
try {
|
|
190
|
+
await fs.promises.access(appRepoPath, fs.constants.R_OK | fs.constants.W_OK);
|
|
191
|
+
logger.warn(`Error cloning app: ${appRepoPath} already exists on your machine!`);
|
|
192
|
+
appError = true;
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
try {
|
|
196
|
+
await cloneRepo(appRepoUrl, appRepoPath);
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
logger.warn(`Error cloning app: ${getErrorMessage(error) || `Unknown error`}`);
|
|
200
|
+
appError = true;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
try {
|
|
204
|
+
const createdEmptyBranch = await checkoutSelectionBranch(appSelectionHash, appRepoPath, `remotes/origin`);
|
|
205
|
+
if (!createdEmptyBranch) {
|
|
206
|
+
await writeNewRepoConfig();
|
|
207
|
+
logger.info(`App is ready.`);
|
|
208
|
+
}
|
|
209
|
+
else if (appCommits?.length) {
|
|
210
|
+
const convert = {
|
|
211
|
+
typeScriptToJavaScript: props.selection.appLanguage === `JavaScript`,
|
|
212
|
+
typeDocToJSDoc: props.selection.appDocs === `JSDoc`,
|
|
213
|
+
npmToYarn: props.selection.appPackageManager === `Yarn`,
|
|
214
|
+
};
|
|
215
|
+
logger.info(`You are the first to assemble this particular Molecule app!`);
|
|
216
|
+
resetMergeDrivers = enableMergeDrivers(appRepoPath);
|
|
217
|
+
logger.info(`Cherry picking the relevant commits...`);
|
|
218
|
+
while (appCommits.length) {
|
|
219
|
+
const commit = appCommits.shift();
|
|
220
|
+
if (commit?.hash) {
|
|
221
|
+
logger.info(`Cherry picking ${commit.hash.substring(0, 7)} (${commit.subject || `Unknown commit??? This should never happen!!!`})`);
|
|
222
|
+
await cherryPick(commit.hash, appRepoPath, `-x`);
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
logger.info(`No commit to cherry pick??? This should never happen!!!`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
resetMergeDrivers();
|
|
229
|
+
if (convert.typeDocToJSDoc || convert.npmToYarn || convert.typeScriptToJavaScript) {
|
|
230
|
+
// Delete package-lock.json for any of these.
|
|
231
|
+
try {
|
|
232
|
+
const packageLockPath = path.join(appRepoPath, `package-lock.json`);
|
|
233
|
+
await fs.promises.unlink(packageLockPath);
|
|
234
|
+
}
|
|
235
|
+
catch (error) {
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
if (convert.typeDocToJSDoc) {
|
|
239
|
+
try {
|
|
240
|
+
logger.info(`Converting TypeDoc to JSDoc...`);
|
|
241
|
+
await convertTypeDocToJSDoc(appRepoPath);
|
|
242
|
+
await asyncExec(`git -C "${appRepoPath}" add --all`);
|
|
243
|
+
await asyncExec(`git -C "${appRepoPath}" commit -m "convert typedoc to jsdoc"`);
|
|
244
|
+
}
|
|
245
|
+
catch (error) {
|
|
246
|
+
logger.warn(`Error: ${getErrorMessage(error)}`);
|
|
247
|
+
throw error;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
if (convert.npmToYarn) {
|
|
251
|
+
try {
|
|
252
|
+
logger.info(`Converting NPM to Yarn...`);
|
|
253
|
+
await convertNpmToYarn(appRepoPath);
|
|
254
|
+
await asyncExec(`git -C "${appRepoPath}" add --all`);
|
|
255
|
+
await asyncExec(`git -C "${appRepoPath}" commit -m "convert npm to yarn"`);
|
|
256
|
+
}
|
|
257
|
+
catch (error) {
|
|
258
|
+
logger.warn(`Error: ${getErrorMessage(error)}`);
|
|
259
|
+
throw error;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
if (convert.typeScriptToJavaScript) {
|
|
263
|
+
try {
|
|
264
|
+
logger.info(`Converting TypeScript to JavaScript...`);
|
|
265
|
+
await convertTypeScriptToJavaScript(appRepoPath);
|
|
266
|
+
await asyncExec(`git -C "${appRepoPath}" add --all`);
|
|
267
|
+
await asyncExec(`git -C "${appRepoPath}" commit -m "convert typescript to javascript"`);
|
|
268
|
+
}
|
|
269
|
+
catch (error) {
|
|
270
|
+
logger.warn(`Error: ${getErrorMessage(error)}`);
|
|
271
|
+
throw error;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
await writeNewRepoConfig();
|
|
275
|
+
logger.info(`App is ready.`);
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
logger.warn(`Created an empty branch but no commits to cherry pick.`);
|
|
279
|
+
appError = true;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
catch (error) {
|
|
283
|
+
if (resetMergeDrivers) {
|
|
284
|
+
resetMergeDrivers();
|
|
285
|
+
}
|
|
286
|
+
logger.warn(`Error assembling app: ${getErrorMessage(error) || `Unknown error`}`);
|
|
287
|
+
appError = true;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
if (apiSelectionHash && appSelectionHash) {
|
|
291
|
+
if (apiError || appError) {
|
|
292
|
+
logger.info(`There may have been an error cloning your Molecule.`);
|
|
293
|
+
logger.info(`If everything seems good, see \`${apiRepoPath}/README.md\` and \`${appRepoPath}/README.md\` to get started.`);
|
|
294
|
+
logger.info(`If not, please contact developer-support@molecule.dev so we can fix this.`);
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
logger.info(`Your Molecule was successfully cloned!`);
|
|
298
|
+
logger.info(`See \`${apiRepoPath}/README.md\` and \`${appRepoPath}/README.md\` to get started.`);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
else if (apiSelectionHash) {
|
|
302
|
+
if (apiError) {
|
|
303
|
+
logger.info(`There may have been an error cloning your Molecule API.`);
|
|
304
|
+
logger.info(`If everything seems good, see \`${apiRepoPath}/README.md\` to get started.`);
|
|
305
|
+
logger.info(`If not, please contact developer-support@molecule.dev so we can fix this.`);
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
logger.info(`Your Molecule API was successfully cloned!`);
|
|
309
|
+
logger.info(`See \`${apiRepoPath}/README.md\` to get started.`);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
else if (appSelectionHash) {
|
|
313
|
+
if (appError) {
|
|
314
|
+
logger.info(`There may have been an error cloning your Molecule app.`);
|
|
315
|
+
logger.info(`If everything seems good, see \`${appRepoPath}/README.md\` to get started.`);
|
|
316
|
+
logger.info(`If not, please contact developer-support@molecule.dev so we can fix this.`);
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
logger.info(`Your Molecule app was successfully cloned!`);
|
|
320
|
+
logger.info(`See \`${appRepoPath}/README.md\` to get started.`);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
catch (error) {
|
|
325
|
+
logger.warn(`Error cloning Molecule: ${getErrorMessage(error) || `Unknown error`}`);
|
|
326
|
+
logger.warn(`Please contact developer-support@molecule.dev so we can fix this.`);
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every available command and utilities.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
export * as utilities from './utilities/index.js';
|
|
7
|
+
export * from './add-ssh-key.js';
|
|
8
|
+
export * from './buy.js';
|
|
9
|
+
export * from './clone.js';
|
|
10
|
+
export * from './info.js';
|
|
11
|
+
export * from './login.js';
|
|
12
|
+
export * from './logout.js';
|
|
13
|
+
export * from './remove-ssh-key.js';
|
|
14
|
+
export * from './subscribe.js';
|
|
15
|
+
export * from './unsubscribe.js';
|
|
16
|
+
export * from './version.js';
|
|
17
|
+
export * from './x-merge-json.js';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import open from 'open';
|
|
2
|
+
import { userLoggedIn } from '../utilities/userLoggedIn.js';
|
|
3
|
+
import { repoConfig } from '../repoConfig.js';
|
|
4
|
+
import { logger } from '../logger.js';
|
|
5
|
+
import { getErrorMessage } from '../utilities/getErrorMessage.js';
|
|
6
|
+
/**
|
|
7
|
+
* Adds the `info` command to the program.
|
|
8
|
+
*/
|
|
9
|
+
export const info = (program) => {
|
|
10
|
+
program.command(`info`)
|
|
11
|
+
.description(`opens your Molecule's information on Molecule.dev`)
|
|
12
|
+
.action(async () => {
|
|
13
|
+
const user = await userLoggedIn();
|
|
14
|
+
if (!user) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (!repoConfig?.id) {
|
|
18
|
+
logger.warn(`Not within a Molecule repository or \`.mlclrc.json\` not found.`);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const url = `${process.env.WEB_ORIGIN}/#/${encodeURIComponent(repoConfig.id)}`;
|
|
22
|
+
const childProcess = await open(url);
|
|
23
|
+
childProcess.on(`error`, error => {
|
|
24
|
+
logger.warn(`Error opening the URL: ${getErrorMessage(error)}`);
|
|
25
|
+
logger.warn(`If your browser didn't open on its own, visit the following URL: ${url}`);
|
|
26
|
+
});
|
|
27
|
+
childProcess.on(`close`, code => {
|
|
28
|
+
if (code !== 0) {
|
|
29
|
+
logger.warn(`If your browser didn't open on its own, visit the following URL: ${url}`);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { userConfig } from '../userConfig.js';
|
|
2
|
+
import { synchronizeUserConfig } from '../utilities/synchronizeUserConfig.js';
|
|
3
|
+
import * as API from '../API/index.js';
|
|
4
|
+
import { logger } from '../logger.js';
|
|
5
|
+
/**
|
|
6
|
+
* Adds the `login` command to the program.
|
|
7
|
+
*/
|
|
8
|
+
export const login = (program) => {
|
|
9
|
+
program.command(`login`)
|
|
10
|
+
.description(`log into mlcl with your Molecule.dev account via the browser`)
|
|
11
|
+
.action(async () => {
|
|
12
|
+
await synchronizeUserConfig();
|
|
13
|
+
if (userConfig.user) {
|
|
14
|
+
logger.info(`Logged in as ${userConfig.user.username}.`);
|
|
15
|
+
logger.info(`If you would like to log in as another user, run \`mlcl logout\` first.`);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
await API.resource.user.utilities.logIn();
|
|
19
|
+
});
|
|
20
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { userConfig } from '../userConfig.js';
|
|
2
|
+
import { synchronizeUserConfig } from '../utilities/synchronizeUserConfig.js';
|
|
3
|
+
import { writeUserConfig } from '../utilities/writeUserConfig.js';
|
|
4
|
+
import * as API from '../API/index.js';
|
|
5
|
+
import { logger } from '../logger.js';
|
|
6
|
+
/**
|
|
7
|
+
* Adds the `logout` command to the program.
|
|
8
|
+
*/
|
|
9
|
+
export const logout = (program) => {
|
|
10
|
+
program.command(`logout`)
|
|
11
|
+
.description(`logs out of your Molecule.dev account`)
|
|
12
|
+
.action(async () => {
|
|
13
|
+
await synchronizeUserConfig();
|
|
14
|
+
if (!userConfig?.user?.id) {
|
|
15
|
+
logger.warn(`Not logged in.`);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
API.resource.user.logOut();
|
|
19
|
+
delete userConfig.user;
|
|
20
|
+
writeUserConfig();
|
|
21
|
+
logger.info(`Logged out.`);
|
|
22
|
+
});
|
|
23
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `molecule` API resource.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { client } from '../../client';
|
|
7
|
+
export * as types from './types';
|
|
8
|
+
export const read = (id) => (client.get(`molecules/${id}`));
|
|
9
|
+
export const create = (props) => (client.post(`molecules`, props));
|
|
10
|
+
export const update = (id, props) => (client.patch(`molecules/${id}`, props));
|
|
11
|
+
export const updatePlan = (id, { planKey, receipt, quantity }) => (client.patch(`molecules/${id}/plan`, { planKey, receipt, quantity }));
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { userConfig } from '../userConfig.js';
|
|
2
|
+
import { userLoggedIn } from '../utilities/userLoggedIn.js';
|
|
3
|
+
import * as API from '../API/index.js';
|
|
4
|
+
import { logger } from '../logger.js';
|
|
5
|
+
import { getErrorMessage } from '../utilities/getErrorMessage.js';
|
|
6
|
+
/**
|
|
7
|
+
* Adds the `remove-ssh-key` command to the program.
|
|
8
|
+
*/
|
|
9
|
+
export const removeSshKey = (program) => {
|
|
10
|
+
program.command(`remove-ssh-key`)
|
|
11
|
+
.description(`removes your current CLI device's SSH key from your Molecule.dev account`)
|
|
12
|
+
.action(async () => {
|
|
13
|
+
const user = await userLoggedIn();
|
|
14
|
+
if (!user) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const deviceId = userConfig.userIdsToDeviceIds?.[user.id] || ``;
|
|
18
|
+
if (!deviceId) {
|
|
19
|
+
logger.warn(`No device ID for the current user. Try logging out and in again.`);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
logger.info(`Removing public SSH key from the API...`);
|
|
23
|
+
try {
|
|
24
|
+
const { props } = (await API.resource.device.update(deviceId, { sshKey: `` })).data;
|
|
25
|
+
if (props.sshKey === ``) {
|
|
26
|
+
logger.info(`SSH key successfully removed!`);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
logger.info(`Failed to remove SSH key.`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
logger.warn(`Failed to remove SSH key. ${getErrorMessage(error)}`);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import * as utilities from './utilities/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Adds the `select` command to the program.
|
|
4
|
+
*/
|
|
5
|
+
export const select = (program) => {
|
|
6
|
+
program.command(`select`)
|
|
7
|
+
.description(`manage the current selection`)
|
|
8
|
+
.argument(`[hash]`, `select by known hash/branch`)
|
|
9
|
+
.option(`--path <path>`, `the path to your Molecule configuration file`, `.mlclrc.json`)
|
|
10
|
+
.option(`--show`, `show the current selection`)
|
|
11
|
+
.option(`--appLanguage [appLanguage]`, `select app language`)
|
|
12
|
+
.option(`--appPackageManager [appPackageManager]`, `select app package manager`)
|
|
13
|
+
.option(`--appRenderer [appRenderer]`, `select app renderer`)
|
|
14
|
+
.option(`--appDocs [appDocs]`, `select app documentation library`)
|
|
15
|
+
.option(`--appTesting [appTesting]`, `select app testing library`)
|
|
16
|
+
.option(`--appLogging [appLogging]`, `select app logging library`)
|
|
17
|
+
.option(`--appPlatformSupport [appPlatformSupport]`, `select app platform support`)
|
|
18
|
+
.option(`--no-appPlatformSupport`, `disable app platform support`)
|
|
19
|
+
.option(`--appPlatforms [appPlatforms...]`, `select app platform(s)`)
|
|
20
|
+
.option(`--appUi [appUi]`, `select app UI library`)
|
|
21
|
+
.option(`--appThemes [appThemes...]`, `select app theme(s)`)
|
|
22
|
+
.option(`--userAuthentication [userAuthentication...]`, `select user authentication method(s)`)
|
|
23
|
+
.option(`--no-userAuthentication`, `disable user authentication`)
|
|
24
|
+
.option(`--oauthServers [oauthServers...]`, `select OAuth server(s)`)
|
|
25
|
+
.option(`--no-oauthServers [oauthServers...]`, `disable OAuth servers`)
|
|
26
|
+
.option(`--pushNotifications [pushNotifications]`, `enable/disable push notifications`)
|
|
27
|
+
.option(`--no-pushNotifications`, `disable push notifications`)
|
|
28
|
+
.option(`--paymentPlatforms [paymentPlatforms...]`, `select payment platform(s)`)
|
|
29
|
+
.option(`--no-paymentPlatforms`, `disable payment platforms`)
|
|
30
|
+
.option(`--appDeployment [appDeployment]`, `select app deployment method`)
|
|
31
|
+
.option(`--no-appDeployment`, `disable app deployment`)
|
|
32
|
+
.option(`--apiLanguage [apiLanguage]`, `select API language`)
|
|
33
|
+
.option(`--apiPackageManager [apiPackageManager]`, `select API package manager`)
|
|
34
|
+
.option(`--apiDocs [apiDocs]`, `select API documentation library`)
|
|
35
|
+
.option(`--apiTesting [apiTesting]`, `select API testing library`)
|
|
36
|
+
.option(`--apiLogging [apiLogging]`, `select API logging library`)
|
|
37
|
+
.option(`--apiDatabase [apiDatabase]`, `select API database`)
|
|
38
|
+
.option(`--apiEmails [apiEmails]`, `select API email method`)
|
|
39
|
+
.option(`--no-apiEmails`, `disable API emails`)
|
|
40
|
+
.option(`--apiUploads [apiUploads]`, `select API upload handler`)
|
|
41
|
+
.option(`--no-apiUploads`, `disable API uploads`)
|
|
42
|
+
.option(`--apiDeployment [apiDeployment]`, `select API deployment method`)
|
|
43
|
+
.option(`--no-apiDeployment`, `disable API deployment`)
|
|
44
|
+
.action(async (hash, options) => {
|
|
45
|
+
const path = options.path;
|
|
46
|
+
const config = utilities.readConfig(path);
|
|
47
|
+
if (!config) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
let selection = config.selection;
|
|
51
|
+
if (hash) {
|
|
52
|
+
selection = config.selectionHashMap?.[hash.replace(/^mlcl-/, ``)];
|
|
53
|
+
if (!selection) {
|
|
54
|
+
console.warn(`Unknown hash.`);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const showSelection = () => {
|
|
59
|
+
if (selection) {
|
|
60
|
+
console.info(`Current selection:`, selection);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
console.info(`No selection found in config.`);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
if (options.show) {
|
|
67
|
+
showSelection();
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (!selection) {
|
|
71
|
+
selection = {};
|
|
72
|
+
}
|
|
73
|
+
const selectionKeys = utilities.constants[`${config.type}SelectionKeys`];
|
|
74
|
+
for (const name of selectionKeys) {
|
|
75
|
+
if (options[name] === false) {
|
|
76
|
+
delete selection[name];
|
|
77
|
+
}
|
|
78
|
+
else if (typeof options[name] !== `undefined`) {
|
|
79
|
+
selection[name] = options[name];
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
for (const name in selection) {
|
|
83
|
+
if (!selectionKeys.some(selectionKey => selectionKey === name)) {
|
|
84
|
+
delete selection[name];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
config.selection = selection;
|
|
89
|
+
await utilities.checkoutSelectionBranch(config);
|
|
90
|
+
utilities.writeConfig(config, path);
|
|
91
|
+
console.info(`Updated config.`);
|
|
92
|
+
showSelection();
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
console.warn(`Unable to checkout the selection's branch.`, error?.message);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { userConfig } from '../userConfig.js';
|
|
4
|
+
import { writeUserConfig } from '../utilities/writeUserConfig.js';
|
|
5
|
+
import { repoConfig } from '../repoConfig.js';
|
|
6
|
+
import { writeRepoConfig } from '../utilities/writeRepoConfig.js';
|
|
7
|
+
import { getRepoRootPath } from './utilities/getRepoRootPath.js';
|
|
8
|
+
import { getErrorMessage } from '../utilities/getErrorMessage.js';
|
|
9
|
+
import * as API from '../API/index.js';
|
|
10
|
+
import { logger } from '../logger.js';
|
|
11
|
+
/**
|
|
12
|
+
* Adds the `set-api-key` command to the program.
|
|
13
|
+
*/
|
|
14
|
+
export const setApiKey = (program) => {
|
|
15
|
+
program.command(`set-api-key`)
|
|
16
|
+
.description(`updates the current repository's .env file with your MOLECULE_USER_ID and MOLECULE_USER_API_KEY`)
|
|
17
|
+
.option(`--new`, `forces a new API key`)
|
|
18
|
+
.action(async (options) => {
|
|
19
|
+
if (!userConfig?.user?.id) {
|
|
20
|
+
logger.warn(`Not logged in. Run \`mlcl login\` first.`);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
const { apiKey } = options.new
|
|
25
|
+
? (await API.resource.user.createApiKey(userConfig.user.id)).data
|
|
26
|
+
: (await API.resource.user.readApiKey(userConfig.user.id)).data;
|
|
27
|
+
if (!apiKey) {
|
|
28
|
+
throw new Error(`No API key.`);
|
|
29
|
+
}
|
|
30
|
+
const envPath = path.join(getRepoRootPath(), `.env`);
|
|
31
|
+
let envFileContents = ``;
|
|
32
|
+
if (fs.existsSync(envPath)) {
|
|
33
|
+
envFileContents = fs.readFileSync(envPath, `utf8`);
|
|
34
|
+
if (/^MOLECULE_USER_API_KEY=(.*)$/gm.test(envFileContents)) {
|
|
35
|
+
envFileContents = envFileContents.replace(/^MOLECULE_USER_API_KEY=(.*)$/, `MOLECULE_USER_API_KEY=${apiKey}`);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
envFileContents = `MOLECULE_USER_API_KEY=${apiKey}\n${envFileContents}`;
|
|
39
|
+
}
|
|
40
|
+
if (/^MOLECULE_USER_ID=(.*)$/gm.test(envFileContents)) {
|
|
41
|
+
envFileContents = envFileContents.replace(/^MOLECULE_USER_ID=(.*)$/, `MOLECULE_USER_ID=${userConfig.user.id}`);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
envFileContents = `MOLECULE_USER_ID=${userConfig.user.id}\n${envFileContents}`;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
envFileContents = `MOLECULE_USER_ID=${userConfig.user.id}\n`
|
|
49
|
+
+ `MOLECULE_USER_API_KEY=${apiKey}\n`;
|
|
50
|
+
}
|
|
51
|
+
fs.writeFileSync(envPath, envFileContents);
|
|
52
|
+
if (!userConfig.userSecrets) {
|
|
53
|
+
userConfig.userSecrets = {};
|
|
54
|
+
}
|
|
55
|
+
userConfig.userSecrets.apiKey = apiKey;
|
|
56
|
+
writeUserConfig();
|
|
57
|
+
logger.info(`Updated user .mlclrc.json file.`);
|
|
58
|
+
if (!repoConfig.userSecrets) {
|
|
59
|
+
repoConfig.userSecrets = {};
|
|
60
|
+
}
|
|
61
|
+
repoConfig.userSecrets.apiKey = apiKey;
|
|
62
|
+
repoConfig.user = userConfig.user;
|
|
63
|
+
writeRepoConfig();
|
|
64
|
+
logger.info(`Updated repo .mlclrc.json file.`);
|
|
65
|
+
logger.info(`Updated .env file with the following:`);
|
|
66
|
+
logger.info(`MOLECULE_USER_ID=${userConfig.user.id}`);
|
|
67
|
+
logger.info(`MOLECULE_USER_API_KEY=${apiKey}`);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
logger.warn(`Failed to set API key. ${getErrorMessage(error)}`);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
};
|