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.
Files changed (195) hide show
  1. package/.eslintignore +31 -0
  2. package/.eslintrc.json +54 -0
  3. package/LICENSE +200 -0
  4. package/README.md +101 -0
  5. package/babel.config.json +10 -0
  6. package/build/API/authorization.js +107 -0
  7. package/build/API/client.js +11 -0
  8. package/build/API/index.js +8 -0
  9. package/build/API/molecule/index.js +11 -0
  10. package/build/API/molecule/types.js +6 -0
  11. package/build/API/resource/device/index.js +12 -0
  12. package/build/API/resource/device/types.js +6 -0
  13. package/build/API/resource/device/utilities/confirmSshKey.js +20 -0
  14. package/build/API/resource/device/utilities/index.js +7 -0
  15. package/build/API/resource/device/utilities/sendSshKey.js +64 -0
  16. package/build/API/resource/index.js +10 -0
  17. package/build/API/resource/molecule/index.js +12 -0
  18. package/build/API/resource/molecule/types.js +6 -0
  19. package/build/API/resource/molecule/utilities/getPlan.js +15 -0
  20. package/build/API/resource/molecule/utilities/index.js +6 -0
  21. package/build/API/resource/payment/index.js +9 -0
  22. package/build/API/resource/payment/plans.js +28 -0
  23. package/build/API/resource/payment/platform.js +7 -0
  24. package/build/API/resource/payment/platforms/apple/index.js +21 -0
  25. package/build/API/resource/payment/platforms/apple/plans/appleMonthly.js +17 -0
  26. package/build/API/resource/payment/platforms/apple/plans/appleYearly.js +18 -0
  27. package/build/API/resource/payment/platforms/apple/plans/index.js +7 -0
  28. package/build/API/resource/payment/platforms/google/index.js +21 -0
  29. package/build/API/resource/payment/platforms/google/plans/googleMonthly.js +17 -0
  30. package/build/API/resource/payment/platforms/google/plans/googleYearly.js +18 -0
  31. package/build/API/resource/payment/platforms/google/plans/index.js +7 -0
  32. package/build/API/resource/payment/platforms/index.js +8 -0
  33. package/build/API/resource/payment/platforms/stripe/index.js +25 -0
  34. package/build/API/resource/payment/platforms/stripe/plans/index.js +11 -0
  35. package/build/API/resource/payment/platforms/stripe/plans/stripeBusinessMolecule.js +21 -0
  36. package/build/API/resource/payment/platforms/stripe/plans/stripeMonthly.js +18 -0
  37. package/build/API/resource/payment/platforms/stripe/plans/stripeMonthlyMolecule.js +18 -0
  38. package/build/API/resource/payment/platforms/stripe/plans/stripeSingleUseMolecule.js +19 -0
  39. package/build/API/resource/payment/platforms/stripe/plans/stripeUnlimitedUseMolecule.js +19 -0
  40. package/build/API/resource/payment/platforms/stripe/plans/stripeYearly.js +19 -0
  41. package/build/API/resource/payment/types.js +6 -0
  42. package/build/API/resource/types.js +6 -0
  43. package/build/API/resource/user/index.js +15 -0
  44. package/build/API/resource/user/types.js +6 -0
  45. package/build/API/resource/user/utilities/getPlan.js +12 -0
  46. package/build/API/resource/user/utilities/index.js +7 -0
  47. package/build/API/resource/user/utilities/logIn.js +60 -0
  48. package/build/cli.js +15 -0
  49. package/build/commands/add-ssh-key.js +24 -0
  50. package/build/commands/buy.js +70 -0
  51. package/build/commands/clone.js +329 -0
  52. package/build/commands/index.js +17 -0
  53. package/build/commands/info.js +33 -0
  54. package/build/commands/login.js +20 -0
  55. package/build/commands/logout.js +23 -0
  56. package/build/commands/molecule/index.js +11 -0
  57. package/build/commands/molecule/types.js +6 -0
  58. package/build/commands/remove-ssh-key.js +36 -0
  59. package/build/commands/select.js +98 -0
  60. package/build/commands/set-api-key.js +73 -0
  61. package/build/commands/subscribe.js +74 -0
  62. package/build/commands/unsubscribe.js +59 -0
  63. package/build/commands/utilities/asyncExec.js +6 -0
  64. package/build/commands/utilities/branchExists.js +13 -0
  65. package/build/commands/utilities/branchExistsSync.js +12 -0
  66. package/build/commands/utilities/checkoutSelectionBranch.js +49 -0
  67. package/build/commands/utilities/cherryPick.js +20 -0
  68. package/build/commands/utilities/cloneRepo.js +9 -0
  69. package/build/commands/utilities/convertNpmToYarn.js +60 -0
  70. package/build/commands/utilities/convertTypeDocToJSDoc.js +51 -0
  71. package/build/commands/utilities/convertTypeScriptToJavaScript.js +451 -0
  72. package/build/commands/utilities/enableMergeDrivers.js +50 -0
  73. package/build/commands/utilities/getCurrentBranch.js +11 -0
  74. package/build/commands/utilities/getCurrentBranchSync.js +7 -0
  75. package/build/commands/utilities/getRepoRootPath.js +7 -0
  76. package/build/commands/utilities/getRepoRootPathSync.js +13 -0
  77. package/build/commands/utilities/index.js +16 -0
  78. package/build/commands/utilities/npm-to-yarn.js +41 -0
  79. package/build/commands/utilities/ts-to-js.js +344 -0
  80. package/build/commands/version.js +14 -0
  81. package/build/commands/x-merge-json.js +33 -0
  82. package/build/config.js +5 -0
  83. package/build/environment.js +80 -0
  84. package/build/index.js +23 -0
  85. package/build/logger.js +12 -0
  86. package/build/pkg.js +5 -0
  87. package/build/repoConfig copy.js +5 -0
  88. package/build/repoConfig.js +5 -0
  89. package/build/types/global.js +6 -0
  90. package/build/types/index.js +6 -0
  91. package/build/userConfig.js +5 -0
  92. package/build/utilities/__tests__/getErrorMessage.js +26 -0
  93. package/build/utilities/__tests__/timeAgo.js +39 -0
  94. package/build/utilities/checkVersion.js +29 -0
  95. package/build/utilities/getErrorMessage.js +15 -0
  96. package/build/utilities/index.js +13 -0
  97. package/build/utilities/readConfig.js +19 -0
  98. package/build/utilities/readRepoConfig copy.js +20 -0
  99. package/build/utilities/readRepoConfig.js +19 -0
  100. package/build/utilities/readUserConfig.js +20 -0
  101. package/build/utilities/synchronizeUserConfig.js +25 -0
  102. package/build/utilities/timeAgo.js +42 -0
  103. package/build/utilities/userLoggedIn.js +24 -0
  104. package/build/utilities/writeConfig.js +8 -0
  105. package/build/utilities/writeRepoConfig copy.js +9 -0
  106. package/build/utilities/writeRepoConfig.js +10 -0
  107. package/build/utilities/writeUserConfig.js +11 -0
  108. package/jest.config.json +11 -0
  109. package/package.json +56 -0
  110. package/src/API/authorization.ts +143 -0
  111. package/src/API/client.ts +12 -0
  112. package/src/API/index.ts +10 -0
  113. package/src/API/resource/device/index.ts +27 -0
  114. package/src/API/resource/device/types.ts +80 -0
  115. package/src/API/resource/device/utilities/confirmSshKey.ts +25 -0
  116. package/src/API/resource/device/utilities/index.ts +8 -0
  117. package/src/API/resource/device/utilities/sendSshKey.ts +80 -0
  118. package/src/API/resource/index.ts +12 -0
  119. package/src/API/resource/molecule/index.ts +30 -0
  120. package/src/API/resource/molecule/types.ts +332 -0
  121. package/src/API/resource/molecule/utilities/getPlan.ts +21 -0
  122. package/src/API/resource/molecule/utilities/index.ts +7 -0
  123. package/src/API/resource/payment/index.ts +12 -0
  124. package/src/API/resource/payment/plans.ts +32 -0
  125. package/src/API/resource/payment/platform.ts +11 -0
  126. package/src/API/resource/payment/platforms/apple/index.ts +25 -0
  127. package/src/API/resource/payment/platforms/apple/plans/appleMonthly.ts +19 -0
  128. package/src/API/resource/payment/platforms/apple/plans/appleYearly.ts +20 -0
  129. package/src/API/resource/payment/platforms/apple/plans/index.ts +9 -0
  130. package/src/API/resource/payment/platforms/google/index.ts +25 -0
  131. package/src/API/resource/payment/platforms/google/plans/googleMonthly.ts +19 -0
  132. package/src/API/resource/payment/platforms/google/plans/googleYearly.ts +20 -0
  133. package/src/API/resource/payment/platforms/google/plans/index.ts +9 -0
  134. package/src/API/resource/payment/platforms/index.ts +10 -0
  135. package/src/API/resource/payment/platforms/stripe/index.ts +29 -0
  136. package/src/API/resource/payment/platforms/stripe/plans/index.ts +12 -0
  137. package/src/API/resource/payment/platforms/stripe/plans/stripeBusinessMolecule.ts +23 -0
  138. package/src/API/resource/payment/platforms/stripe/plans/stripeMonthly.ts +20 -0
  139. package/src/API/resource/payment/platforms/stripe/plans/stripeMonthlyMolecule.ts +20 -0
  140. package/src/API/resource/payment/platforms/stripe/plans/stripeSingleUseMolecule.ts +21 -0
  141. package/src/API/resource/payment/platforms/stripe/plans/stripeUnlimitedUseMolecule.ts +21 -0
  142. package/src/API/resource/payment/platforms/stripe/plans/stripeYearly.ts +21 -0
  143. package/src/API/resource/payment/types.ts +201 -0
  144. package/src/API/resource/types.ts +169 -0
  145. package/src/API/resource/user/index.ts +29 -0
  146. package/src/API/resource/user/types.ts +131 -0
  147. package/src/API/resource/user/utilities/getPlan.ts +16 -0
  148. package/src/API/resource/user/utilities/index.ts +8 -0
  149. package/src/API/resource/user/utilities/logIn.ts +71 -0
  150. package/src/commands/add-ssh-key.ts +30 -0
  151. package/src/commands/buy.ts +83 -0
  152. package/src/commands/clone.ts +363 -0
  153. package/src/commands/index.ts +19 -0
  154. package/src/commands/info.ts +40 -0
  155. package/src/commands/login.ts +24 -0
  156. package/src/commands/logout.ts +27 -0
  157. package/src/commands/remove-ssh-key.ts +42 -0
  158. package/src/commands/subscribe.ts +84 -0
  159. package/src/commands/unsubscribe.ts +67 -0
  160. package/src/commands/utilities/asyncExec.ts +7 -0
  161. package/src/commands/utilities/branchExists.ts +15 -0
  162. package/src/commands/utilities/checkoutSelectionBranch.ts +62 -0
  163. package/src/commands/utilities/cherryPick.ts +23 -0
  164. package/src/commands/utilities/cloneRepo.ts +10 -0
  165. package/src/commands/utilities/convertNpmToYarn.ts +71 -0
  166. package/src/commands/utilities/convertTypeDocToJSDoc.ts +55 -0
  167. package/src/commands/utilities/convertTypeScriptToJavaScript.ts +526 -0
  168. package/src/commands/utilities/enableMergeDrivers.ts +55 -0
  169. package/src/commands/utilities/getCurrentBranch.ts +14 -0
  170. package/src/commands/utilities/getRepoRootPathSync.ts +13 -0
  171. package/src/commands/utilities/index.ts +17 -0
  172. package/src/commands/version.ts +22 -0
  173. package/src/commands/x-merge-json.ts +41 -0
  174. package/src/environment.ts +88 -0
  175. package/src/index.ts +30 -0
  176. package/src/logger.ts +29 -0
  177. package/src/pkg.ts +11 -0
  178. package/src/repoConfig.ts +6 -0
  179. package/src/types/global.ts +26 -0
  180. package/src/types/index.ts +53 -0
  181. package/src/types/process.env.d.ts +56 -0
  182. package/src/userConfig.ts +6 -0
  183. package/src/utilities/__tests__/getErrorMessage.ts +32 -0
  184. package/src/utilities/__tests__/timeAgo.ts +46 -0
  185. package/src/utilities/checkVersion.ts +31 -0
  186. package/src/utilities/getErrorMessage.ts +30 -0
  187. package/src/utilities/index.ts +14 -0
  188. package/src/utilities/readRepoConfig.ts +22 -0
  189. package/src/utilities/readUserConfig.ts +24 -0
  190. package/src/utilities/synchronizeUserConfig.ts +26 -0
  191. package/src/utilities/timeAgo.ts +39 -0
  192. package/src/utilities/userLoggedIn.ts +28 -0
  193. package/src/utilities/writeRepoConfig.ts +11 -0
  194. package/src/utilities/writeUserConfig.ts +13 -0
  195. 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
+ };
@@ -0,0 +1,5 @@
1
+ import * as utilities from './utilities/index.js';
2
+ /**
3
+ * The current `.mlcl.json` (default) configuration state.
4
+ */
5
+ export const config = utilities.readConfig();
@@ -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();
@@ -0,0 +1,12 @@
1
+ /**
2
+ * The logger, using `loglevel`.
3
+ *
4
+ * @see https://www.npmjs.com/package/loglevel
5
+ *
6
+ * @module
7
+ */
8
+ import logger from 'loglevel';
9
+ if (process.env.LOG_LEVEL) {
10
+ logger.setLevel(process.env.LOG_LEVEL);
11
+ }
12
+ export { logger };
package/build/pkg.js ADDED
@@ -0,0 +1,5 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ const __dirname = fileURLToPath(path.dirname(import.meta.url));
5
+ export const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, `../package.json`), `utf8`));
@@ -0,0 +1,5 @@
1
+ import { readRepoConfig } from './utilities/readRepoConfig.js';
2
+ /**
3
+ * The current repo's `mlcl` configuration state.
4
+ */
5
+ export const repoConfig = readRepoConfig();
@@ -0,0 +1,5 @@
1
+ import { readRepoConfig } from './utilities/readRepoConfig.js';
2
+ /**
3
+ * The current repo's `mlcl` configuration state.
4
+ */
5
+ export const repoConfig = readRepoConfig();
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Global type definitions.
3
+ *
4
+ * @module
5
+ */
6
+ export {};
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Types used throughout `mlcl`.
3
+ *
4
+ * @module
5
+ */
6
+ export * as global from './global.js';
@@ -0,0 +1,5 @@
1
+ import { readUserConfig } from './utilities/readUserConfig.js';
2
+ /**
3
+ * The current user's `mlcl` configuration state.
4
+ */
5
+ export const userConfig = readUserConfig();
@@ -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
+ };