dsh 0.2.0-rc.2: in-container update (experimental channel), path-agnostic compose, upstream patches adapted to 0.1.x/0.2.x
This commit is contained in:
commit
e6dcef9bf5
302 files changed
+75178
No files matched your search
@@ -0,0 +1,67 @@
|
||||
import { open, readFile, rm } from 'node:fs/promises'
|
||||
import { dirname } from 'node:path'
|
||||
import { canonicalJson } from '../../../platform/lib/canonical-json.mjs'
|
||||
import { durableReplace } from '../../../platform/lib/atomic.mjs'
|
||||
import { userPluginInternals } from './user-inventory.mjs'
|
||||
|
||||
function parse(value) {
|
||||
if (value === null || typeof value !== 'object' || Array.isArray(value)
|
||||
|| Object.keys(value).sort().join(',') !== 'disabled,schema'
|
||||
|| value.schema !== 1 || !Array.isArray(value.disabled)) {
|
||||
throw new Error('User Plugin selection state is invalid')
|
||||
}
|
||||
const names = new Set()
|
||||
const disabled = value.disabled.map(entry => {
|
||||
if (entry === null || typeof entry !== 'object' || Array.isArray(entry)
|
||||
|| Object.keys(entry).some(key => !['index', 'name'].includes(key))
|
||||
|| !userPluginInternals.PACKAGE_NAME_PATTERN.test(entry.name)
|
||||
|| !Number.isSafeInteger(entry.index) || entry.index < 0 || names.has(entry.name)) {
|
||||
throw new Error('User Plugin disabled-order entry is invalid')
|
||||
}
|
||||
names.add(entry.name)
|
||||
return Object.freeze({ name: entry.name, index: entry.index })
|
||||
})
|
||||
return Object.freeze({ schema: 1, disabled: Object.freeze(disabled) })
|
||||
}
|
||||
|
||||
export class UserPluginSelectionStore {
|
||||
constructor(path) {
|
||||
this.path = path
|
||||
}
|
||||
|
||||
async read() {
|
||||
return (await this.snapshot()).state
|
||||
}
|
||||
|
||||
async snapshot() {
|
||||
try {
|
||||
return Object.freeze({ present: true, state: parse(JSON.parse(await readFile(this.path, 'utf8'))) })
|
||||
} catch (error) {
|
||||
if (error?.code === 'ENOENT') {
|
||||
return Object.freeze({ present: false, state: parse({ schema: 1, disabled: [] }) })
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async write(value) {
|
||||
const state = parse(value)
|
||||
await durableReplace(this.path, `${canonicalJson(state).toString('utf8')}\n`)
|
||||
return state
|
||||
}
|
||||
|
||||
async restore(snapshot) {
|
||||
if (snapshot === null || typeof snapshot !== 'object' || typeof snapshot.present !== 'boolean') {
|
||||
throw new Error('User Plugin selection snapshot is invalid')
|
||||
}
|
||||
if (snapshot.present) return this.write(snapshot.state)
|
||||
await rm(this.path, { force: true })
|
||||
const directory = await open(dirname(this.path), 'r').catch(error => error?.code === 'ENOENT' ? undefined : Promise.reject(error))
|
||||
if (directory !== undefined) {
|
||||
try { await directory.sync() } finally { await directory.close() }
|
||||
}
|
||||
return parse({ schema: 1, disabled: [] })
|
||||
}
|
||||
}
|
||||
|
||||
export const userPluginStateInternals = Object.freeze({ parse })
|
||||
Reference in new issue
Block a user