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,344 @@
|
|
|
1
|
+
/* eslint-disable react-hooks/rules-of-hooks */
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import ts from 'typescript';
|
|
6
|
+
import prettier from 'prettier';
|
|
7
|
+
import process from 'process';
|
|
8
|
+
const __dirname = fileURLToPath(path.dirname(import.meta.url));
|
|
9
|
+
/**
|
|
10
|
+
* Returns the name of some node.
|
|
11
|
+
*/
|
|
12
|
+
const getName = (source, node) => {
|
|
13
|
+
let name = (node.name && node.name.escapedText)
|
|
14
|
+
|| (node.parameters && source.substring(node.parameters.pos, node.parameters.end));
|
|
15
|
+
// Change type [key: string] to {...} so it will be parsed by JSDoc.
|
|
16
|
+
if (name === 'key: string') {
|
|
17
|
+
return '{...}';
|
|
18
|
+
}
|
|
19
|
+
return name;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Returns the name of some type.
|
|
23
|
+
*/
|
|
24
|
+
const getTypeName = (source, type) => {
|
|
25
|
+
let typeName = ``;
|
|
26
|
+
if (!type) {
|
|
27
|
+
return `any`;
|
|
28
|
+
}
|
|
29
|
+
if (type.typeName && type.typeName.escapedText) {
|
|
30
|
+
typeName = type.typeName.escapedText;
|
|
31
|
+
if (type.typeArguments && type.typeArguments.length) {
|
|
32
|
+
const args = type.typeArguments.map(subType => getTypeName(source, subType)).join(', ');
|
|
33
|
+
typeName = `${typeName}<${args}>`;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else if (ts.isFunctionTypeNode(type) || ts.isFunctionLike(type)) {
|
|
37
|
+
typeName = 'function';
|
|
38
|
+
}
|
|
39
|
+
else if (ts.isArrayTypeNode(type)) {
|
|
40
|
+
typeName = 'Array';
|
|
41
|
+
}
|
|
42
|
+
else if (type.types) {
|
|
43
|
+
typeName = type.types.map(subType => getTypeName(source, subType)).join(' | ');
|
|
44
|
+
}
|
|
45
|
+
else if (type.members && type.members.length) {
|
|
46
|
+
typeName = 'object';
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
typeName = source.substring(type.pos, type.end).trim();
|
|
50
|
+
}
|
|
51
|
+
typeName = typeName.replace(/`/g, `'`);
|
|
52
|
+
typeName = typeName.replace(`['`, `#`).replace(`']`, ``);
|
|
53
|
+
typeName = typeName.replace(/keyof .+/g, `string`);
|
|
54
|
+
return typeName;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Returns the JSDoc `@param` tag for some parameter.
|
|
58
|
+
*/
|
|
59
|
+
const getJSDocParamTag = (source, parameter) => {
|
|
60
|
+
let parameterName = getName(source, parameter);
|
|
61
|
+
const parameterComment = (parameter.jsDoc && parameter.jsDoc[0] && parameter.jsDoc[0].comment) || '';
|
|
62
|
+
if (parameter.questionToken) {
|
|
63
|
+
parameterName = ['[', parameterName, ']'].join('');
|
|
64
|
+
}
|
|
65
|
+
return `@param {${getTypeName(source, parameter.type)}} ${parameterName}${parameterComment ? ` ${parameterComment}` : ``}`;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Returns JSDoc `@property` tags for some type.
|
|
69
|
+
*/
|
|
70
|
+
const getJSDocPropertyTags = (source, type, tags = [], parentName = '') => {
|
|
71
|
+
// Type could be an array of types like: `{sth: 1} | string` so parse each type separately.
|
|
72
|
+
const typesToCheck = [type];
|
|
73
|
+
if (type.types && type.types.length) {
|
|
74
|
+
typesToCheck.push(...type.types);
|
|
75
|
+
}
|
|
76
|
+
typesToCheck.forEach(type => {
|
|
77
|
+
// Handling array defined like this: {element1: 'something'}[]
|
|
78
|
+
if (ts.isArrayTypeNode(type) && type.elementType) {
|
|
79
|
+
getJSDocPropertyTags(source, type.elementType, tags, parentName ? parentName + '[]' : '[]');
|
|
80
|
+
}
|
|
81
|
+
// Handling Array<{element1: 'somethin'}>
|
|
82
|
+
if (type.typeName && type.typeName.escapedText === 'Array') {
|
|
83
|
+
if (type.typeArguments && type.typeArguments.length) {
|
|
84
|
+
type.typeArguments.forEach(subType => {
|
|
85
|
+
getJSDocPropertyTags(source, subType, tags, parentName ? parentName + '[]' : '');
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Handling {property1: "value"}
|
|
90
|
+
(type.members || []).filter(m => ts.isTypeElement(m)).forEach(member => {
|
|
91
|
+
let memberName = getName(source, member);
|
|
92
|
+
const memberComment = (member.jsDoc && member.jsDoc[0] && member.jsDoc[0].comment) || '';
|
|
93
|
+
const members = member.type.members || [];
|
|
94
|
+
const memberTypeName = members.length ? 'object' : getTypeName(source, member.type);
|
|
95
|
+
if (parentName) {
|
|
96
|
+
memberName = [parentName, memberName].join('.');
|
|
97
|
+
}
|
|
98
|
+
tags.push(`@property {${memberTypeName}} ${member.questionToken ? `[${memberName}]` : memberName}${memberComment ? ` ${memberComment}` : ``}`);
|
|
99
|
+
getJSDocPropertyTags(source, member.type, tags, memberName);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
return tags;
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Returns JSDoc comment lines and a method to append comment lines.
|
|
106
|
+
*/
|
|
107
|
+
const useCommentLines = (source, jsDocNode) => {
|
|
108
|
+
const commentLines = jsDocNode
|
|
109
|
+
? source.substring(jsDocNode.pos, jsDocNode.end).split(/(\n|\r|\r\n)/).filter(line => line.trim().length > 0)
|
|
110
|
+
: [`/**`, ` */`];
|
|
111
|
+
let appendedAtLeastOnce = jsDocNode ? false : true;
|
|
112
|
+
const shouldUpdate = { current: false };
|
|
113
|
+
const appendComment = line => {
|
|
114
|
+
let args = [commentLines.length - 1, 0];
|
|
115
|
+
if (!appendedAtLeastOnce) {
|
|
116
|
+
appendedAtLeastOnce = true;
|
|
117
|
+
args = args.concat(` *`);
|
|
118
|
+
}
|
|
119
|
+
args = args.concat([].concat(line).map(line => ` * ${line}`));
|
|
120
|
+
commentLines.splice.apply(commentLines, args);
|
|
121
|
+
shouldUpdate.current = true;
|
|
122
|
+
};
|
|
123
|
+
return [commentLines, appendComment, shouldUpdate];
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* Updates JSDoc comments based on the type definitions.
|
|
127
|
+
*/
|
|
128
|
+
const updateJSDocComments = (source, filename, modulePath) => {
|
|
129
|
+
const sourceFile = ts.createSourceFile(filename, source, ts.ScriptTarget.Latest, true);
|
|
130
|
+
let updatedSource = source;
|
|
131
|
+
let tempConstantIndex = 1;
|
|
132
|
+
const isTest = modulePath.includes(`/__tests__/`) && !/\.(spec|test)\.tsx?$/.test(filename);
|
|
133
|
+
if (modulePath && !isTest) {
|
|
134
|
+
if (!updatedSource.includes(`* @module`)) {
|
|
135
|
+
updatedSource = `${updatedSource}\n\n/** @module ${modulePath} */`;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
for (const statement of sourceFile.statements) {
|
|
139
|
+
const name = getName(source, statement);
|
|
140
|
+
const [commentLines, appendComment, shouldUpdate] = useCommentLines(source, statement.jsDoc && statement.jsDoc[0]);
|
|
141
|
+
const appendMemberOf = () => {
|
|
142
|
+
if (modulePath && !isTest) {
|
|
143
|
+
appendComment([
|
|
144
|
+
`@memberof module:${modulePath}`,
|
|
145
|
+
``
|
|
146
|
+
]);
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
let addCommentAfter = false;
|
|
150
|
+
const declaration = statement.declarationList
|
|
151
|
+
&& statement.declarationList.declarations
|
|
152
|
+
&& statement.declarationList.declarations[0];
|
|
153
|
+
const functionParameters = declaration
|
|
154
|
+
&& declaration.initializer
|
|
155
|
+
&& declaration.initializer.parameters;
|
|
156
|
+
if (ts.isTypeAliasDeclaration(statement)) {
|
|
157
|
+
addCommentAfter = true;
|
|
158
|
+
if (ts.isFunctionTypeNode(statement.type)) {
|
|
159
|
+
appendMemberOf();
|
|
160
|
+
appendComment(`@typedef {function} ${name}`);
|
|
161
|
+
statement.type.parameters.forEach(parameter => {
|
|
162
|
+
appendComment(getJSDocParamTag(source, parameter));
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
if (ts.isTypeLiteralNode(statement.type)) {
|
|
166
|
+
appendMemberOf();
|
|
167
|
+
appendComment(`@typedef {object} ${name}`);
|
|
168
|
+
getJSDocPropertyTags(source, statement.type).forEach(appendComment);
|
|
169
|
+
}
|
|
170
|
+
if (ts.isIntersectionTypeNode(statement.type)) {
|
|
171
|
+
appendMemberOf();
|
|
172
|
+
appendComment(`@typedef {object} ${name}`);
|
|
173
|
+
getJSDocPropertyTags(source, statement.type).forEach(appendComment);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
else if (ts.isInterfaceDeclaration(statement)) {
|
|
177
|
+
addCommentAfter = true;
|
|
178
|
+
appendMemberOf();
|
|
179
|
+
appendComment(`@typedef ${name}`);
|
|
180
|
+
statement.members.forEach(member => {
|
|
181
|
+
const memberName = getName(source, member);
|
|
182
|
+
appendComment(`@property {${getTypeName(source, member.type)}} ${member.questionToken ? `[${memberName}]` : memberName}`);
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
else if (ts.isClassDeclaration(statement)) {
|
|
186
|
+
const className = getName(source, statement);
|
|
187
|
+
const memberComments = [];
|
|
188
|
+
statement.members.forEach(member => {
|
|
189
|
+
if (!ts.isPropertyDeclaration(member)) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
const modifiers = (member.modifiers || []).map(m => m.getText({ text: source }));
|
|
193
|
+
modifiers.forEach(m => {
|
|
194
|
+
if (['private', 'public', 'protected'].includes(m)) {
|
|
195
|
+
memberComments.push(`@${m}`);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
if (member.type) {
|
|
199
|
+
memberComments.push(`@type {${getTypeName(source, member.type)}}`);
|
|
200
|
+
}
|
|
201
|
+
if (modifiers.find((m => m === 'static'))) {
|
|
202
|
+
memberComments.push(`${className}.${getName(source, member)}`);
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
memberComments.push(`${className}.prototype.${getName(source, member)}`);
|
|
206
|
+
}
|
|
207
|
+
memberComments.forEach(appendComment);
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
else if (declaration && declaration.type) {
|
|
211
|
+
appendMemberOf();
|
|
212
|
+
appendComment(`@type {${getTypeName(source, declaration.type)}}`);
|
|
213
|
+
}
|
|
214
|
+
else if (functionParameters) {
|
|
215
|
+
appendMemberOf();
|
|
216
|
+
functionParameters.forEach(parameter => {
|
|
217
|
+
appendComment(getJSDocParamTag(source, parameter));
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
if (shouldUpdate.current) {
|
|
221
|
+
const newCommentBlock = commentLines.join(`\n`); // TODO .replace(/```ts/g, '```js')
|
|
222
|
+
const text = statement.getText().trim();
|
|
223
|
+
const fullText = statement.getFullText().trim();
|
|
224
|
+
if (filename.split(/\/|\\/).pop() === `types.ts` || !fullText || updatedSource.indexOf(fullText) < 0) {
|
|
225
|
+
updatedSource = `${updatedSource}\n\n${newCommentBlock}`;
|
|
226
|
+
}
|
|
227
|
+
else if (addCommentAfter) {
|
|
228
|
+
updatedSource = updatedSource.replace(statement.jsDoc ? fullText : text, `${text}\n\n${newCommentBlock}\nconst ___temp${tempConstantIndex++} = null`);
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
updatedSource = updatedSource.replace(statement.jsDoc ? fullText : text, `${newCommentBlock}\n${text}`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return updatedSource;
|
|
236
|
+
};
|
|
237
|
+
/**
|
|
238
|
+
* Recursively walks through the directories and converts all .ts and .tsx files
|
|
239
|
+
* to .js and .jsx files with JSDoc type annotations based on the type definitions.
|
|
240
|
+
*
|
|
241
|
+
* All other files are copied as is.
|
|
242
|
+
*/
|
|
243
|
+
const tsToJs = (tsPath, jsPath, modulePath = '') => {
|
|
244
|
+
const files = fs.readdirSync(tsPath);
|
|
245
|
+
for (const file of files) {
|
|
246
|
+
const tsFile = path.join(tsPath, file);
|
|
247
|
+
const jsFile = path.join(jsPath, file.replace(/\.ts$/, '.js').replace(/\.tsx$/, '.jsx'));
|
|
248
|
+
const stats = fs.statSync(tsFile);
|
|
249
|
+
if (stats.isDirectory()) {
|
|
250
|
+
tsToJs(tsFile, jsFile, modulePath ? `${modulePath}/${file}` : file);
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
else if (!/\.tsx?$/.test(file)) {
|
|
254
|
+
// Ensure the directory exists.
|
|
255
|
+
if (!fs.existsSync(jsPath)) {
|
|
256
|
+
fs.mkdirSync(jsPath, { recursive: true });
|
|
257
|
+
}
|
|
258
|
+
fs.copyFileSync(tsFile, jsFile);
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
else if (/\.d\.ts$/.test(file)) {
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
let source = fs.readFileSync(tsFile, 'utf8');
|
|
265
|
+
if (source.includes(`/** @ts-only */`)) {
|
|
266
|
+
// Skip copying of files with this flag.
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
// Remove lines (usually type imports) containing the `// @ts-only` comment.
|
|
270
|
+
source = source.replace(/^(.*)\/\/ @ts-only(.*)(\r|\n|\r\n)/gm, ``);
|
|
271
|
+
// Ensure every module is covered.
|
|
272
|
+
source = source + `\n\n\nconst ___temp = null`;
|
|
273
|
+
// Add the necessary JSDoc comments based on the type definitions.
|
|
274
|
+
source = updateJSDocComments(source, tsFile, modulePath ? `${modulePath}/${file.replace(/\.tsx?$/, ``)}` : file.replace(/\.tsx?$/, ``));
|
|
275
|
+
// Preserve line spacing.
|
|
276
|
+
source = source.replace(/(\n\n|\r\r|\r\n\r\n)/g, '\n/* __NEWLINE__ */');
|
|
277
|
+
// Get transpiled ESM code.
|
|
278
|
+
source = ts.transpileModule(source, {
|
|
279
|
+
compilerOptions: {
|
|
280
|
+
target: ts.ScriptTarget.ESNext,
|
|
281
|
+
module: ts.ModuleKind.ESNext,
|
|
282
|
+
moduleResolution: ts.ModuleResolutionKind.NodeJs,
|
|
283
|
+
esModuleInterop: true,
|
|
284
|
+
strict: false,
|
|
285
|
+
jsx: /\.tsx$/.test(file) ? ts.JsxEmit.Preserve : ts.JsxEmit.None,
|
|
286
|
+
newLine: ts.NewLineKind.LineFeed,
|
|
287
|
+
removeComments: false,
|
|
288
|
+
pretty: true
|
|
289
|
+
}
|
|
290
|
+
}).outputText;
|
|
291
|
+
// Restore line spacing.
|
|
292
|
+
source = source.replace(/\/\* __NEWLINE__ \*\//g, '\n');
|
|
293
|
+
// Remove the temporary constants.
|
|
294
|
+
source = source.replace(/const ___temp(|[0-9]+) = null/g, '');
|
|
295
|
+
// Remove @typescript-eslint lines.
|
|
296
|
+
source = source.replace(/(\s|)(\/\/|\/\*) eslint-disable(|-next-line) @typescript-eslint\/.*?(\n|\r|\r\n)/gi, `\n`);
|
|
297
|
+
try {
|
|
298
|
+
// Make the code pretty again.
|
|
299
|
+
source = prettier.format(source, {
|
|
300
|
+
filepath: jsFile,
|
|
301
|
+
printWidth: 120,
|
|
302
|
+
semi: false,
|
|
303
|
+
singleQuote: true,
|
|
304
|
+
quoteProps: 'consistent',
|
|
305
|
+
jsxSingleQuote: true,
|
|
306
|
+
trailingComma: 'none'
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
catch (error) {
|
|
310
|
+
console.error(error);
|
|
311
|
+
console.log(tsFile);
|
|
312
|
+
console.log(source);
|
|
313
|
+
}
|
|
314
|
+
if (source.trim().length && source.trim() !== `export {}`) {
|
|
315
|
+
// Ensure the directory exists.
|
|
316
|
+
if (!fs.existsSync(jsPath)) {
|
|
317
|
+
fs.mkdirSync(jsPath, { recursive: true });
|
|
318
|
+
}
|
|
319
|
+
// Write the JavaScript file.
|
|
320
|
+
fs.writeFileSync(jsFile, source);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
if (process.argv[2]) {
|
|
325
|
+
const tsPath = path.join(__dirname, process.argv[2], `src-ts`);
|
|
326
|
+
const jsPath = path.join(__dirname, process.argv[2], `src`);
|
|
327
|
+
if (fs.existsSync(jsPath)) {
|
|
328
|
+
fs.rmSync(jsPath, { recursive: true });
|
|
329
|
+
}
|
|
330
|
+
fs.mkdirSync(jsPath);
|
|
331
|
+
tsToJs(tsPath, jsPath);
|
|
332
|
+
}
|
|
333
|
+
else if (fs.existsSync(path.join(__dirname, `src-ts`))) {
|
|
334
|
+
const tsPath = path.join(__dirname, `src-ts`);
|
|
335
|
+
const jsPath = path.join(__dirname, `src`);
|
|
336
|
+
if (fs.existsSync(jsPath)) {
|
|
337
|
+
fs.rmSync(jsPath, { recursive: true });
|
|
338
|
+
}
|
|
339
|
+
fs.mkdirSync(jsPath);
|
|
340
|
+
tsToJs(tsPath, jsPath);
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
console.info(`Usage is: node ts-to-js <dir>`);
|
|
344
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
const __dirname = fileURLToPath(path.dirname(import.meta.url));
|
|
5
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, `../../package.json`), `utf8`));
|
|
6
|
+
/**
|
|
7
|
+
* Adds the `version` command to the program.
|
|
8
|
+
*/
|
|
9
|
+
export const version = (program) => {
|
|
10
|
+
program
|
|
11
|
+
.name(process.env.APP_NAME || pkg.name)
|
|
12
|
+
.description(pkg.description)
|
|
13
|
+
.version(process.env.APP_VERSION || pkg.version);
|
|
14
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import xdiff from 'xdiff';
|
|
3
|
+
import detectIndent from 'detect-indent';
|
|
4
|
+
const encoding = 'utf8';
|
|
5
|
+
/**
|
|
6
|
+
* Adds the `x-merge-json` command to the program.
|
|
7
|
+
*
|
|
8
|
+
* Based off of https://github.com/jonatanpedersen/git-json-merge.
|
|
9
|
+
* Using our own implementation here because we're going to improve it later.
|
|
10
|
+
*/
|
|
11
|
+
export const xMergeJSON = (program) => {
|
|
12
|
+
program.command(`x-merge-json`)
|
|
13
|
+
.description(`git merge driver for JSON files`)
|
|
14
|
+
.argument(`[baseFilename]`, `base filename`)
|
|
15
|
+
.argument(`[oursFilename]`, `ours filename`)
|
|
16
|
+
.argument(`[theirsFilename]`, `theirs filename`)
|
|
17
|
+
.action(async (baseFilename, oursFilename, theirsFilename) => {
|
|
18
|
+
const baseJson = fs.readFileSync(baseFilename, encoding);
|
|
19
|
+
const base = JSON.parse(baseJson);
|
|
20
|
+
const baseIndent = detectIndent(baseJson).indent;
|
|
21
|
+
const oursJson = fs.readFileSync(oursFilename, encoding);
|
|
22
|
+
const ours = JSON.parse(oursJson);
|
|
23
|
+
const oursIndent = detectIndent(oursJson).indent;
|
|
24
|
+
const theirsJson = fs.readFileSync(theirsFilename, encoding);
|
|
25
|
+
const theirs = JSON.parse(theirsJson);
|
|
26
|
+
const theirsIndent = detectIndent(theirsJson).indent;
|
|
27
|
+
const indent = oursIndent !== baseIndent ? oursIndent : theirsIndent !== baseIndent ? theirsIndent : baseIndent;
|
|
28
|
+
const diff = xdiff.diff3(ours, base, theirs);
|
|
29
|
+
const newOurs = diff ? xdiff.patch(base, diff) : base;
|
|
30
|
+
const newOursJson = JSON.stringify(newOurs, null, indent);
|
|
31
|
+
fs.writeFileSync(oursFilename, newOursJson, encoding);
|
|
32
|
+
});
|
|
33
|
+
};
|
package/build/config.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This module helps with various sets of environment variables,
|
|
3
|
+
* using both `dotenv` and `env-cmd`.
|
|
4
|
+
*
|
|
5
|
+
* The `.env` file will be loaded via `dotenv.config()` and extended
|
|
6
|
+
* by the variables for the `NODE_ENV` key specified in `.env-cmdrc.json`.
|
|
7
|
+
*
|
|
8
|
+
* This also allows you to combine various sets of env vars using e.g.:
|
|
9
|
+
* ```
|
|
10
|
+
* ./node_modules/.bin/env-cmd -e development,something,etc npm run dev
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* @see https://www.npmjs.com/package/dotenv
|
|
14
|
+
* @see https://www.npmjs.com/package/env-cmd
|
|
15
|
+
*
|
|
16
|
+
* @module
|
|
17
|
+
*/
|
|
18
|
+
import 'dotenv/config';
|
|
19
|
+
import fs from 'fs';
|
|
20
|
+
import path from 'path';
|
|
21
|
+
import { fileURLToPath } from 'url';
|
|
22
|
+
import { pkg } from './pkg.js';
|
|
23
|
+
const __dirname = fileURLToPath(path.dirname(import.meta.url));
|
|
24
|
+
const defaultEnv = {
|
|
25
|
+
APP_ID: `mlcl`,
|
|
26
|
+
APP_NAME: pkg.name,
|
|
27
|
+
APP_VERSION: pkg.version,
|
|
28
|
+
APP_PLATFORM: `cli`,
|
|
29
|
+
API_ORIGIN: `https://api.molecule.dev`,
|
|
30
|
+
WEB_ORIGIN: `https://assemble.molecule.dev`,
|
|
31
|
+
LOG_LEVEL: `info`,
|
|
32
|
+
};
|
|
33
|
+
const defaultEnvCmdrc = {
|
|
34
|
+
'development': {
|
|
35
|
+
NODE_ENV: 'development',
|
|
36
|
+
API_ORIGIN: 'http://localhost:4000',
|
|
37
|
+
WEB_ORIGIN: 'http://localhost:3000',
|
|
38
|
+
},
|
|
39
|
+
'production': {
|
|
40
|
+
NODE_ENV: 'production',
|
|
41
|
+
API_ORIGIN: 'https://api.molecule.dev',
|
|
42
|
+
WEB_ORIGIN: 'https://assemble.molecule.dev',
|
|
43
|
+
},
|
|
44
|
+
'test': {
|
|
45
|
+
NODE_ENV: 'test',
|
|
46
|
+
LOG_LEVEL: 'silent',
|
|
47
|
+
API_ORIGIN: 'http://localhost:4000',
|
|
48
|
+
WEB_ORIGIN: 'http://localhost:3000',
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
if (!process.env.NODE_ENV) {
|
|
52
|
+
process.env.NODE_ENV = `production`;
|
|
53
|
+
}
|
|
54
|
+
for (const key in defaultEnv) {
|
|
55
|
+
process.env[key] = defaultEnv[key];
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Sets the variables specified within each environment within `.env-cmdrc.json`.
|
|
59
|
+
*/
|
|
60
|
+
export const setVariables = (environments = [process.env.NODE_ENV || `production`]) => {
|
|
61
|
+
try {
|
|
62
|
+
const envCmdrcPath = path.join(__dirname, '../.env-cmdrc.json');
|
|
63
|
+
const envCmdrc = fs.existsSync(envCmdrcPath)
|
|
64
|
+
? JSON.parse(fs.readFileSync(envCmdrcPath, 'utf8'))
|
|
65
|
+
: defaultEnvCmdrc;
|
|
66
|
+
for (const environment of environments) {
|
|
67
|
+
const variables = envCmdrc[environment];
|
|
68
|
+
if (variables) {
|
|
69
|
+
Object.assign(process.env, variables);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
console.warn(`Environment "${environment}" not found within .env-cmdrc.`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
// Extend the environment variables using `.env-cmdrc.json`.
|
|
80
|
+
setVariables();
|
package/build/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Molecule.dev command line tools.
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
import './environment.js';
|
|
8
|
+
import { program } from 'commander';
|
|
9
|
+
import * as commands from './commands/index.js';
|
|
10
|
+
export * as API from './API/index.js';
|
|
11
|
+
export * as commands from './commands/index.js';
|
|
12
|
+
export * as utilities from './utilities/index.js';
|
|
13
|
+
export * from './logger.js';
|
|
14
|
+
export * from './pkg.js';
|
|
15
|
+
export * from './repoConfig.js';
|
|
16
|
+
export * from './userConfig.js';
|
|
17
|
+
export * as types from './types/index.js';
|
|
18
|
+
for (const commandKey in commands) {
|
|
19
|
+
if (typeof commands[commandKey] === `function`) {
|
|
20
|
+
commands[commandKey](program);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
program.parse();
|
package/build/logger.js
ADDED
package/build/pkg.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { getErrorMessage } from '../getErrorMessage.js';
|
|
2
|
+
it(`returns a better "timed out" message`, () => {
|
|
3
|
+
expect(getErrorMessage({ code: `ETIMEDOUT` })).toBe(`Timed out`);
|
|
4
|
+
});
|
|
5
|
+
it(`returns a better "connection aborted" message`, () => {
|
|
6
|
+
expect(getErrorMessage({ code: `ECONNABORTED` })).toBe(`Connection aborted`);
|
|
7
|
+
});
|
|
8
|
+
it(`returns response data's error message`, () => {
|
|
9
|
+
expect(getErrorMessage({
|
|
10
|
+
response: {
|
|
11
|
+
data: {
|
|
12
|
+
error: `Username is required.`
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
})).toBe(`Username is required.`);
|
|
16
|
+
});
|
|
17
|
+
it(`returns error message`, () => {
|
|
18
|
+
expect(getErrorMessage(new Error(`Unexpected token`))).toBe(`Unexpected token`);
|
|
19
|
+
});
|
|
20
|
+
it(`returns the error if already a string`, () => {
|
|
21
|
+
expect(getErrorMessage(`Unexpected token`)).toBe(`Unexpected token`);
|
|
22
|
+
});
|
|
23
|
+
it(`returns null if no error`, () => {
|
|
24
|
+
expect(getErrorMessage()).toBe(null);
|
|
25
|
+
expect(getErrorMessage(null)).toBe(null);
|
|
26
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { timeAgo } from '../timeAgo.js';
|
|
2
|
+
const MINUTE = 60000 + 1;
|
|
3
|
+
const HOUR = 3600000 + 1;
|
|
4
|
+
const DAY = 86400000 + 1;
|
|
5
|
+
const WEEK = 604800000 + 1;
|
|
6
|
+
const YEAR = 31557600000 + 1;
|
|
7
|
+
it(`returns "just now"`, () => {
|
|
8
|
+
expect(timeAgo(new Date().getTime())).toBe(`just now`);
|
|
9
|
+
});
|
|
10
|
+
it(`returns "minute(s)"`, () => {
|
|
11
|
+
expect(timeAgo(new Date().getTime() - MINUTE)).toBe(`1 minute ago`);
|
|
12
|
+
expect(timeAgo(new Date().getTime() - MINUTE * 2)).toBe(`2 minutes ago`);
|
|
13
|
+
expect(timeAgo(new Date().getTime() - MINUTE, true)).toBe(`1m ago`);
|
|
14
|
+
expect(timeAgo(new Date().getTime() - MINUTE * 2, true)).toBe(`2m ago`);
|
|
15
|
+
});
|
|
16
|
+
it(`returns "hour(s)"`, () => {
|
|
17
|
+
expect(timeAgo(new Date().getTime() - HOUR)).toBe(`1 hour ago`);
|
|
18
|
+
expect(timeAgo(new Date().getTime() - HOUR * 2)).toBe(`2 hours ago`);
|
|
19
|
+
expect(timeAgo(new Date().getTime() - HOUR, true)).toBe(`1h ago`);
|
|
20
|
+
expect(timeAgo(new Date().getTime() - HOUR * 2, true)).toBe(`2h ago`);
|
|
21
|
+
});
|
|
22
|
+
it(`returns "day(s)"`, () => {
|
|
23
|
+
expect(timeAgo(new Date().getTime() - DAY)).toBe(`1 day ago`);
|
|
24
|
+
expect(timeAgo(new Date().getTime() - DAY * 2)).toBe(`2 days ago`);
|
|
25
|
+
expect(timeAgo(new Date().getTime() - DAY, true)).toBe(`1d ago`);
|
|
26
|
+
expect(timeAgo(new Date().getTime() - DAY * 2, true)).toBe(`2d ago`);
|
|
27
|
+
});
|
|
28
|
+
it(`returns "week(s)"`, () => {
|
|
29
|
+
expect(timeAgo(new Date().getTime() - WEEK)).toBe(`1 week ago`);
|
|
30
|
+
expect(timeAgo(new Date().getTime() - WEEK * 2)).toBe(`2 weeks ago`);
|
|
31
|
+
expect(timeAgo(new Date().getTime() - WEEK, true)).toBe(`1w ago`);
|
|
32
|
+
expect(timeAgo(new Date().getTime() - WEEK * 2, true)).toBe(`2w ago`);
|
|
33
|
+
});
|
|
34
|
+
it(`returns "year(s)"`, () => {
|
|
35
|
+
expect(timeAgo(new Date().getTime() - YEAR)).toBe(`1 year ago`);
|
|
36
|
+
expect(timeAgo(new Date().getTime() - YEAR * 2)).toBe(`2 years ago`);
|
|
37
|
+
expect(timeAgo(new Date().getTime() - YEAR, true)).toBe(`1y ago`);
|
|
38
|
+
expect(timeAgo(new Date().getTime() - YEAR * 2, true)).toBe(`2y ago`);
|
|
39
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import semver from 'semver';
|
|
2
|
+
import axios from 'axios';
|
|
3
|
+
import { pkg } from '../pkg.js';
|
|
4
|
+
import { userConfig } from '../userConfig.js';
|
|
5
|
+
import { writeUserConfig } from '../utilities/writeUserConfig.js';
|
|
6
|
+
import { logger } from '../logger.js';
|
|
7
|
+
export const checkVersion = async () => {
|
|
8
|
+
if (userConfig.newVersion) {
|
|
9
|
+
if (semver.gt(userConfig.newVersion, pkg.version)) {
|
|
10
|
+
logger.info(`A new version (${userConfig.newVersion}) of \`mlcl\` is available.`);
|
|
11
|
+
logger.info(`You are currently on version ${pkg.version}.`);
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
delete userConfig.newVersion;
|
|
15
|
+
writeUserConfig();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
const { version } = (await axios.get(`https://registry.npmjs.org/mlcl/latest`)).data;
|
|
20
|
+
if (version && semver.gt(version, pkg.version)) {
|
|
21
|
+
userConfig.newVersion = version;
|
|
22
|
+
writeUserConfig();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
// Check every time `mlcl` is run.
|
|
29
|
+
checkVersion();
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attempts to return a human readable message based on some `Error`.
|
|
3
|
+
*/
|
|
4
|
+
export const getErrorMessage = (error) => {
|
|
5
|
+
if (!error) {
|
|
6
|
+
return null;
|
|
7
|
+
}
|
|
8
|
+
if (typeof error === `string`) {
|
|
9
|
+
return error;
|
|
10
|
+
}
|
|
11
|
+
return (({ ETIMEDOUT: `Timed out`, ECONNABORTED: `Connection aborted` })[error.code || -1]
|
|
12
|
+
|| error.response?.data?.error
|
|
13
|
+
|| error.message
|
|
14
|
+
|| null);
|
|
15
|
+
};
|