@tremho/mist-lift 1.1.4 → 1.1.5
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/LICENSE +21 -21
- package/README.md +70 -66
- package/build/QSTest/functions/IntegrationTest/src/main.js +1 -1
- package/build/src/commands/builtin/ApiDocMaker.js +0 -1
- package/build/src/commands/builtin/ApiDocMaker.js.map +1 -1
- package/build/src/commands/doctor.js +12 -1
- package/build/src/commands/doctor.js.map +1 -1
- package/build/src/lib/LiftVersion.js +1 -1
- package/build/src/lib/LiftVersion.js.map +1 -1
- package/package.json +79 -79
- package/src/commands/actions/initQuestions.ts +133 -133
- package/src/commands/actions/setupPackageJson.ts +32 -32
- package/src/commands/build.ts +173 -173
- package/src/commands/builtin/ApiDocMaker.ts +105 -106
- package/src/commands/builtin/BuiltInHandler.ts +47 -47
- package/src/commands/builtin/DeployBuiltInZip.ts +25 -25
- package/src/commands/builtin/StageWebrootZip.ts +36 -36
- package/src/commands/create.ts +52 -52
- package/src/commands/deploy.ts +161 -161
- package/src/commands/doctor.ts +118 -107
- package/src/commands/help.ts +178 -178
- package/src/commands/info.ts +42 -42
- package/src/commands/init.ts +61 -61
- package/src/commands/package.ts +234 -234
- package/src/commands/publish.ts +330 -330
- package/src/commands/settings.ts +73 -73
- package/src/commands/start.ts +43 -43
- package/src/commands/test.ts +37 -37
- package/src/commands/user.ts +20 -20
- package/src/expressRoutes/all.ts +99 -99
- package/src/expressRoutes/api.ts +22 -22
- package/src/expressRoutes/functionBinder.ts +155 -155
- package/src/integration-tests/quickstart-scenario.test.ts +76 -76
- package/src/lib/CaseUtils.ts +63 -63
- package/src/lib/DirectoryUtils.ts +34 -34
- package/src/lib/LiftConfig.ts +74 -74
- package/src/lib/LiftVersion.ts +87 -87
- package/src/lib/Tests/fileCompare.test.ts +35 -35
- package/src/lib/askQuestion.ts +17 -17
- package/src/lib/executeCommand.ts +45 -45
- package/src/lib/fileCompare.ts +55 -55
- package/src/lib/openAPI/ApiBuildCollector.ts +47 -47
- package/src/lib/openAPI/WebrootFileSupport.ts +19 -19
- package/src/lib/openAPI/openApiConstruction.ts +196 -196
- package/src/lib/pathResolve.ts +26 -26
- package/src/lib/utils.ts +43 -43
- package/src/lift.ts +87 -87
- package/templateData/function-definition-template +20 -20
- package/templateData/function-local-ts +16 -16
- package/templateData/function-main-ts +16 -16
- package/templateData/function-runmain-mjs +6 -6
- package/templateData/function-test-template +11 -11
- package/templateData/swagger-ui-bundle.js +2 -2
- package/templateData/swagger-ui-standalone-preset.js +2 -2
- package/templateData/swagger-ui.css +2 -2
- package/tsconfig.json +28 -28
- package/build/commands/builtin/prebuilt-zips/API.zip +0 -0
- package/build/commands/builtin/prebuilt-zips/FileServe.zip +0 -0
- package/build/commands/builtin/prebuilt-zips/Webroot.zip +0 -0
package/src/lib/LiftConfig.ts
CHANGED
|
@@ -1,74 +1,74 @@
|
|
|
1
|
-
// configuration for setting cloud provider credentials
|
|
2
|
-
// may expand later for other MistLift settings/preferences
|
|
3
|
-
|
|
4
|
-
import path from 'path'
|
|
5
|
-
import fs from 'fs'
|
|
6
|
-
import { fromIni } from '@aws-sdk/credential-providers'
|
|
7
|
-
|
|
8
|
-
let sLiftConfigLoaded: LiftConfig | null = null
|
|
9
|
-
|
|
10
|
-
// Defines the structure of the .mistlft json file
|
|
11
|
-
// All relevant configuration for the cloud host goes here
|
|
12
|
-
export class LiftConfig {
|
|
13
|
-
public cloudHost: string = 'AWS' // all we support now
|
|
14
|
-
public awsIniProfile?: string
|
|
15
|
-
public awsPreferredRegion?: string
|
|
16
|
-
public awsNodeRuntime?: RuntimeType
|
|
17
|
-
public awsServiceRoleARN?: string
|
|
18
|
-
}
|
|
19
|
-
export type RuntimeType = 'nodejs' | 'nodejs4.3' | 'nodejs6.10' | 'nodejs8.10' | 'nodejs10.x' | 'nodejs12.x' | 'nodejs14.x' | 'nodejs16.x' | 'java8' | 'java8.al2' | 'java11' | 'python2.7' | 'python3.6' | 'python3.7' | 'python3.8' | 'python3.9' | 'dotnetcore1.0' | 'dotnetcore2.0' | 'dotnetcore2.1' | 'dotnetcore3.1' | 'dotnet6' | 'dotnet8' | 'nodejs4.3-edge' | 'go1.x' | 'ruby2.5' | 'ruby2.7' | 'provided' | 'provided.al2' | 'nodejs18.x' | 'python3.10' | 'java17' | 'ruby3.2' | 'ruby3.3' | 'python3.11' | 'nodejs20.x' | 'provided.al2023' | 'python3.12' | 'java21'
|
|
20
|
-
|
|
21
|
-
// Available for general use because, why not?
|
|
22
|
-
export function getUserHome (): string {
|
|
23
|
-
return process.env.HOME ?? process.env.HOMEPATH ?? process.env.USERPROFILE ?? '~'
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function LoadLiftConfig (): LiftConfig | null {
|
|
27
|
-
if (sLiftConfigLoaded == null) {
|
|
28
|
-
const mistlift = path.join(getUserHome(), '.mistlift')
|
|
29
|
-
let configJson = '{}'
|
|
30
|
-
if (fs.existsSync(mistlift)) {
|
|
31
|
-
try {
|
|
32
|
-
configJson = fs.readFileSync(mistlift).toString()
|
|
33
|
-
sLiftConfigLoaded = JSON.parse(configJson)
|
|
34
|
-
} catch (e: any) {
|
|
35
|
-
//
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
return sLiftConfigLoaded
|
|
40
|
-
}
|
|
41
|
-
export function resetLiftConfig (): void {
|
|
42
|
-
sLiftConfigLoaded = null
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export function areSettingsAvailable (): boolean {
|
|
46
|
-
const mistlift = path.join(getUserHome(), '.mistlift')
|
|
47
|
-
return fs.existsSync(mistlift)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export function getSettings (): LiftConfig {
|
|
51
|
-
if (sLiftConfigLoaded == null) LoadLiftConfig()
|
|
52
|
-
return sLiftConfigLoaded as LiftConfig
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Return the credentials required for AWS based upon our config options.
|
|
57
|
-
*
|
|
58
|
-
* We will use the standard .aws config ini file, looked up by profile or default
|
|
59
|
-
* Prior attempts to have it do more than this failed, and resulted in a default profile choice anyway.
|
|
60
|
-
*/
|
|
61
|
-
export function getAWSCredentials (): any {
|
|
62
|
-
let config = LoadLiftConfig()
|
|
63
|
-
if (config == null) {
|
|
64
|
-
// console.error("No .mistlift configuration found - using AWS default profile");
|
|
65
|
-
config = { cloudHost: 'AWS', awsIniProfile: 'default' }
|
|
66
|
-
}
|
|
67
|
-
if (config.cloudHost?.toUpperCase() !== 'AWS') {
|
|
68
|
-
throw Error('HostType Not Supported')
|
|
69
|
-
}
|
|
70
|
-
let credentials = {}
|
|
71
|
-
const profile = config.awsIniProfile ?? 'default'
|
|
72
|
-
credentials = fromIni({ profile })
|
|
73
|
-
return credentials
|
|
74
|
-
}
|
|
1
|
+
// configuration for setting cloud provider credentials
|
|
2
|
+
// may expand later for other MistLift settings/preferences
|
|
3
|
+
|
|
4
|
+
import path from 'path'
|
|
5
|
+
import fs from 'fs'
|
|
6
|
+
import { fromIni } from '@aws-sdk/credential-providers'
|
|
7
|
+
|
|
8
|
+
let sLiftConfigLoaded: LiftConfig | null = null
|
|
9
|
+
|
|
10
|
+
// Defines the structure of the .mistlft json file
|
|
11
|
+
// All relevant configuration for the cloud host goes here
|
|
12
|
+
export class LiftConfig {
|
|
13
|
+
public cloudHost: string = 'AWS' // all we support now
|
|
14
|
+
public awsIniProfile?: string
|
|
15
|
+
public awsPreferredRegion?: string
|
|
16
|
+
public awsNodeRuntime?: RuntimeType
|
|
17
|
+
public awsServiceRoleARN?: string
|
|
18
|
+
}
|
|
19
|
+
export type RuntimeType = 'nodejs' | 'nodejs4.3' | 'nodejs6.10' | 'nodejs8.10' | 'nodejs10.x' | 'nodejs12.x' | 'nodejs14.x' | 'nodejs16.x' | 'java8' | 'java8.al2' | 'java11' | 'python2.7' | 'python3.6' | 'python3.7' | 'python3.8' | 'python3.9' | 'dotnetcore1.0' | 'dotnetcore2.0' | 'dotnetcore2.1' | 'dotnetcore3.1' | 'dotnet6' | 'dotnet8' | 'nodejs4.3-edge' | 'go1.x' | 'ruby2.5' | 'ruby2.7' | 'provided' | 'provided.al2' | 'nodejs18.x' | 'python3.10' | 'java17' | 'ruby3.2' | 'ruby3.3' | 'python3.11' | 'nodejs20.x' | 'provided.al2023' | 'python3.12' | 'java21'
|
|
20
|
+
|
|
21
|
+
// Available for general use because, why not?
|
|
22
|
+
export function getUserHome (): string {
|
|
23
|
+
return process.env.HOME ?? process.env.HOMEPATH ?? process.env.USERPROFILE ?? '~'
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function LoadLiftConfig (): LiftConfig | null {
|
|
27
|
+
if (sLiftConfigLoaded == null) {
|
|
28
|
+
const mistlift = path.join(getUserHome(), '.mistlift')
|
|
29
|
+
let configJson = '{}'
|
|
30
|
+
if (fs.existsSync(mistlift)) {
|
|
31
|
+
try {
|
|
32
|
+
configJson = fs.readFileSync(mistlift).toString()
|
|
33
|
+
sLiftConfigLoaded = JSON.parse(configJson)
|
|
34
|
+
} catch (e: any) {
|
|
35
|
+
//
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return sLiftConfigLoaded
|
|
40
|
+
}
|
|
41
|
+
export function resetLiftConfig (): void {
|
|
42
|
+
sLiftConfigLoaded = null
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function areSettingsAvailable (): boolean {
|
|
46
|
+
const mistlift = path.join(getUserHome(), '.mistlift')
|
|
47
|
+
return fs.existsSync(mistlift)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function getSettings (): LiftConfig {
|
|
51
|
+
if (sLiftConfigLoaded == null) LoadLiftConfig()
|
|
52
|
+
return sLiftConfigLoaded as LiftConfig
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Return the credentials required for AWS based upon our config options.
|
|
57
|
+
*
|
|
58
|
+
* We will use the standard .aws config ini file, looked up by profile or default
|
|
59
|
+
* Prior attempts to have it do more than this failed, and resulted in a default profile choice anyway.
|
|
60
|
+
*/
|
|
61
|
+
export function getAWSCredentials (): any {
|
|
62
|
+
let config = LoadLiftConfig()
|
|
63
|
+
if (config == null) {
|
|
64
|
+
// console.error("No .mistlift configuration found - using AWS default profile");
|
|
65
|
+
config = { cloudHost: 'AWS', awsIniProfile: 'default' }
|
|
66
|
+
}
|
|
67
|
+
if (config.cloudHost?.toUpperCase() !== 'AWS') {
|
|
68
|
+
throw Error('HostType Not Supported')
|
|
69
|
+
}
|
|
70
|
+
let credentials = {}
|
|
71
|
+
const profile = config.awsIniProfile ?? 'default'
|
|
72
|
+
credentials = fromIni({ profile })
|
|
73
|
+
return credentials
|
|
74
|
+
}
|
package/src/lib/LiftVersion.ts
CHANGED
|
@@ -1,87 +1,87 @@
|
|
|
1
|
-
|
|
2
|
-
import * as path from 'path'
|
|
3
|
-
import * as fs from 'fs'
|
|
4
|
-
import { resolvePaths } from './pathResolve'
|
|
5
|
-
|
|
6
|
-
export class VersionInfo {
|
|
7
|
-
public major: number = 0
|
|
8
|
-
public minor: number = 0
|
|
9
|
-
public revision: number = 0
|
|
10
|
-
public suffix: string = ''
|
|
11
|
-
|
|
12
|
-
constructor (vstr: string) {
|
|
13
|
-
this.parse(vstr)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
public toString = (): string => {
|
|
17
|
-
let sfx = ''
|
|
18
|
-
if (this.suffix !== '') sfx = '-' + this.suffix
|
|
19
|
-
return `${this.major}.${this.minor}.${this.revision}${sfx}`
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
public parse = (vstr: string): VersionInfo => {
|
|
23
|
-
const sn = vstr.indexOf('-')
|
|
24
|
-
let suffix = ''
|
|
25
|
-
if (sn !== -1) {
|
|
26
|
-
suffix = vstr.substring(sn + 1)
|
|
27
|
-
vstr = vstr.substring(0, sn)
|
|
28
|
-
}
|
|
29
|
-
const parts = vstr.split('.')
|
|
30
|
-
while (parts.length < 3) parts.push('0')
|
|
31
|
-
this.major = parseInt(parts[0])
|
|
32
|
-
this.minor = parseInt(parts[1])
|
|
33
|
-
this.revision = parseInt(parts[2])
|
|
34
|
-
if (!isFinite(this.major)) this.major = 0
|
|
35
|
-
if (!isFinite(this.minor)) this.minor = 0
|
|
36
|
-
if (!isFinite(this.revision)) this.revision = 0
|
|
37
|
-
this.suffix = suffix
|
|
38
|
-
return this
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
public equals (other: VersionInfo | string): boolean {
|
|
42
|
-
// Note: not really a valid SemVer comparison
|
|
43
|
-
if (typeof other === 'string') other = new VersionInfo(other)
|
|
44
|
-
return this.major === other.major &&
|
|
45
|
-
this.minor === other.minor &&
|
|
46
|
-
this.revision === other.revision
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
public isGreaterThan (other: VersionInfo | string): boolean {
|
|
50
|
-
// Note: not really a valid SemVer comparison
|
|
51
|
-
if (typeof other === 'string') other = new VersionInfo(other)
|
|
52
|
-
if (this.major > other.major) return true
|
|
53
|
-
if (this.major < other.major) return false
|
|
54
|
-
if (this.minor > other.minor) return true
|
|
55
|
-
if (this.minor < other.minor) return false
|
|
56
|
-
return (this.revision > other.revision)
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// read version from Lift's package.json
|
|
61
|
-
export function getLiftVersion (): VersionInfo {
|
|
62
|
-
const pkg = path.join(__dirname, '..', '..', 'package.json')
|
|
63
|
-
return readPackageVersion(pkg)
|
|
64
|
-
}
|
|
65
|
-
// read version from project's package.json
|
|
66
|
-
export function getProjectVersion (): VersionInfo {
|
|
67
|
-
const projectPaths = resolvePaths()
|
|
68
|
-
return readPackageVersion(projectPaths.packagePath)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export function getProjectName (): string {
|
|
72
|
-
const projectPaths = resolvePaths()
|
|
73
|
-
let pkgJson: { name?: string } = {}
|
|
74
|
-
try {
|
|
75
|
-
pkgJson = JSON.parse(fs.readFileSync(projectPaths.packagePath).toString())
|
|
76
|
-
} catch (e) {}
|
|
77
|
-
return pkgJson.name ?? ''
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function readPackageVersion (pkgPath: string): VersionInfo {
|
|
81
|
-
let pkgJson: { version?: string } = {}
|
|
82
|
-
try {
|
|
83
|
-
pkgJson = JSON.parse(fs.readFileSync(pkgPath).toString())
|
|
84
|
-
} catch (e) {}
|
|
85
|
-
|
|
86
|
-
return new VersionInfo(pkgJson.version ?? '')
|
|
87
|
-
}
|
|
1
|
+
|
|
2
|
+
import * as path from 'path'
|
|
3
|
+
import * as fs from 'fs'
|
|
4
|
+
import { resolvePaths } from './pathResolve'
|
|
5
|
+
|
|
6
|
+
export class VersionInfo {
|
|
7
|
+
public major: number = 0
|
|
8
|
+
public minor: number = 0
|
|
9
|
+
public revision: number = 0
|
|
10
|
+
public suffix: string = ''
|
|
11
|
+
|
|
12
|
+
constructor (vstr: string) {
|
|
13
|
+
this.parse(vstr)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
public toString = (): string => {
|
|
17
|
+
let sfx = ''
|
|
18
|
+
if (this.suffix !== '') sfx = '-' + this.suffix
|
|
19
|
+
return `${this.major}.${this.minor}.${this.revision}${sfx}`
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public parse = (vstr: string): VersionInfo => {
|
|
23
|
+
const sn = vstr.indexOf('-')
|
|
24
|
+
let suffix = ''
|
|
25
|
+
if (sn !== -1) {
|
|
26
|
+
suffix = vstr.substring(sn + 1)
|
|
27
|
+
vstr = vstr.substring(0, sn)
|
|
28
|
+
}
|
|
29
|
+
const parts = vstr.split('.')
|
|
30
|
+
while (parts.length < 3) parts.push('0')
|
|
31
|
+
this.major = parseInt(parts[0])
|
|
32
|
+
this.minor = parseInt(parts[1])
|
|
33
|
+
this.revision = parseInt(parts[2])
|
|
34
|
+
if (!isFinite(this.major)) this.major = 0
|
|
35
|
+
if (!isFinite(this.minor)) this.minor = 0
|
|
36
|
+
if (!isFinite(this.revision)) this.revision = 0
|
|
37
|
+
this.suffix = suffix
|
|
38
|
+
return this
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public equals (other: VersionInfo | string): boolean {
|
|
42
|
+
// Note: not really a valid SemVer comparison
|
|
43
|
+
if (typeof other === 'string') other = new VersionInfo(other)
|
|
44
|
+
return this.major === other.major &&
|
|
45
|
+
this.minor === other.minor &&
|
|
46
|
+
this.revision === other.revision
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public isGreaterThan (other: VersionInfo | string): boolean {
|
|
50
|
+
// Note: not really a valid SemVer comparison
|
|
51
|
+
if (typeof other === 'string') other = new VersionInfo(other)
|
|
52
|
+
if (this.major > other.major) return true
|
|
53
|
+
if (this.major < other.major) return false
|
|
54
|
+
if (this.minor > other.minor) return true
|
|
55
|
+
if (this.minor < other.minor) return false
|
|
56
|
+
return (this.revision > other.revision)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// read version from Lift's package.json
|
|
61
|
+
export function getLiftVersion (): VersionInfo {
|
|
62
|
+
const pkg = path.join(__dirname, '..', '..', '..', 'package.json')
|
|
63
|
+
return readPackageVersion(pkg)
|
|
64
|
+
}
|
|
65
|
+
// read version from project's package.json
|
|
66
|
+
export function getProjectVersion (): VersionInfo {
|
|
67
|
+
const projectPaths = resolvePaths()
|
|
68
|
+
return readPackageVersion(projectPaths.packagePath)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function getProjectName (): string {
|
|
72
|
+
const projectPaths = resolvePaths()
|
|
73
|
+
let pkgJson: { name?: string } = {}
|
|
74
|
+
try {
|
|
75
|
+
pkgJson = JSON.parse(fs.readFileSync(projectPaths.packagePath).toString())
|
|
76
|
+
} catch (e) {}
|
|
77
|
+
return pkgJson.name ?? ''
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function readPackageVersion (pkgPath: string): VersionInfo {
|
|
81
|
+
let pkgJson: { version?: string } = {}
|
|
82
|
+
try {
|
|
83
|
+
pkgJson = JSON.parse(fs.readFileSync(pkgPath).toString())
|
|
84
|
+
} catch (e) {}
|
|
85
|
+
|
|
86
|
+
return new VersionInfo(pkgJson.version ?? '')
|
|
87
|
+
}
|
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
|
|
2
|
-
/* eslint @typescript-eslint/no-floating-promises: "off" */
|
|
3
|
-
|
|
4
|
-
import Tap from 'tap'
|
|
5
|
-
|
|
6
|
-
import * as path from 'path'
|
|
7
|
-
import { isNewerFile } from '../fileCompare'
|
|
8
|
-
|
|
9
|
-
function test (t: any): void {
|
|
10
|
-
// ./dir1/file.1 551 < ./dir2/file.1 552
|
|
11
|
-
// ./dir1/file.2 553 > ./dir2/file.1 552
|
|
12
|
-
// ./dir1 553 > ./dir2 552
|
|
13
|
-
// .dir1 (.1) 552 < ./dir2 552
|
|
14
|
-
|
|
15
|
-
const dir1 = path.join(__dirname, 'dir1')
|
|
16
|
-
const dir2 = path.join(__dirname, 'dir2')
|
|
17
|
-
const dir1File1 = path.join(dir1, 'file.1')
|
|
18
|
-
const dir1File2 = path.join(dir1, 'file.2')
|
|
19
|
-
const dir2File1 = path.join(dir2, 'file.1')
|
|
20
|
-
|
|
21
|
-
let newer = isNewerFile(dir1File1, dir2File1)
|
|
22
|
-
t.equal(newer, false, './dir1/file.1 < ./dir2/file.1')
|
|
23
|
-
newer = isNewerFile(dir1File2, dir2File1)
|
|
24
|
-
t.equal(newer, true, './dir1/file.2 > ./dir2/file.1')
|
|
25
|
-
newer = isNewerFile(dir1, dir2)
|
|
26
|
-
t.ok(newer, 'dir1 > dir2')
|
|
27
|
-
newer = isNewerFile(dir1, dir2, '.1')
|
|
28
|
-
t.ok(!newer, './dir1 (.1) < ./dir2')
|
|
29
|
-
|
|
30
|
-
t.end()
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
Tap.test('IsNewer', t => {
|
|
34
|
-
test(t)
|
|
35
|
-
})
|
|
1
|
+
|
|
2
|
+
/* eslint @typescript-eslint/no-floating-promises: "off" */
|
|
3
|
+
|
|
4
|
+
import Tap from 'tap'
|
|
5
|
+
|
|
6
|
+
import * as path from 'path'
|
|
7
|
+
import { isNewerFile } from '../fileCompare'
|
|
8
|
+
|
|
9
|
+
function test (t: any): void {
|
|
10
|
+
// ./dir1/file.1 551 < ./dir2/file.1 552
|
|
11
|
+
// ./dir1/file.2 553 > ./dir2/file.1 552
|
|
12
|
+
// ./dir1 553 > ./dir2 552
|
|
13
|
+
// .dir1 (.1) 552 < ./dir2 552
|
|
14
|
+
|
|
15
|
+
const dir1 = path.join(__dirname, 'dir1')
|
|
16
|
+
const dir2 = path.join(__dirname, 'dir2')
|
|
17
|
+
const dir1File1 = path.join(dir1, 'file.1')
|
|
18
|
+
const dir1File2 = path.join(dir1, 'file.2')
|
|
19
|
+
const dir2File1 = path.join(dir2, 'file.1')
|
|
20
|
+
|
|
21
|
+
let newer = isNewerFile(dir1File1, dir2File1)
|
|
22
|
+
t.equal(newer, false, './dir1/file.1 < ./dir2/file.1')
|
|
23
|
+
newer = isNewerFile(dir1File2, dir2File1)
|
|
24
|
+
t.equal(newer, true, './dir1/file.2 > ./dir2/file.1')
|
|
25
|
+
newer = isNewerFile(dir1, dir2)
|
|
26
|
+
t.ok(newer, 'dir1 > dir2')
|
|
27
|
+
newer = isNewerFile(dir1, dir2, '.1')
|
|
28
|
+
t.ok(!newer, './dir1 (.1) < ./dir2')
|
|
29
|
+
|
|
30
|
+
t.end()
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
Tap.test('IsNewer', t => {
|
|
34
|
+
test(t)
|
|
35
|
+
})
|
package/src/lib/askQuestion.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
/** handles interaction for asking a question */
|
|
2
|
-
|
|
3
|
-
/* eslint @typescript-eslint/no-var-requires: "off" */
|
|
4
|
-
import * as ac from 'ansi-colors'
|
|
5
|
-
const readlineSync = require('readline-sync')
|
|
6
|
-
|
|
7
|
-
export function ask (
|
|
8
|
-
desc: string, // describes the context
|
|
9
|
-
query: string, // asks the actual question
|
|
10
|
-
def: string // default answer
|
|
11
|
-
|
|
12
|
-
): string { // answer provided
|
|
13
|
-
console.log(ac.dim.blue.italic(desc))
|
|
14
|
-
let answer = readlineSync.question(ac.bold.green(query) + ac.dim.grey(` [${def}] `) + '? ')
|
|
15
|
-
if (answer === '') answer = def
|
|
16
|
-
return answer
|
|
17
|
-
}
|
|
1
|
+
/** handles interaction for asking a question */
|
|
2
|
+
|
|
3
|
+
/* eslint @typescript-eslint/no-var-requires: "off" */
|
|
4
|
+
import * as ac from 'ansi-colors'
|
|
5
|
+
const readlineSync = require('readline-sync')
|
|
6
|
+
|
|
7
|
+
export function ask (
|
|
8
|
+
desc: string, // describes the context
|
|
9
|
+
query: string, // asks the actual question
|
|
10
|
+
def: string // default answer
|
|
11
|
+
|
|
12
|
+
): string { // answer provided
|
|
13
|
+
console.log(ac.dim.blue.italic(desc))
|
|
14
|
+
let answer = readlineSync.question(ac.bold.green(query) + ac.dim.grey(` [${def}] `) + '? ')
|
|
15
|
+
if (answer === '') answer = def
|
|
16
|
+
return answer
|
|
17
|
+
}
|
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
|
|
2
|
-
import { exec } from 'child_process'
|
|
3
|
-
|
|
4
|
-
interface StringObject {
|
|
5
|
-
toString: () => string
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export async function executeCommand (cmd: string, args: any[], cwd = '', consolePass = false, env: any = {}): Promise<any> {
|
|
9
|
-
const out = {
|
|
10
|
-
stdStr: '',
|
|
11
|
-
errStr: '',
|
|
12
|
-
retcode: 0
|
|
13
|
-
}
|
|
14
|
-
return await new Promise(resolve => {
|
|
15
|
-
const cmdstr = cmd + ' ' + args.join(' ')
|
|
16
|
-
// console.log('executing ', cmdstr, 'at', cwd)
|
|
17
|
-
const opts = {
|
|
18
|
-
cwd,
|
|
19
|
-
env: Object.assign(env, process.env)
|
|
20
|
-
}
|
|
21
|
-
const proc = exec(cmdstr, opts)
|
|
22
|
-
if (proc.stdout != null) {
|
|
23
|
-
proc.stdout.on('data', (data: StringObject) => {
|
|
24
|
-
out.stdStr += data.toString()
|
|
25
|
-
if (consolePass) process.stdout.write(data.toString())
|
|
26
|
-
})
|
|
27
|
-
}
|
|
28
|
-
if (proc.stderr != null) {
|
|
29
|
-
proc.stderr.on('data', (data: StringObject) => {
|
|
30
|
-
out.errStr += data.toString()
|
|
31
|
-
if (consolePass) process.stdout.write(data.toString())
|
|
32
|
-
})
|
|
33
|
-
}
|
|
34
|
-
proc.on('error', error => {
|
|
35
|
-
console.error(error)
|
|
36
|
-
if (out.errStr === '') out.errStr = error.message
|
|
37
|
-
out.retcode = -1
|
|
38
|
-
resolve(out)
|
|
39
|
-
})
|
|
40
|
-
proc.on('close', code => {
|
|
41
|
-
out.retcode = code === null ? -1 : code
|
|
42
|
-
resolve(out)
|
|
43
|
-
})
|
|
44
|
-
})
|
|
45
|
-
}
|
|
1
|
+
|
|
2
|
+
import { exec } from 'child_process'
|
|
3
|
+
|
|
4
|
+
interface StringObject {
|
|
5
|
+
toString: () => string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export async function executeCommand (cmd: string, args: any[], cwd = '', consolePass = false, env: any = {}): Promise<any> {
|
|
9
|
+
const out = {
|
|
10
|
+
stdStr: '',
|
|
11
|
+
errStr: '',
|
|
12
|
+
retcode: 0
|
|
13
|
+
}
|
|
14
|
+
return await new Promise(resolve => {
|
|
15
|
+
const cmdstr = cmd + ' ' + args.join(' ')
|
|
16
|
+
// console.log('executing ', cmdstr, 'at', cwd)
|
|
17
|
+
const opts = {
|
|
18
|
+
cwd,
|
|
19
|
+
env: Object.assign(env, process.env)
|
|
20
|
+
}
|
|
21
|
+
const proc = exec(cmdstr, opts)
|
|
22
|
+
if (proc.stdout != null) {
|
|
23
|
+
proc.stdout.on('data', (data: StringObject) => {
|
|
24
|
+
out.stdStr += data.toString()
|
|
25
|
+
if (consolePass) process.stdout.write(data.toString())
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
if (proc.stderr != null) {
|
|
29
|
+
proc.stderr.on('data', (data: StringObject) => {
|
|
30
|
+
out.errStr += data.toString()
|
|
31
|
+
if (consolePass) process.stdout.write(data.toString())
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
proc.on('error', error => {
|
|
35
|
+
console.error(error)
|
|
36
|
+
if (out.errStr === '') out.errStr = error.message
|
|
37
|
+
out.retcode = -1
|
|
38
|
+
resolve(out)
|
|
39
|
+
})
|
|
40
|
+
proc.on('close', code => {
|
|
41
|
+
out.retcode = code === null ? -1 : code
|
|
42
|
+
resolve(out)
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
}
|
package/src/lib/fileCompare.ts
CHANGED
|
@@ -1,55 +1,55 @@
|
|
|
1
|
-
import path from 'path'
|
|
2
|
-
import fs from 'fs'
|
|
3
|
-
import { recurseDirectory } from './DirectoryUtils'
|
|
4
|
-
|
|
5
|
-
// true if filepath > mapped file in outDir (i.e. .ts > .js)
|
|
6
|
-
export function isNewer (
|
|
7
|
-
filepath: string,
|
|
8
|
-
outDir: string,
|
|
9
|
-
mappingObj: any = { '.ts': '.js' }
|
|
10
|
-
): boolean {
|
|
11
|
-
let basename = path.basename(filepath)
|
|
12
|
-
const ext = path.extname(filepath)
|
|
13
|
-
basename = basename.substring(0, basename.lastIndexOf(ext))
|
|
14
|
-
let newExt = ''
|
|
15
|
-
|
|
16
|
-
if (mappingObj[ext] !== undefined) newExt = mappingObj[ext]
|
|
17
|
-
|
|
18
|
-
const outfile = path.join(outDir, basename + newExt)
|
|
19
|
-
return isNewerFile(filepath, outfile)
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// true if filepath is newer than destpath
|
|
23
|
-
export function isNewerFile (
|
|
24
|
-
filepath: string,
|
|
25
|
-
destpath: string,
|
|
26
|
-
srcFilter: string = '',
|
|
27
|
-
dstFilter: string = ''
|
|
28
|
-
): boolean {
|
|
29
|
-
const sstat = fs.statSync(filepath)
|
|
30
|
-
const srcTime = sstat.isDirectory() ? latestInDirectory(filepath, srcFilter) : fs.statSync(filepath).mtime
|
|
31
|
-
let destTime = new Date(0)
|
|
32
|
-
if (fs.existsSync((destpath))) {
|
|
33
|
-
const dstat = fs.statSync(destpath)
|
|
34
|
-
destTime = dstat.isDirectory() ? latestInDirectory(destpath, dstFilter) : fs.statSync(destpath).mtime
|
|
35
|
-
}
|
|
36
|
-
return (srcTime >= destTime)
|
|
37
|
-
}
|
|
38
|
-
function latestInDirectory (
|
|
39
|
-
dirPath: string,
|
|
40
|
-
extFilter: string = ''
|
|
41
|
-
): Date {
|
|
42
|
-
let newestTime = new Date(0)
|
|
43
|
-
recurseDirectory(dirPath, (filepath, stats) => {
|
|
44
|
-
if (stats.isFile()) {
|
|
45
|
-
const ext = path.extname(filepath)
|
|
46
|
-
if ((extFilter ?? '') === '' || ext === extFilter) {
|
|
47
|
-
if (stats.mtime > newestTime) {
|
|
48
|
-
newestTime = stats.mtime
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
return false
|
|
53
|
-
})
|
|
54
|
-
return newestTime
|
|
55
|
-
}
|
|
1
|
+
import path from 'path'
|
|
2
|
+
import fs from 'fs'
|
|
3
|
+
import { recurseDirectory } from './DirectoryUtils'
|
|
4
|
+
|
|
5
|
+
// true if filepath > mapped file in outDir (i.e. .ts > .js)
|
|
6
|
+
export function isNewer (
|
|
7
|
+
filepath: string,
|
|
8
|
+
outDir: string,
|
|
9
|
+
mappingObj: any = { '.ts': '.js' }
|
|
10
|
+
): boolean {
|
|
11
|
+
let basename = path.basename(filepath)
|
|
12
|
+
const ext = path.extname(filepath)
|
|
13
|
+
basename = basename.substring(0, basename.lastIndexOf(ext))
|
|
14
|
+
let newExt = ''
|
|
15
|
+
|
|
16
|
+
if (mappingObj[ext] !== undefined) newExt = mappingObj[ext]
|
|
17
|
+
|
|
18
|
+
const outfile = path.join(outDir, basename + newExt)
|
|
19
|
+
return isNewerFile(filepath, outfile)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// true if filepath is newer than destpath
|
|
23
|
+
export function isNewerFile (
|
|
24
|
+
filepath: string,
|
|
25
|
+
destpath: string,
|
|
26
|
+
srcFilter: string = '',
|
|
27
|
+
dstFilter: string = ''
|
|
28
|
+
): boolean {
|
|
29
|
+
const sstat = fs.statSync(filepath)
|
|
30
|
+
const srcTime = sstat.isDirectory() ? latestInDirectory(filepath, srcFilter) : fs.statSync(filepath).mtime
|
|
31
|
+
let destTime = new Date(0)
|
|
32
|
+
if (fs.existsSync((destpath))) {
|
|
33
|
+
const dstat = fs.statSync(destpath)
|
|
34
|
+
destTime = dstat.isDirectory() ? latestInDirectory(destpath, dstFilter) : fs.statSync(destpath).mtime
|
|
35
|
+
}
|
|
36
|
+
return (srcTime >= destTime)
|
|
37
|
+
}
|
|
38
|
+
function latestInDirectory (
|
|
39
|
+
dirPath: string,
|
|
40
|
+
extFilter: string = ''
|
|
41
|
+
): Date {
|
|
42
|
+
let newestTime = new Date(0)
|
|
43
|
+
recurseDirectory(dirPath, (filepath, stats) => {
|
|
44
|
+
if (stats.isFile()) {
|
|
45
|
+
const ext = path.extname(filepath)
|
|
46
|
+
if ((extFilter ?? '') === '' || ext === extFilter) {
|
|
47
|
+
if (stats.mtime > newestTime) {
|
|
48
|
+
newestTime = stats.mtime
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return false
|
|
53
|
+
})
|
|
54
|
+
return newestTime
|
|
55
|
+
}
|