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,88 @@
|
|
|
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
|
+
|
|
19
|
+
import 'dotenv/config'
|
|
20
|
+
import fs from 'fs'
|
|
21
|
+
import path from 'path'
|
|
22
|
+
import { fileURLToPath } from 'url'
|
|
23
|
+
import { pkg } from './pkg.js'
|
|
24
|
+
|
|
25
|
+
const __dirname = fileURLToPath(path.dirname(import.meta.url))
|
|
26
|
+
|
|
27
|
+
const defaultEnv = {
|
|
28
|
+
APP_ID: `mlcl`,
|
|
29
|
+
APP_NAME: pkg.name,
|
|
30
|
+
APP_VERSION: pkg.version,
|
|
31
|
+
APP_PLATFORM: `cli`,
|
|
32
|
+
API_ORIGIN: `https://api.molecule.dev`,
|
|
33
|
+
WEB_ORIGIN: `https://assemble.molecule.dev`,
|
|
34
|
+
LOG_LEVEL: `info`,
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const defaultEnvCmdrc = {
|
|
38
|
+
'development': {
|
|
39
|
+
NODE_ENV: 'development',
|
|
40
|
+
API_ORIGIN: 'http://localhost:4000',
|
|
41
|
+
WEB_ORIGIN: 'http://localhost:3000',
|
|
42
|
+
},
|
|
43
|
+
'production': {
|
|
44
|
+
NODE_ENV: 'production',
|
|
45
|
+
API_ORIGIN: 'https://api.molecule.dev',
|
|
46
|
+
WEB_ORIGIN: 'https://assemble.molecule.dev',
|
|
47
|
+
},
|
|
48
|
+
'test': {
|
|
49
|
+
NODE_ENV: 'test',
|
|
50
|
+
LOG_LEVEL: 'silent',
|
|
51
|
+
API_ORIGIN: 'http://localhost:4000',
|
|
52
|
+
WEB_ORIGIN: 'http://localhost:3000',
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (!process.env.NODE_ENV) {
|
|
57
|
+
process.env.NODE_ENV = `production`
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
for (const key in defaultEnv) {
|
|
61
|
+
process.env[key] = defaultEnv[key]
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Sets the variables specified within each environment within `.env-cmdrc.json`.
|
|
66
|
+
*/
|
|
67
|
+
export const setVariables = (environments: string[] = [ process.env.NODE_ENV || `production` ]) => {
|
|
68
|
+
try {
|
|
69
|
+
const envCmdrcPath = path.join(__dirname, '../.env-cmdrc.json')
|
|
70
|
+
const envCmdrc = fs.existsSync(envCmdrcPath)
|
|
71
|
+
? JSON.parse(fs.readFileSync(envCmdrcPath, 'utf8'))
|
|
72
|
+
: defaultEnvCmdrc
|
|
73
|
+
|
|
74
|
+
for (const environment of environments) {
|
|
75
|
+
const variables = envCmdrc[environment]
|
|
76
|
+
|
|
77
|
+
if (variables) {
|
|
78
|
+
Object.assign(process.env, variables)
|
|
79
|
+
} else {
|
|
80
|
+
console.warn(`Environment "${environment}" not found within .env-cmdrc.`)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
} catch (error) {
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Extend the environment variables using `.env-cmdrc.json`.
|
|
88
|
+
setVariables()
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Molecule.dev command line tools.
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import './environment.js'
|
|
10
|
+
import { program } from 'commander'
|
|
11
|
+
import * as commands from './commands/index.js'
|
|
12
|
+
|
|
13
|
+
export * as API from './API/index.js'
|
|
14
|
+
export * as commands from './commands/index.js'
|
|
15
|
+
export * as utilities from './utilities/index.js'
|
|
16
|
+
|
|
17
|
+
export * from './logger.js'
|
|
18
|
+
export * from './pkg.js'
|
|
19
|
+
export * from './repoConfig.js'
|
|
20
|
+
export * from './userConfig.js'
|
|
21
|
+
|
|
22
|
+
export * as types from './types/index.js'
|
|
23
|
+
|
|
24
|
+
for (const commandKey in commands) {
|
|
25
|
+
if (typeof commands[commandKey] === `function`) {
|
|
26
|
+
commands[commandKey](program)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
program.parse()
|
package/src/logger.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The logger, using `loglevel`.
|
|
3
|
+
*
|
|
4
|
+
* @see https://www.npmjs.com/package/loglevel
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import logger from 'loglevel'
|
|
10
|
+
|
|
11
|
+
declare global {
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
13
|
+
namespace NodeJS {
|
|
14
|
+
export interface ProcessEnv {
|
|
15
|
+
/**
|
|
16
|
+
* The log level.
|
|
17
|
+
*
|
|
18
|
+
* @default warn
|
|
19
|
+
*/
|
|
20
|
+
LOG_LEVEL?: `trace` | `debug` | `info` | `warn` | `error` | `silent`
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (process.env.LOG_LEVEL) {
|
|
26
|
+
logger.setLevel(process.env.LOG_LEVEL)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export { logger }
|
package/src/pkg.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import { fileURLToPath } from 'url'
|
|
4
|
+
|
|
5
|
+
const __dirname = fileURLToPath(path.dirname(import.meta.url))
|
|
6
|
+
|
|
7
|
+
export const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, `../package.json`), `utf8`)) as {
|
|
8
|
+
name: string
|
|
9
|
+
description: string
|
|
10
|
+
version: string
|
|
11
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global type definitions.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
declare global {
|
|
8
|
+
/**
|
|
9
|
+
* Useful when specifying that some type is a JSON value.
|
|
10
|
+
*/
|
|
11
|
+
export type JSONValue = string | number | boolean | JSONObject | JSONArray | null | undefined
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Useful when specifying that some type is a JSON object.
|
|
15
|
+
*/
|
|
16
|
+
export interface JSONObject {
|
|
17
|
+
[key: string]: JSONValue
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Useful when specifying that some type is a JSON array.
|
|
22
|
+
*/
|
|
23
|
+
export type JSONArray = Array<JSONValue>
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export {}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types used throughout `mlcl`.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as userTypes from '../API/resource/user/types.js'
|
|
8
|
+
|
|
9
|
+
export * as global from './global.js'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Molecule user configuration.
|
|
13
|
+
*
|
|
14
|
+
* Mostly used for authenticating with the Molecule.dev API.
|
|
15
|
+
*
|
|
16
|
+
* We'll be adding some really useful functionality surrounding this in the future.
|
|
17
|
+
*/
|
|
18
|
+
export interface UserConfig {
|
|
19
|
+
/**
|
|
20
|
+
* Stored authorization headers used for talking to the Molecule.dev API.
|
|
21
|
+
*/
|
|
22
|
+
authorizationHeader?: string
|
|
23
|
+
/**
|
|
24
|
+
* Remember the user's device.
|
|
25
|
+
*/
|
|
26
|
+
userIdsToDeviceIds?: { [userId: string]: string }
|
|
27
|
+
/**
|
|
28
|
+
* The current user's properties.
|
|
29
|
+
*/
|
|
30
|
+
user?: userTypes.Props
|
|
31
|
+
/**
|
|
32
|
+
* This will be asynchronously set to the latest `mlcl` version number if available
|
|
33
|
+
* on the NPM registry. A message will be shown to the user, suggesting the update.
|
|
34
|
+
*/
|
|
35
|
+
newVersion?: string
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Molecule repository configuration.
|
|
40
|
+
*
|
|
41
|
+
* We'll be adding some really useful functionality surrounding this in the future.
|
|
42
|
+
*/
|
|
43
|
+
export interface RepoConfig {
|
|
44
|
+
id: string
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Git commit information.
|
|
49
|
+
*/
|
|
50
|
+
export interface Commit {
|
|
51
|
+
hash: string
|
|
52
|
+
subject?: string
|
|
53
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
declare namespace NodeJS {
|
|
2
|
+
export interface ProcessEnv {
|
|
3
|
+
/**
|
|
4
|
+
* The current environment.
|
|
5
|
+
*/
|
|
6
|
+
NODE_ENV?: `development` | `production` | `test`
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A unique identifier for the app.
|
|
10
|
+
*
|
|
11
|
+
* @default mlcl
|
|
12
|
+
*/
|
|
13
|
+
APP_ID?: string
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The name of the app, typically as specified within `package.json`.
|
|
17
|
+
*
|
|
18
|
+
* @default $npm_package_name
|
|
19
|
+
*/
|
|
20
|
+
APP_NAME?: string
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The version number of the app, typically as specified within `package.json`.
|
|
24
|
+
*
|
|
25
|
+
* @default $npm_package_version
|
|
26
|
+
*/
|
|
27
|
+
APP_VERSION?: string
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The available app platforms.
|
|
31
|
+
*/
|
|
32
|
+
APP_PLATFORM?: undefined
|
|
33
|
+
| `android`
|
|
34
|
+
| `ios`
|
|
35
|
+
| `windows`
|
|
36
|
+
| `mac`
|
|
37
|
+
| `linux`
|
|
38
|
+
| `cli`
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The API's origin.
|
|
42
|
+
*
|
|
43
|
+
* @example https://api.molecule.dev
|
|
44
|
+
* @example http://localhost:4000
|
|
45
|
+
*/
|
|
46
|
+
API_ORIGIN?: string
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The web app's origin.
|
|
50
|
+
*
|
|
51
|
+
* @example https://app.molecule.dev
|
|
52
|
+
* @example http://localhost:3000
|
|
53
|
+
*/
|
|
54
|
+
WEB_ORIGIN?: string
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { getErrorMessage } from '../getErrorMessage.js'
|
|
2
|
+
|
|
3
|
+
it(`returns a better "timed out" message`, () => {
|
|
4
|
+
expect(getErrorMessage({ code: `ETIMEDOUT` })).toBe(`Timed out`)
|
|
5
|
+
})
|
|
6
|
+
|
|
7
|
+
it(`returns a better "connection aborted" message`, () => {
|
|
8
|
+
expect(getErrorMessage({ code: `ECONNABORTED` })).toBe(`Connection aborted`)
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
it(`returns response data's error message`, () => {
|
|
12
|
+
expect(getErrorMessage({
|
|
13
|
+
response: {
|
|
14
|
+
data: {
|
|
15
|
+
error: `Username is required.`
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
})).toBe(`Username is required.`)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
it(`returns error message`, () => {
|
|
22
|
+
expect(getErrorMessage(new Error(`Unexpected token`))).toBe(`Unexpected token`)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it(`returns the error if already a string`, () => {
|
|
26
|
+
expect(getErrorMessage(`Unexpected token`)).toBe(`Unexpected token`)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it(`returns null if no error`, () => {
|
|
30
|
+
expect(getErrorMessage()).toBe(null)
|
|
31
|
+
expect(getErrorMessage(null)).toBe(null)
|
|
32
|
+
})
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { timeAgo } from '../timeAgo.js'
|
|
2
|
+
|
|
3
|
+
const MINUTE = 60000 + 1
|
|
4
|
+
const HOUR = 3600000 + 1
|
|
5
|
+
const DAY = 86400000 + 1
|
|
6
|
+
const WEEK = 604800000 + 1
|
|
7
|
+
const YEAR = 31557600000 + 1
|
|
8
|
+
|
|
9
|
+
it(`returns "just now"`, () => {
|
|
10
|
+
expect(timeAgo(new Date().getTime())).toBe(`just now`)
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
it(`returns "minute(s)"`, () => {
|
|
14
|
+
expect(timeAgo(new Date().getTime() - MINUTE)).toBe(`1 minute ago`)
|
|
15
|
+
expect(timeAgo(new Date().getTime() - MINUTE*2)).toBe(`2 minutes ago`)
|
|
16
|
+
expect(timeAgo(new Date().getTime() - MINUTE, true)).toBe(`1m ago`)
|
|
17
|
+
expect(timeAgo(new Date().getTime() - MINUTE*2, true)).toBe(`2m ago`)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it(`returns "hour(s)"`, () => {
|
|
21
|
+
expect(timeAgo(new Date().getTime() - HOUR)).toBe(`1 hour ago`)
|
|
22
|
+
expect(timeAgo(new Date().getTime() - HOUR*2)).toBe(`2 hours ago`)
|
|
23
|
+
expect(timeAgo(new Date().getTime() - HOUR, true)).toBe(`1h ago`)
|
|
24
|
+
expect(timeAgo(new Date().getTime() - HOUR*2, true)).toBe(`2h ago`)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it(`returns "day(s)"`, () => {
|
|
28
|
+
expect(timeAgo(new Date().getTime() - DAY)).toBe(`1 day ago`)
|
|
29
|
+
expect(timeAgo(new Date().getTime() - DAY*2)).toBe(`2 days ago`)
|
|
30
|
+
expect(timeAgo(new Date().getTime() - DAY, true)).toBe(`1d ago`)
|
|
31
|
+
expect(timeAgo(new Date().getTime() - DAY*2, true)).toBe(`2d ago`)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it(`returns "week(s)"`, () => {
|
|
35
|
+
expect(timeAgo(new Date().getTime() - WEEK)).toBe(`1 week ago`)
|
|
36
|
+
expect(timeAgo(new Date().getTime() - WEEK*2)).toBe(`2 weeks ago`)
|
|
37
|
+
expect(timeAgo(new Date().getTime() - WEEK, true)).toBe(`1w ago`)
|
|
38
|
+
expect(timeAgo(new Date().getTime() - WEEK*2, true)).toBe(`2w ago`)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it(`returns "year(s)"`, () => {
|
|
42
|
+
expect(timeAgo(new Date().getTime() - YEAR)).toBe(`1 year ago`)
|
|
43
|
+
expect(timeAgo(new Date().getTime() - YEAR*2)).toBe(`2 years ago`)
|
|
44
|
+
expect(timeAgo(new Date().getTime() - YEAR, true)).toBe(`1y ago`)
|
|
45
|
+
expect(timeAgo(new Date().getTime() - YEAR*2, true)).toBe(`2y ago`)
|
|
46
|
+
})
|
|
@@ -0,0 +1,31 @@
|
|
|
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
|
+
|
|
8
|
+
export const checkVersion = async () => {
|
|
9
|
+
if (userConfig.newVersion) {
|
|
10
|
+
if (semver.gt(userConfig.newVersion, pkg.version)) {
|
|
11
|
+
logger.info(`A new version (${userConfig.newVersion}) of \`mlcl\` is available.`)
|
|
12
|
+
logger.info(`You are currently on version ${pkg.version}.`)
|
|
13
|
+
} else {
|
|
14
|
+
delete userConfig.newVersion
|
|
15
|
+
writeUserConfig()
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
const { version } = (await axios.get(`https://registry.npmjs.org/mlcl/latest`)).data
|
|
21
|
+
|
|
22
|
+
if (version && semver.gt(version, pkg.version)) {
|
|
23
|
+
userConfig.newVersion = version
|
|
24
|
+
writeUserConfig()
|
|
25
|
+
}
|
|
26
|
+
} catch (error) {
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Check every time `mlcl` is run.
|
|
31
|
+
checkVersion()
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type VariableError = null | string | {
|
|
2
|
+
code?: string | number
|
|
3
|
+
message?: string
|
|
4
|
+
response?: {
|
|
5
|
+
statusText?: string
|
|
6
|
+
data?: {
|
|
7
|
+
error?: string
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Attempts to return a human readable message based on some `Error`.
|
|
14
|
+
*/
|
|
15
|
+
export const getErrorMessage = (error?: VariableError): string | null => {
|
|
16
|
+
if (!error) {
|
|
17
|
+
return null
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (typeof error === `string`) {
|
|
21
|
+
return error
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
({ ETIMEDOUT: `Timed out`, ECONNABORTED: `Connection aborted` })[error.code || -1]
|
|
26
|
+
|| error.response?.data?.error
|
|
27
|
+
|| error.message
|
|
28
|
+
|| null
|
|
29
|
+
)
|
|
30
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Various utilities used throughout the application.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export * from './checkVersion.js'
|
|
8
|
+
export * from './getErrorMessage.js'
|
|
9
|
+
export * from './readRepoConfig.js'
|
|
10
|
+
export * from './readUserConfig.js'
|
|
11
|
+
export * from './synchronizeUserConfig.js'
|
|
12
|
+
export * from './timeAgo.js'
|
|
13
|
+
export * from './writeRepoConfig.js'
|
|
14
|
+
export * from './writeUserConfig.js'
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import { RepoConfig } from '../types/index.js'
|
|
4
|
+
import { getRepoRootPathSync } from '../commands/utilities/getRepoRootPathSync.js'
|
|
5
|
+
import { logger } from '../logger.js'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Reads and returns the current repo's config.
|
|
9
|
+
*/
|
|
10
|
+
export const readRepoConfig = (repoConfigPath = path.join(getRepoRootPathSync(), `.mlclrc.json`)) => {
|
|
11
|
+
try {
|
|
12
|
+
if (fs.existsSync(repoConfigPath)) {
|
|
13
|
+
const config = JSON.parse(fs.readFileSync(repoConfigPath, `utf8`))
|
|
14
|
+
|
|
15
|
+
return config as RepoConfig
|
|
16
|
+
}
|
|
17
|
+
} catch (error) {
|
|
18
|
+
logger.error(error)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return {} as RepoConfig
|
|
22
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import os from 'os'
|
|
2
|
+
import fs from 'fs'
|
|
3
|
+
import path from 'path'
|
|
4
|
+
import { UserConfig } from '../types/index.js'
|
|
5
|
+
import { logger } from '../logger.js'
|
|
6
|
+
|
|
7
|
+
const homeDir = os.homedir()
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Reads and returns the current user's config.
|
|
11
|
+
*/
|
|
12
|
+
export const readUserConfig = (userConfigPath = path.join(homeDir, `.mlclrc.json`)) => {
|
|
13
|
+
try {
|
|
14
|
+
if (fs.existsSync(userConfigPath)) {
|
|
15
|
+
const config = JSON.parse(fs.readFileSync(userConfigPath, `utf8`))
|
|
16
|
+
|
|
17
|
+
return config as UserConfig
|
|
18
|
+
}
|
|
19
|
+
} catch (error) {
|
|
20
|
+
logger.error(error)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return {} as UserConfig
|
|
24
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { read as readUser } from '../API/resource/user/index.js'
|
|
2
|
+
import { userConfig } from '../userConfig.js'
|
|
3
|
+
import { writeUserConfig } from '../utilities/writeUserConfig.js'
|
|
4
|
+
import { logger } from '../logger.js'
|
|
5
|
+
import { getErrorMessage } from '../utilities/getErrorMessage.js'
|
|
6
|
+
|
|
7
|
+
export const synchronizeUserConfig = async () => {
|
|
8
|
+
if (userConfig.user) {
|
|
9
|
+
try {
|
|
10
|
+
const { props: user } = (await readUser(userConfig.user.id)).data
|
|
11
|
+
|
|
12
|
+
if (!user) {
|
|
13
|
+
throw new Error(`No user was returned by the Molecule.dev API.`)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (userConfig.user?.id === user.id) {
|
|
17
|
+
userConfig.user = user
|
|
18
|
+
writeUserConfig()
|
|
19
|
+
} else {
|
|
20
|
+
logger.warn(`The Molecule.dev API returned an unexpected response when synchronizing the user.`)
|
|
21
|
+
}
|
|
22
|
+
} catch (error) {
|
|
23
|
+
logger.warn(`Error fetching user: ${getErrorMessage(error) || `Unknown error`}`)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const MINUTE = 60000
|
|
2
|
+
const HOUR = 3600000
|
|
3
|
+
const DAY = 86400000
|
|
4
|
+
const WEEK = 604800000
|
|
5
|
+
const YEAR = 31557600000
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Returns how long ago some time (date) was.
|
|
9
|
+
*/
|
|
10
|
+
export const timeAgo = (time: number | string, abbreviate?: boolean): string => {
|
|
11
|
+
if (typeof time !== `number`) {
|
|
12
|
+
try {
|
|
13
|
+
time = new Date(time).getTime()
|
|
14
|
+
} catch (error) {
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const diff = Math.max(0, Date.now() - Number(time))
|
|
19
|
+
let count = 0
|
|
20
|
+
|
|
21
|
+
if (diff < MINUTE) {
|
|
22
|
+
return `just now`
|
|
23
|
+
} else if (diff < HOUR) {
|
|
24
|
+
count = Math.round(diff / MINUTE)
|
|
25
|
+
return `${count}${abbreviate ? `m` : ` minute${count === 1 ? `` : `s`}`} ago`
|
|
26
|
+
} else if (diff < DAY) {
|
|
27
|
+
count = Math.round(diff / HOUR)
|
|
28
|
+
return `${count}${abbreviate ? `h` : ` hour${count === 1 ? `` : `s`}`} ago`
|
|
29
|
+
} else if (diff < WEEK) {
|
|
30
|
+
count = Math.round(diff / DAY)
|
|
31
|
+
return `${count}${abbreviate ? `d` : ` day${count === 1 ? `` : `s`}`} ago`
|
|
32
|
+
} else if (diff < YEAR) {
|
|
33
|
+
count = Math.round(diff / WEEK)
|
|
34
|
+
return `${count}${abbreviate ? `w` : ` week${count === 1 ? `` : `s`}`} ago`
|
|
35
|
+
} else {
|
|
36
|
+
count = Math.round(diff / YEAR)
|
|
37
|
+
return `${count}${abbreviate ? `y` : ` year${count === 1 ? `` : `s`}`} ago`
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { userConfig } from '../userConfig.js'
|
|
2
|
+
import { synchronizeUserConfig } from './synchronizeUserConfig.js'
|
|
3
|
+
import * as API from '../API/index.js'
|
|
4
|
+
import { logger } from '../logger.js'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Ensures the user is logged in before continuing.
|
|
8
|
+
*
|
|
9
|
+
* If the user is not logged in, automatically runs the `login` command.
|
|
10
|
+
*/
|
|
11
|
+
export const userLoggedIn = async () => {
|
|
12
|
+
await synchronizeUserConfig()
|
|
13
|
+
|
|
14
|
+
if (userConfig?.user?.id) {
|
|
15
|
+
logger.info(`Hello, ${userConfig.user.name || userConfig.user.username}!`)
|
|
16
|
+
} else {
|
|
17
|
+
logger.info(`Not logged into \`mlcl\`. Logging in...`)
|
|
18
|
+
|
|
19
|
+
await API.resource.user.utilities.logIn()
|
|
20
|
+
|
|
21
|
+
if (!userConfig.user?.id) {
|
|
22
|
+
logger.warn(`Not logged in. Run \`mlcl login\` first.`)
|
|
23
|
+
return null
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return userConfig.user
|
|
28
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import { repoConfig as currentRepoConfig } from '../repoConfig.js'
|
|
4
|
+
import { getRepoRootPathSync } from '../commands/utilities/getRepoRootPathSync.js'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Writes the current repo's config to disk.
|
|
8
|
+
*/
|
|
9
|
+
export const writeRepoConfig = (repoConfig = currentRepoConfig, repoConfigPath = path.join(getRepoRootPathSync(), `.mlclrc.json`)) => {
|
|
10
|
+
fs.writeFileSync(repoConfigPath, JSON.stringify(repoConfig, null, 2))
|
|
11
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import os from 'os'
|
|
2
|
+
import fs from 'fs'
|
|
3
|
+
import path from 'path'
|
|
4
|
+
import { userConfig as currentUserConfig } from '../userConfig.js'
|
|
5
|
+
|
|
6
|
+
const homeDir = os.homedir()
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Writes the current user's config to disk.
|
|
10
|
+
*/
|
|
11
|
+
export const writeUserConfig = (userConfig = currentUserConfig, userConfigPath = path.join(homeDir, `.mlclrc.json`)) => {
|
|
12
|
+
fs.writeFileSync(userConfigPath, JSON.stringify(userConfig, null, 2))
|
|
13
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"rootDir": "./src",
|
|
4
|
+
"outDir": "./build",
|
|
5
|
+
"target": "ES2020",
|
|
6
|
+
"lib": [
|
|
7
|
+
"ESNext"
|
|
8
|
+
],
|
|
9
|
+
"module": "ESNext",
|
|
10
|
+
"moduleResolution": "Node",
|
|
11
|
+
"esModuleInterop": true,
|
|
12
|
+
"strictNullChecks": true
|
|
13
|
+
},
|
|
14
|
+
"include": [
|
|
15
|
+
"./src"
|
|
16
|
+
],
|
|
17
|
+
"exclude": [
|
|
18
|
+
"./node_modules",
|
|
19
|
+
"./build",
|
|
20
|
+
"./docs"
|
|
21
|
+
],
|
|
22
|
+
"ts-node": {
|
|
23
|
+
"files": true
|
|
24
|
+
}
|
|
25
|
+
}
|