@capgo/cli 4.0.12 → 4.0.13
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/CHANGELOG.md +8 -0
- package/bun.lockb +0 -0
- package/capacitor.config.ts +2 -2
- package/dist/index.js +650 -654
- package/eslint.config.js +3 -0
- package/package.json +3 -2
- package/src/api/app.ts +29 -36
- package/src/api/channels.ts +53 -49
- package/src/api/crypto.ts +83 -80
- package/src/api/devices_override.ts +12 -13
- package/src/api/update.ts +10 -10
- package/src/api/versions.ts +43 -42
- package/src/app/add.ts +61 -53
- package/src/app/debug.ts +153 -151
- package/src/app/delete.ts +61 -59
- package/src/app/info.ts +74 -77
- package/src/app/list.ts +33 -31
- package/src/app/set.ts +85 -82
- package/src/bundle/check.ts +30 -32
- package/src/bundle/cleanup.ts +71 -74
- package/src/bundle/compatibility.ts +52 -55
- package/src/bundle/decrypt.ts +21 -19
- package/src/bundle/delete.ts +27 -25
- package/src/bundle/encrypt.ts +23 -21
- package/src/bundle/list.ts +42 -40
- package/src/bundle/unlink.ts +69 -60
- package/src/bundle/upload.ts +170 -149
- package/src/bundle/zip.ts +122 -118
- package/src/channel/add.ts +62 -60
- package/src/channel/currentBundle.ts +56 -56
- package/src/channel/delete.ts +46 -43
- package/src/channel/list.ts +23 -21
- package/src/channel/set.ts +76 -68
- package/src/index.ts +55 -57
- package/src/init.ts +254 -252
- package/src/key.ts +56 -52
- package/src/login.ts +30 -28
- package/src/types/capacitor__cli.d.ts +2 -3
- package/src/types/supabase.types.ts +505 -505
- package/src/utils.ts +560 -571
- package/.eslintrc +0 -71
package/src/app/info.ts
CHANGED
|
@@ -1,90 +1,87 @@
|
|
|
1
|
-
import { readFileSync } from
|
|
2
|
-
import { join } from
|
|
3
|
-
import os from 'node:os'
|
|
4
|
-
import
|
|
5
|
-
import
|
|
1
|
+
import { readFileSync } from 'node:fs'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
import os from 'node:os'
|
|
4
|
+
import process from 'node:process'
|
|
5
|
+
import getLatest from 'get-latest-version'
|
|
6
|
+
import Spinnies from '@trufflesuite/spinnies'
|
|
7
|
+
import * as p from '@clack/prompts'
|
|
6
8
|
import pack from '../../package.json'
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
10
|
+
async function getLatestDependencies(installedDependencies: { [key: string]: string }) {
|
|
11
|
+
const latestDependencies: { [key: string]: string } = {}
|
|
12
|
+
const all = []
|
|
13
|
+
for (const dependency in installedDependencies) {
|
|
14
|
+
if (Object.prototype.hasOwnProperty.call(installedDependencies, dependency)) {
|
|
15
|
+
// get in npm the last version of the dependency
|
|
16
|
+
all.push(getLatest(dependency))
|
|
16
17
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
18
|
+
}
|
|
19
|
+
await Promise.all(all)
|
|
20
|
+
.then((values) => {
|
|
21
|
+
const keys = Object.keys(installedDependencies)
|
|
22
|
+
for (let i = 0; i < values.length; i += 1) {
|
|
23
|
+
const v = values[i]
|
|
24
|
+
if (v)
|
|
25
|
+
latestDependencies[keys[i]] = v
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
return latestDependencies
|
|
28
29
|
}
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
async function readPackageJson() {
|
|
32
|
+
const packageJson = readFileSync(join(process.cwd(), 'package.json'))
|
|
33
|
+
return JSON.parse(packageJson as any)
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
async function getInstalledDependencies() {
|
|
37
|
+
const { dependencies } = await readPackageJson()
|
|
38
|
+
const installedDependencies: { [key: string]: string } = {
|
|
39
|
+
'@capgo/cli': pack.version,
|
|
40
|
+
}
|
|
41
|
+
for (const dependency in dependencies) {
|
|
42
|
+
if (Object.prototype.hasOwnProperty.call(dependencies, dependency) && dependency.startsWith('@capgo/')) {
|
|
43
|
+
// remove ^ or ~ from version
|
|
44
|
+
const version = dependencies[dependency].replace('^', '').replace('~', '')
|
|
45
|
+
installedDependencies[dependency] = version
|
|
39
46
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
// remove ^ or ~ from version
|
|
43
|
-
const version = dependencies[dependency].replace('^', '').replace('~', '')
|
|
44
|
-
installedDependencies[dependency] = version
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
return installedDependencies
|
|
47
|
+
}
|
|
48
|
+
return installedDependencies
|
|
48
49
|
}
|
|
49
50
|
|
|
50
|
-
export
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
console.log(` ${dependency}: ${installedVersion}`)
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
console.log('\n')
|
|
69
|
-
const spinnies = new Spinnies();
|
|
70
|
-
spinnies.add('loading', { text: 'Loading latest dependencies' });
|
|
71
|
-
const latestDependencies = await getLatestDependencies(installedDependencies)
|
|
72
|
-
spinnies.succeed('loading', { text: 'Latest Dependencies:' });
|
|
73
|
-
console.log('\n')
|
|
74
|
-
for (const dependency in latestDependencies) {
|
|
75
|
-
if (Object.prototype.hasOwnProperty.call(latestDependencies, dependency)) {
|
|
76
|
-
const latestVersion = (latestDependencies as any)[dependency]
|
|
77
|
-
console.log(` ${dependency}: ${latestVersion}`)
|
|
78
|
-
}
|
|
51
|
+
export async function getInfo() {
|
|
52
|
+
p.log.info(' 💊 Capgo Doctor 💊\n')
|
|
53
|
+
p.log.info(` OS: ${os.platform()} ${os.version()}\n`)
|
|
54
|
+
p.log.info(` Node: ${process.version}\n`)
|
|
55
|
+
p.log.info(' Installed Dependencies:\n')
|
|
56
|
+
const installedDependencies = await getInstalledDependencies()
|
|
57
|
+
if (Object.keys(installedDependencies).length === 0) {
|
|
58
|
+
// display in red color in shell with console log
|
|
59
|
+
p.log.warning('\x1B[31m%s\x1B[0m 🚨 No dependencies found')
|
|
60
|
+
process.exit(1)
|
|
61
|
+
}
|
|
62
|
+
for (const dependency in installedDependencies) {
|
|
63
|
+
if (Object.prototype.hasOwnProperty.call(installedDependencies, dependency)) {
|
|
64
|
+
const installedVersion = (installedDependencies as any)[dependency]
|
|
65
|
+
p.log.info(` ${dependency}: ${installedVersion}`)
|
|
79
66
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
67
|
+
}
|
|
68
|
+
p.log.info('\n')
|
|
69
|
+
const spinnies = new Spinnies()
|
|
70
|
+
spinnies.add('loading', { text: ' Loading latest dependencies' })
|
|
71
|
+
const latestDependencies = await getLatestDependencies(installedDependencies)
|
|
72
|
+
spinnies.succeed('loading', { text: ' Latest Dependencies:' })
|
|
73
|
+
for (const dependency in latestDependencies) {
|
|
74
|
+
if (Object.prototype.hasOwnProperty.call(latestDependencies, dependency)) {
|
|
75
|
+
const latestVersion = (latestDependencies as any)[dependency]
|
|
76
|
+
p.log.info(` ${dependency}: ${latestVersion}`)
|
|
85
77
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
78
|
+
}
|
|
79
|
+
if (JSON.stringify(installedDependencies) !== JSON.stringify(latestDependencies)) {
|
|
80
|
+
// display in red color in shell with console log
|
|
81
|
+
p.log.warn('\x1B[31m🚨 Some dependencies are not up to date\x1B[0m')
|
|
82
|
+
process.exit(1)
|
|
83
|
+
}
|
|
84
|
+
// display in green color in shell with console log
|
|
85
|
+
p.log.success('\x1B[32m✅ All dependencies are up to date\x1B[0m')
|
|
86
|
+
process.exit()
|
|
90
87
|
}
|
package/src/app/list.ts
CHANGED
|
@@ -1,61 +1,63 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import process from 'node:process'
|
|
2
|
+
import { program } from 'commander'
|
|
3
|
+
import { Table } from 'console-table-printer'
|
|
4
|
+
import type { SupabaseClient } from '@supabase/supabase-js'
|
|
5
|
+
import * as p from '@clack/prompts'
|
|
6
|
+
import type { Database } from '../types/supabase.types'
|
|
7
|
+
import type { OptionsBase } from '../utils'
|
|
8
|
+
import { createSupabaseClient, findSavedKey, getHumanDate, verifyUser } from '../utils'
|
|
9
|
+
import { checkLatest } from '../api/update'
|
|
10
|
+
|
|
11
|
+
function displayApp(data: Database['public']['Tables']['apps']['Row'][]) {
|
|
10
12
|
const t = new Table({
|
|
11
|
-
title:
|
|
12
|
-
charLength: {
|
|
13
|
-
})
|
|
13
|
+
title: 'Apps',
|
|
14
|
+
charLength: { '❌': 2, '✅': 2 },
|
|
15
|
+
})
|
|
14
16
|
|
|
15
17
|
// add rows with color
|
|
16
|
-
data.reverse().forEach(row => {
|
|
18
|
+
data.reverse().forEach((row) => {
|
|
17
19
|
t.addRow({
|
|
18
20
|
Name: row.name,
|
|
19
21
|
id: row.app_id,
|
|
20
|
-
Created: getHumanDate(row.created_at)
|
|
21
|
-
})
|
|
22
|
-
})
|
|
22
|
+
Created: getHumanDate(row.created_at),
|
|
23
|
+
})
|
|
24
|
+
})
|
|
23
25
|
|
|
24
|
-
p.log.success(t.render())
|
|
26
|
+
p.log.success(t.render())
|
|
25
27
|
}
|
|
26
28
|
|
|
27
|
-
export
|
|
29
|
+
export async function getActiveApps(supabase: SupabaseClient<Database>) {
|
|
28
30
|
const { data, error: vError } = await supabase
|
|
29
31
|
.from('apps')
|
|
30
32
|
.select()
|
|
31
33
|
// .eq('user_id', userId)
|
|
32
|
-
.order('created_at', { ascending: false })
|
|
34
|
+
.order('created_at', { ascending: false })
|
|
33
35
|
|
|
34
36
|
if (vError) {
|
|
35
|
-
p.log.error('Apps not found')
|
|
36
|
-
program.error('')
|
|
37
|
+
p.log.error('Apps not found')
|
|
38
|
+
program.error('')
|
|
37
39
|
}
|
|
38
|
-
return data
|
|
40
|
+
return data
|
|
39
41
|
}
|
|
40
42
|
|
|
41
|
-
export
|
|
42
|
-
p.intro(`List apps in Capgo`)
|
|
43
|
+
export async function listApp(options: OptionsBase) {
|
|
44
|
+
p.intro(`List apps in Capgo`)
|
|
43
45
|
|
|
44
|
-
await checkLatest()
|
|
46
|
+
await checkLatest()
|
|
45
47
|
options.apikey = options.apikey || findSavedKey()
|
|
46
48
|
|
|
47
49
|
const supabase = await createSupabaseClient(options.apikey)
|
|
48
50
|
|
|
49
|
-
await verifyUser(supabase, options.apikey, ['write', 'all', 'read', 'upload'])
|
|
51
|
+
await verifyUser(supabase, options.apikey, ['write', 'all', 'read', 'upload'])
|
|
50
52
|
|
|
51
|
-
p.log.info(`Getting active bundle in Capgo`)
|
|
53
|
+
p.log.info(`Getting active bundle in Capgo`)
|
|
52
54
|
|
|
53
55
|
// Get all active app versions we might possibly be able to cleanup
|
|
54
|
-
const allApps = await getActiveApps(supabase)
|
|
56
|
+
const allApps = await getActiveApps(supabase)
|
|
55
57
|
|
|
56
|
-
p.log.info(`Active app in Capgo: ${allApps?.length}`)
|
|
58
|
+
p.log.info(`Active app in Capgo: ${allApps?.length}`)
|
|
57
59
|
|
|
58
|
-
displayApp(allApps)
|
|
59
|
-
p.outro(`Done ✅`)
|
|
60
|
+
displayApp(allApps)
|
|
61
|
+
p.outro(`Done ✅`)
|
|
60
62
|
process.exit()
|
|
61
63
|
}
|
package/src/app/set.ts
CHANGED
|
@@ -1,91 +1,94 @@
|
|
|
1
|
-
import { randomUUID } from
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
1
|
+
import { randomUUID } from 'node:crypto'
|
|
2
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
3
|
+
import process from 'node:process'
|
|
4
|
+
import mime from 'mime'
|
|
5
|
+
import { program } from 'commander'
|
|
6
|
+
import * as p from '@clack/prompts'
|
|
7
|
+
import type { Options } from '../api/app'
|
|
8
|
+
import { checkAppExistsAndHasPermissionErr, newIconPath } from '../api/app'
|
|
9
|
+
import { createSupabaseClient, findSavedKey, formatError, getConfig, verifyUser } from '../utils'
|
|
8
10
|
|
|
9
|
-
export
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
export async function setApp(appId: string, options: Options) {
|
|
12
|
+
p.intro(`Set app`)
|
|
13
|
+
options.apikey = options.apikey || findSavedKey()
|
|
14
|
+
const config = await getConfig()
|
|
15
|
+
appId = appId || config?.app?.appId
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
if (!options.apikey) {
|
|
18
|
+
p.log.error(`Missing API key, you need to provide a API key to upload your bundle`)
|
|
19
|
+
program.error(``)
|
|
20
|
+
}
|
|
21
|
+
if (!appId) {
|
|
22
|
+
p.log.error('Missing argument, you need to provide a appId, or be in a capacitor project')
|
|
23
|
+
program.error(``)
|
|
24
|
+
}
|
|
25
|
+
const supabase = await createSupabaseClient(options.apikey)
|
|
24
26
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
const userId = await verifyUser(supabase, options.apikey, ['write', 'all'])
|
|
28
|
+
// Check we have app access to this appId
|
|
29
|
+
await checkAppExistsAndHasPermissionErr(supabase, options.apikey, appId)
|
|
28
30
|
|
|
29
|
-
|
|
31
|
+
const { name, icon, retention } = options
|
|
30
32
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
if (retention && !Number.isNaN(Number(retention))) {
|
|
34
|
+
p.log.error(`retention value must be a number`)
|
|
35
|
+
program.error(``)
|
|
36
|
+
}
|
|
37
|
+
else if (retention && retention < 0) {
|
|
38
|
+
p.log.error(`retention value cannot be less than 0`)
|
|
39
|
+
program.error(``)
|
|
40
|
+
}
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
let iconBuff
|
|
43
|
+
let iconType
|
|
44
|
+
const fileName = `icon_${randomUUID()}`
|
|
45
|
+
let signedURL = 'https://xvwzpoazmxkqosrdewyv.supabase.co/storage/v1/object/public/images/capgo.png'
|
|
44
46
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const { data: signedURLData } = await supabase
|
|
70
|
-
.storage
|
|
71
|
-
.from(`images/${userId}/${appId}`)
|
|
72
|
-
.getPublicUrl(fileName)
|
|
73
|
-
signedURL = signedURLData?.publicUrl || signedURL
|
|
74
|
-
}
|
|
75
|
-
// retention is in seconds in the database but received as days here
|
|
76
|
-
const { error: dbError } = await supabase
|
|
77
|
-
.from('apps')
|
|
78
|
-
.update({
|
|
79
|
-
icon_url: signedURL,
|
|
80
|
-
name,
|
|
81
|
-
retention: !retention ? undefined : retention * 24 * 60 * 60,
|
|
82
|
-
})
|
|
83
|
-
.eq('app_id', appId)
|
|
84
|
-
.eq('user_id', userId)
|
|
85
|
-
if (dbError) {
|
|
86
|
-
p.log.error(`Could not add app ${formatError(dbError)}`);
|
|
87
|
-
program.error(``);
|
|
47
|
+
if (icon && existsSync(icon)) {
|
|
48
|
+
iconBuff = readFileSync(icon)
|
|
49
|
+
const contentType = mime.getType(icon)
|
|
50
|
+
iconType = contentType || 'image/png'
|
|
51
|
+
p.log.warn(`Found app icon ${icon}`)
|
|
52
|
+
}
|
|
53
|
+
else if (existsSync(newIconPath)) {
|
|
54
|
+
iconBuff = readFileSync(newIconPath)
|
|
55
|
+
const contentType = mime.getType(newIconPath)
|
|
56
|
+
iconType = contentType || 'image/png'
|
|
57
|
+
p.log.warn(`Found app icon ${newIconPath}`)
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
p.log.warn(`Cannot find app icon in any of the following locations: ${icon}, ${newIconPath}`)
|
|
61
|
+
}
|
|
62
|
+
if (iconBuff && iconType) {
|
|
63
|
+
const { error } = await supabase.storage
|
|
64
|
+
.from(`images/${userId}/${appId}`)
|
|
65
|
+
.upload(fileName, iconBuff, {
|
|
66
|
+
contentType: iconType,
|
|
67
|
+
})
|
|
68
|
+
if (error) {
|
|
69
|
+
p.log.error(`Could not add app ${formatError(error)}`)
|
|
70
|
+
program.error(``)
|
|
88
71
|
}
|
|
89
|
-
|
|
90
|
-
|
|
72
|
+
const { data: signedURLData } = await supabase
|
|
73
|
+
.storage
|
|
74
|
+
.from(`images/${userId}/${appId}`)
|
|
75
|
+
.getPublicUrl(fileName)
|
|
76
|
+
signedURL = signedURLData?.publicUrl || signedURL
|
|
77
|
+
}
|
|
78
|
+
// retention is in seconds in the database but received as days here
|
|
79
|
+
const { error: dbError } = await supabase
|
|
80
|
+
.from('apps')
|
|
81
|
+
.update({
|
|
82
|
+
icon_url: signedURL,
|
|
83
|
+
name,
|
|
84
|
+
retention: !retention ? undefined : retention * 24 * 60 * 60,
|
|
85
|
+
})
|
|
86
|
+
.eq('app_id', appId)
|
|
87
|
+
.eq('user_id', userId)
|
|
88
|
+
if (dbError) {
|
|
89
|
+
p.log.error(`Could not add app ${formatError(dbError)}`)
|
|
90
|
+
program.error(``)
|
|
91
|
+
}
|
|
92
|
+
p.outro(`Done ✅`)
|
|
93
|
+
process.exit()
|
|
91
94
|
}
|
package/src/bundle/check.ts
CHANGED
|
@@ -1,44 +1,42 @@
|
|
|
1
|
-
import fs from 'node:fs'
|
|
2
|
-
import path from
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
const content = fs.readFileSync(filePath,
|
|
6
|
-
return content.includes(searchString)
|
|
7
|
-
}
|
|
4
|
+
function searchInFile(filePath: string, searchString: string) {
|
|
5
|
+
const content = fs.readFileSync(filePath, 'utf8')
|
|
6
|
+
return content.includes(searchString)
|
|
7
|
+
}
|
|
8
8
|
|
|
9
|
-
export
|
|
10
|
-
const files = fs.readdirSync(dirPath)
|
|
9
|
+
export function searchInDirectory(dirPath: string, searchString: string) {
|
|
10
|
+
const files = fs.readdirSync(dirPath)
|
|
11
11
|
for (const file of files) {
|
|
12
|
-
const filePath = path.join(dirPath, file)
|
|
13
|
-
const stats = fs.statSync(filePath)
|
|
12
|
+
const filePath = path.join(dirPath, file)
|
|
13
|
+
const stats = fs.statSync(filePath)
|
|
14
14
|
|
|
15
15
|
if (stats.isDirectory()) {
|
|
16
|
-
if (searchInDirectory(filePath, searchString))
|
|
17
|
-
return true
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
if (searchInFile(filePath, searchString))
|
|
21
|
-
return true
|
|
22
|
-
}
|
|
16
|
+
if (searchInDirectory(filePath, searchString))
|
|
17
|
+
return true
|
|
18
|
+
}
|
|
19
|
+
else if (stats.isFile() && path.extname(filePath) === '.js') {
|
|
20
|
+
if (searchInFile(filePath, searchString))
|
|
21
|
+
return true
|
|
23
22
|
}
|
|
24
23
|
}
|
|
25
24
|
|
|
26
|
-
return false
|
|
27
|
-
}
|
|
25
|
+
return false
|
|
26
|
+
}
|
|
28
27
|
|
|
29
|
-
export
|
|
28
|
+
export function checkIndexPosition(dirPath: string): boolean {
|
|
30
29
|
// look for index.html in the root folder or if there only one folder in the root folder look for index.html in this folder
|
|
31
|
-
const files = fs.readdirSync(dirPath)
|
|
30
|
+
const files = fs.readdirSync(dirPath)
|
|
32
31
|
if (files.length === 1) {
|
|
33
|
-
const filePath = path.join(dirPath, files[0])
|
|
34
|
-
const stats = fs.statSync(filePath)
|
|
35
|
-
if (stats.isDirectory())
|
|
36
|
-
return checkIndexPosition(filePath)
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
const index = files.indexOf("index.html");
|
|
40
|
-
if (index > -1) {
|
|
41
|
-
return true;
|
|
32
|
+
const filePath = path.join(dirPath, files[0])
|
|
33
|
+
const stats = fs.statSync(filePath)
|
|
34
|
+
if (stats.isDirectory())
|
|
35
|
+
return checkIndexPosition(filePath)
|
|
42
36
|
}
|
|
43
|
-
|
|
44
|
-
|
|
37
|
+
const index = files.indexOf('index.html')
|
|
38
|
+
if (index > -1)
|
|
39
|
+
return true
|
|
40
|
+
|
|
41
|
+
return false
|
|
42
|
+
}
|