esm.dev 2.0.3 → 2.0.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/dist/cli.js +20 -0
- package/dist/commands/ESMDevCommand.js +6 -0
- package/dist/commands/InitCommand.js +49 -0
- package/dist/commands/LoginCommand.js +12 -0
- package/dist/commands/MustacheGeneratorCommand.js +9 -0
- package/dist/commands/RepublishCommand.js +11 -0
- package/dist/commands/StartCommand.js +18 -0
- package/dist/commands/TokenCommand.js +23 -0
- package/dist/commands/VersionCommand.js +15 -0
- package/dist/commands/WaitForRegistryCommand.js +12 -0
- package/dist/commands/WatchCommand.js +12 -0
- package/dist/commands/mixins/CommandClass.js +1 -0
- package/dist/commands/mixins/ESMServed.js +9 -0
- package/dist/commands/mixins/ESMStorageSpecific.js +9 -0
- package/dist/commands/mixins/PackagePathSpecific.js +14 -0
- package/dist/commands/mixins/RegistrySpecific.js +9 -0
- package/dist/commands/mixins/Retryable.js +29 -0
- package/dist/commands/mixins/Servable.js +11 -0
- package/dist/commands/mixins/Watchable.js +9 -0
- package/dist/commands/options/EnvOption.js +6 -0
- package/dist/lib/MustacheGenerator.js +9 -0
- package/dist/lib/getPackageMeta.js +10 -0
- package/dist/lib/index.js +8 -0
- package/dist/lib/login.js +25 -0
- package/dist/lib/publish.js +7 -0
- package/dist/lib/queue.js +48 -0
- package/dist/lib/republish.js +9 -0
- package/dist/lib/server.js +34 -0
- package/dist/lib/unpublish.js +26 -0
- package/dist/lib/until.js +32 -0
- package/dist/lib/watch.js +88 -0
- package/dist/lib/watchIgnoreList.js +50 -0
- package/package.json +5 -7
- package/src/cli.ts +0 -21
- package/src/commands/ESMDevCommand.ts +0 -8
- package/src/commands/InitCommand.ts +0 -71
- package/src/commands/LoginCommand.ts +0 -15
- package/src/commands/MustacheGeneratorCommand.ts +0 -10
- package/src/commands/RepublishCommand.ts +0 -15
- package/src/commands/StartCommand.ts +0 -23
- package/src/commands/TokenCommand.ts +0 -29
- package/src/commands/VersionCommand.ts +0 -23
- package/src/commands/WaitForRegistryCommand.ts +0 -17
- package/src/commands/WatchCommand.ts +0 -15
- package/src/commands/mixins/CommandClass.ts +0 -3
- package/src/commands/mixins/ESMServed.ts +0 -12
- package/src/commands/mixins/ESMStorageSpecific.ts +0 -16
- package/src/commands/mixins/PackagePathSpecific.ts +0 -18
- package/src/commands/mixins/RegistrySpecific.ts +0 -12
- package/src/commands/mixins/Retryable.ts +0 -33
- package/src/commands/mixins/Servable.ts +0 -14
- package/src/commands/mixins/Watchable.ts +0 -13
- package/src/commands/options/EnvOption.ts +0 -27
- package/src/lib/MustacheGenerator.ts +0 -10
- package/src/lib/getPackageMeta.ts +0 -15
- package/src/lib/login.ts +0 -29
- package/src/lib/publish.ts +0 -14
- package/src/lib/queue.ts +0 -59
- package/src/lib/republish.ts +0 -16
- package/src/lib/server.ts +0 -33
- package/src/lib/unpublish.ts +0 -40
- package/src/lib/until.ts +0 -50
- package/src/lib/watch.ts +0 -134
- package/src/lib/watchIgnoreList.ts +0 -61
package/src/lib/republish.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { getPackageMeta } from './getPackageMeta.ts'
|
|
2
|
-
import { publish } from './publish.ts'
|
|
3
|
-
import { unpublish } from './unpublish.ts'
|
|
4
|
-
|
|
5
|
-
export async function republish(
|
|
6
|
-
packagePath: string,
|
|
7
|
-
opts: {
|
|
8
|
-
registry: string
|
|
9
|
-
esmStoragePath: string
|
|
10
|
-
},
|
|
11
|
-
): Promise<void> {
|
|
12
|
-
console.info(`Republishing ${packagePath}`)
|
|
13
|
-
const { name, packageRoot } = await getPackageMeta(packagePath)
|
|
14
|
-
await unpublish({ ...opts, name })
|
|
15
|
-
await publish({ ...opts, packageRoot })
|
|
16
|
-
}
|
package/src/lib/server.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { queue } from './queue.ts'
|
|
2
|
-
import { createServer } from 'node:http'
|
|
3
|
-
import httpProxy from 'http-proxy'
|
|
4
|
-
|
|
5
|
-
export function serve(port: number, esmOrigin: string): () => void {
|
|
6
|
-
const proxy = httpProxy.createProxyServer()
|
|
7
|
-
|
|
8
|
-
const server = createServer((req, res) => {
|
|
9
|
-
queue(
|
|
10
|
-
() =>
|
|
11
|
-
new Promise<void>((resolve, reject) => {
|
|
12
|
-
console.info('Proxying', req.url)
|
|
13
|
-
req.on('error', reject)
|
|
14
|
-
res.on('error', reject)
|
|
15
|
-
res.on('close', resolve)
|
|
16
|
-
proxy.web(req, res, { target: esmOrigin })
|
|
17
|
-
}),
|
|
18
|
-
).catch((error) => {
|
|
19
|
-
res.statusCode = 500
|
|
20
|
-
res.setHeader('Content-Type', 'application/json; charset=utf-8')
|
|
21
|
-
res.write(JSON.stringify(error))
|
|
22
|
-
res.end()
|
|
23
|
-
})
|
|
24
|
-
}).listen(port, () => {
|
|
25
|
-
console.info('ESM proxy server listining on', server.address())
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
return () => {
|
|
29
|
-
console.info('closing the server')
|
|
30
|
-
server.closeAllConnections()
|
|
31
|
-
server.close()
|
|
32
|
-
}
|
|
33
|
-
}
|
package/src/lib/unpublish.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { $, ProcessOutput } from 'zx'
|
|
2
|
-
import { glob } from 'glob'
|
|
3
|
-
import { rm } from 'node:fs/promises'
|
|
4
|
-
|
|
5
|
-
export async function unpublish({
|
|
6
|
-
registry,
|
|
7
|
-
esmStoragePath,
|
|
8
|
-
name,
|
|
9
|
-
}: {
|
|
10
|
-
registry: string
|
|
11
|
-
esmStoragePath: string
|
|
12
|
-
name: string
|
|
13
|
-
}): Promise<void> {
|
|
14
|
-
await Promise.all([
|
|
15
|
-
unpublishPackage(registry, name),
|
|
16
|
-
deleteESMCache(esmStoragePath, name),
|
|
17
|
-
])
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async function unpublishPackage(registry: string, name: string) {
|
|
21
|
-
try {
|
|
22
|
-
await $`npm unpublish --registry ${registry} --force ${name}`
|
|
23
|
-
} catch (error) {
|
|
24
|
-
if (
|
|
25
|
-
error instanceof ProcessOutput &&
|
|
26
|
-
!error.stderr.includes('npm error code E404')
|
|
27
|
-
)
|
|
28
|
-
throw error
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async function deleteESMCache(esmStoragePath: string, name: string) {
|
|
33
|
-
const paths = await glob(`${esmStoragePath}/**/${name}@*`)
|
|
34
|
-
await Promise.all(
|
|
35
|
-
paths.map((path) => {
|
|
36
|
-
console.info('Deleting', path)
|
|
37
|
-
return rm(path, { recursive: true })
|
|
38
|
-
}),
|
|
39
|
-
)
|
|
40
|
-
}
|
package/src/lib/until.ts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { setTimeout } from 'node:timers/promises'
|
|
2
|
-
|
|
3
|
-
export async function until({
|
|
4
|
-
interval,
|
|
5
|
-
timeout,
|
|
6
|
-
try: Try,
|
|
7
|
-
}: {
|
|
8
|
-
interval: number
|
|
9
|
-
timeout: number
|
|
10
|
-
try(signal: AbortSignal): Promise<boolean>
|
|
11
|
-
}): Promise<boolean> {
|
|
12
|
-
const signal = AbortSignal.timeout(timeout)
|
|
13
|
-
while (!signal.aborted) {
|
|
14
|
-
try {
|
|
15
|
-
if (await Try(signal)) return true
|
|
16
|
-
} catch (error) {}
|
|
17
|
-
try {
|
|
18
|
-
await setTimeout(interval, null, { signal })
|
|
19
|
-
} catch (error) {}
|
|
20
|
-
}
|
|
21
|
-
return false
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export async function waitForEndpoint({
|
|
25
|
-
interval = 300,
|
|
26
|
-
timeout = 10_000,
|
|
27
|
-
endpoint,
|
|
28
|
-
}: {
|
|
29
|
-
interval?: number
|
|
30
|
-
timeout?: number
|
|
31
|
-
endpoint: string
|
|
32
|
-
}): Promise<void> {
|
|
33
|
-
if (
|
|
34
|
-
!(await until({
|
|
35
|
-
interval,
|
|
36
|
-
timeout,
|
|
37
|
-
async try(signal) {
|
|
38
|
-
const response = await fetch(endpoint, { signal })
|
|
39
|
-
return response.ok
|
|
40
|
-
},
|
|
41
|
-
}))
|
|
42
|
-
)
|
|
43
|
-
throw new EndpointUnavailableError()
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export class EndpointUnavailableError extends Error {
|
|
47
|
-
constructor() {
|
|
48
|
-
super('Endpoint not available')
|
|
49
|
-
}
|
|
50
|
-
}
|
package/src/lib/watch.ts
DELETED
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
import { watch as fsWatch } from 'node:fs'
|
|
2
|
-
import { republish } from './republish.ts'
|
|
3
|
-
import { getPackageMeta } from './getPackageMeta.ts'
|
|
4
|
-
import { readFile, writeFile } from 'node:fs/promises'
|
|
5
|
-
import { createHash } from 'node:crypto'
|
|
6
|
-
import { glob } from 'glob'
|
|
7
|
-
import { queue, queuedDebounce } from './queue.ts'
|
|
8
|
-
import { getWatchIgnorer, type Ignorer } from './watchIgnoreList.ts'
|
|
9
|
-
import { tempfile } from 'zx'
|
|
10
|
-
|
|
11
|
-
export async function watch(
|
|
12
|
-
packagePath: string,
|
|
13
|
-
opts: { registry: string; esmStoragePath: string; legacyMethod?: boolean },
|
|
14
|
-
): Promise<() => void> {
|
|
15
|
-
const {
|
|
16
|
-
name,
|
|
17
|
-
packageRoot,
|
|
18
|
-
private: prvte,
|
|
19
|
-
} = await getPackageMeta(packagePath)
|
|
20
|
-
|
|
21
|
-
if (prvte) {
|
|
22
|
-
console.info(`${name} is a private package... ignoring`)
|
|
23
|
-
return () => {}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
console.info('Watching', packageRoot)
|
|
27
|
-
|
|
28
|
-
const abortController = new AbortController()
|
|
29
|
-
const { signal } = abortController
|
|
30
|
-
|
|
31
|
-
const republishPackage = (filename: string = '') => {
|
|
32
|
-
console.info(`Change detected at ${packageRoot}/${filename}`)
|
|
33
|
-
return republish(packageRoot, opts).catch(console.error)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
try {
|
|
37
|
-
await queue(republishPackage, signal)
|
|
38
|
-
} catch (error: any) {
|
|
39
|
-
if (error.name === 'AbortError') return () => {}
|
|
40
|
-
else throw error
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return opts.legacyMethod
|
|
44
|
-
? legacyWatch(abortController, packageRoot, republishPackage)
|
|
45
|
-
: modernWatch(
|
|
46
|
-
abortController,
|
|
47
|
-
packageRoot,
|
|
48
|
-
queuedDebounce(republishPackage, 1_000, signal),
|
|
49
|
-
)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async function modernWatch(
|
|
53
|
-
abortController: AbortController,
|
|
54
|
-
dirname: string,
|
|
55
|
-
republish: (filename?: string | undefined) => Promise<void>,
|
|
56
|
-
) {
|
|
57
|
-
abortController.signal.addEventListener('abort', () => {
|
|
58
|
-
console.info('Stop watching', dirname)
|
|
59
|
-
watcher.close()
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
const ignorer = await getWatchIgnorer(dirname)
|
|
63
|
-
const watcher = fsWatch(
|
|
64
|
-
dirname,
|
|
65
|
-
{ recursive: true /*, signal: abortController.signal */ },
|
|
66
|
-
(_, filename) =>
|
|
67
|
-
(filename && ignorer.ignores(filename)) ||
|
|
68
|
-
republish(filename ?? '').catch((error) => {
|
|
69
|
-
if (error.name !== 'AbortError') throw error
|
|
70
|
-
}),
|
|
71
|
-
)
|
|
72
|
-
|
|
73
|
-
return () => abortController.abort()
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
async function legacyWatch(
|
|
77
|
-
abortController: AbortController,
|
|
78
|
-
dirname: string,
|
|
79
|
-
republish: (filename?: string | undefined) => Promise<void>,
|
|
80
|
-
) {
|
|
81
|
-
const ignorer = await getWatchIgnorer(dirname)
|
|
82
|
-
const filename = tempfile()
|
|
83
|
-
await hashDirectory(dirname, ignorer, filename, () => {})
|
|
84
|
-
|
|
85
|
-
abortController.signal.addEventListener('abort', () => {
|
|
86
|
-
console.info('Stop (legacy) watching', dirname)
|
|
87
|
-
clearTimeout(timer)
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
let timer: NodeJS.Timeout | undefined
|
|
91
|
-
beginTimer()
|
|
92
|
-
return () => abortController.abort()
|
|
93
|
-
|
|
94
|
-
function beginTimer() {
|
|
95
|
-
timer = setTimeout(
|
|
96
|
-
() =>
|
|
97
|
-
hashDirectory(dirname, ignorer, filename, republish)
|
|
98
|
-
.catch(console.error)
|
|
99
|
-
.finally(beginTimer),
|
|
100
|
-
1_000,
|
|
101
|
-
)
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
async function hashDirectory(
|
|
106
|
-
dirname: string,
|
|
107
|
-
ignorer: Ignorer,
|
|
108
|
-
filename: string,
|
|
109
|
-
onChange: () => any,
|
|
110
|
-
) {
|
|
111
|
-
const files = await glob(`${dirname}/**/*`, {
|
|
112
|
-
nodir: true,
|
|
113
|
-
ignore: { ignored: (path) => ignorer.ignores(path.fullpath()) },
|
|
114
|
-
})
|
|
115
|
-
const hashes = await Promise.all(
|
|
116
|
-
files.map(async (file) => {
|
|
117
|
-
const contents = await readFile(file)
|
|
118
|
-
return createHash('sha256').update(contents).digest('hex')
|
|
119
|
-
}),
|
|
120
|
-
)
|
|
121
|
-
const newHash = hashes.join('')
|
|
122
|
-
|
|
123
|
-
let previousHash = ''
|
|
124
|
-
|
|
125
|
-
try {
|
|
126
|
-
previousHash = await readFile(filename, 'utf-8')
|
|
127
|
-
} catch (error: any) {
|
|
128
|
-
if (error.code !== 'ENOENT') throw error
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (newHash !== previousHash) {
|
|
132
|
-
await Promise.all([writeFile(filename, newHash), onChange()])
|
|
133
|
-
}
|
|
134
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import gitignore from 'ignore'
|
|
2
|
-
import { Minimatch } from 'minimatch'
|
|
3
|
-
import { createReadStream } from 'node:fs'
|
|
4
|
-
import { access, constants } from 'node:fs/promises'
|
|
5
|
-
import * as path from 'node:path'
|
|
6
|
-
import { createInterface as createReadlineInterface } from 'node:readline/promises'
|
|
7
|
-
|
|
8
|
-
export async function getWatchIgnorer(dirname: string): Promise<Ignorer> {
|
|
9
|
-
const ignoreList = await getIgnoreList(dirname)
|
|
10
|
-
return ignoreList?.basename === '.gitignore'
|
|
11
|
-
? createGitIgnore(ignoreList.ignoreList)
|
|
12
|
-
: ignoreList?.basename === '.npmignore'
|
|
13
|
-
? createNPMIgnore(ignoreList.ignoreList)
|
|
14
|
-
: createNullIgnore()
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface Ignorer {
|
|
18
|
-
ignores(filename: string): boolean
|
|
19
|
-
filter(filenames: string[]): string[]
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function createNullIgnore(): Ignorer {
|
|
23
|
-
return { ignores: () => false, filter: (filenames) => filenames }
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function createNPMIgnore(list: string[]): Ignorer {
|
|
27
|
-
const mms = list.map((pattern) => new Minimatch(pattern))
|
|
28
|
-
const ignores = (filename: string) => mms.some((mm) => mm.match(filename))
|
|
29
|
-
return {
|
|
30
|
-
ignores,
|
|
31
|
-
filter: (filenames) => filenames.filter((filename) => !ignores(filename)),
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function createGitIgnore(list: string[]): Ignorer {
|
|
36
|
-
return gitignore().add(list)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
async function getIgnoreList(dirname: string) {
|
|
40
|
-
for (const basename of ['.npmignore', '.gitignore']) {
|
|
41
|
-
const filename = path.join(dirname, basename)
|
|
42
|
-
|
|
43
|
-
try {
|
|
44
|
-
await access(filename, constants.F_OK)
|
|
45
|
-
} catch (error) {
|
|
46
|
-
continue
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const rl = createReadlineInterface({
|
|
50
|
-
input: createReadStream(filename),
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
const ignoreList: string[] = []
|
|
54
|
-
for await (const line of rl) if (line) ignoreList.push(line.trim())
|
|
55
|
-
|
|
56
|
-
return {
|
|
57
|
-
basename,
|
|
58
|
-
ignoreList,
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|