mirror of
https://github.com/Start9Labs/start-sdk.git
synced 2026-03-30 12:21:57 +00:00
feat: remove the file things since we now are in node
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import { SDKManifest } from "../manifest/ManifestTypes"
|
import { SDKManifest } from "../manifest/ManifestTypes"
|
||||||
import * as T from "../types"
|
import * as T from "../types"
|
||||||
|
import fs from "fs"
|
||||||
|
|
||||||
export type BACKUP = "BACKUP"
|
export type BACKUP = "BACKUP"
|
||||||
export const DEFAULT_OPTIONS: T.BackupOptions = {
|
export const DEFAULT_OPTIONS: T.BackupOptions = {
|
||||||
@@ -93,47 +94,45 @@ export class Backups<M extends SDKManifest> {
|
|||||||
const createBackup: T.ExpectedExports.createBackup = async ({
|
const createBackup: T.ExpectedExports.createBackup = async ({
|
||||||
effects,
|
effects,
|
||||||
}) => {
|
}) => {
|
||||||
const previousItems = (
|
// const previousItems = (
|
||||||
await effects
|
// await effects
|
||||||
.readDir({
|
// .readDir({
|
||||||
volumeId: Backups.BACKUP,
|
// volumeId: Backups.BACKUP,
|
||||||
path: ".",
|
// path: ".",
|
||||||
})
|
// })
|
||||||
.catch(() => [])
|
// .catch(() => [])
|
||||||
).map((x) => `${x}`)
|
// ).map((x) => `${x}`)
|
||||||
const backupPaths = this.backupSet
|
// const backupPaths = this.backupSet
|
||||||
.filter((x) => x.dstVolume === Backups.BACKUP)
|
// .filter((x) => x.dstVolume === Backups.BACKUP)
|
||||||
.map((x) => x.dstPath)
|
// .map((x) => x.dstPath)
|
||||||
.map((x) => x.replace(/\.\/([^]*)\//, "$1"))
|
// .map((x) => x.replace(/\.\/([^]*)\//, "$1"))
|
||||||
const filteredItems = previousItems.filter(
|
// const filteredItems = previousItems.filter(
|
||||||
(x) => backupPaths.indexOf(x) === -1,
|
// (x) => backupPaths.indexOf(x) === -1,
|
||||||
)
|
// )
|
||||||
for (const itemToRemove of filteredItems) {
|
// for (const itemToRemove of filteredItems) {
|
||||||
effects.console.error(`Trying to remove ${itemToRemove}`)
|
// effects.console.error(`Trying to remove ${itemToRemove}`)
|
||||||
await effects
|
// await effects
|
||||||
.removeDir({
|
// .removeDir({
|
||||||
volumeId: Backups.BACKUP,
|
// volumeId: Backups.BACKUP,
|
||||||
path: itemToRemove,
|
// path: itemToRemove,
|
||||||
})
|
// })
|
||||||
.catch(() =>
|
// .catch(() =>
|
||||||
effects.removeFile({
|
// effects.removeFile({
|
||||||
volumeId: Backups.BACKUP,
|
// volumeId: Backups.BACKUP,
|
||||||
path: itemToRemove,
|
// path: itemToRemove,
|
||||||
}),
|
// }),
|
||||||
)
|
// )
|
||||||
.catch(() => {
|
// .catch(() => {
|
||||||
effects.console.warn(
|
// console.warn(`Failed to remove ${itemToRemove} from backup volume`)
|
||||||
`Failed to remove ${itemToRemove} from backup volume`,
|
// })
|
||||||
)
|
// }
|
||||||
})
|
|
||||||
}
|
|
||||||
for (const item of this.backupSet) {
|
for (const item of this.backupSet) {
|
||||||
if (notEmptyPath(item.dstPath)) {
|
// if (notEmptyPath(item.dstPath)) {
|
||||||
await effects.createDir({
|
// await effects.createDir({
|
||||||
volumeId: item.dstVolume,
|
// volumeId: item.dstVolume,
|
||||||
path: item.dstPath,
|
// path: item.dstPath,
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
await effects
|
await effects
|
||||||
.runRsync({
|
.runRsync({
|
||||||
...item,
|
...item,
|
||||||
@@ -150,12 +149,14 @@ export class Backups<M extends SDKManifest> {
|
|||||||
effects,
|
effects,
|
||||||
}) => {
|
}) => {
|
||||||
for (const item of this.backupSet) {
|
for (const item of this.backupSet) {
|
||||||
if (notEmptyPath(item.srcPath)) {
|
// if (notEmptyPath(item.srcPath)) {
|
||||||
await effects.createDir({
|
// await new Promise((resolve, reject) => fs.mkdir(items.src)).createDir(
|
||||||
volumeId: item.srcVolume,
|
// {
|
||||||
path: item.srcPath,
|
// volumeId: item.srcVolume,
|
||||||
})
|
// path: item.srcPath,
|
||||||
}
|
// },
|
||||||
|
// )
|
||||||
|
// }
|
||||||
await effects
|
await effects
|
||||||
.runRsync({
|
.runRsync({
|
||||||
options: {
|
options: {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { string } from "ts-matches"
|
|
||||||
import { Backups } from "./Backups"
|
import { Backups } from "./Backups"
|
||||||
import { SDKManifest } from "../manifest/ManifestTypes"
|
import { SDKManifest } from "../manifest/ManifestTypes"
|
||||||
import { BackupOptions, ExpectedExports } from "../types"
|
import { ExpectedExports } from "../types"
|
||||||
import { _ } from "../util"
|
import { _ } from "../util"
|
||||||
|
|
||||||
export type SetupBackupsParams<M extends SDKManifest> = Array<
|
export type SetupBackupsParams<M extends SDKManifest> = Array<
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ export function setupConfig<
|
|||||||
return {
|
return {
|
||||||
setConfig: (async ({ effects, input }) => {
|
setConfig: (async ({ effects, input }) => {
|
||||||
if (!validator.test(input)) {
|
if (!validator.test(input)) {
|
||||||
await effects.console.error(String(validator.errorMessage(input)))
|
await console.error(String(validator.errorMessage(input)))
|
||||||
return { error: "Set config type error for config" }
|
return { error: "Set config type error for config" }
|
||||||
}
|
}
|
||||||
const { restart } = await write({
|
const { restart } = await write({
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ export const checkWebUrl = async (
|
|||||||
message: successMessage,
|
message: successMessage,
|
||||||
}))
|
}))
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
effects.console.warn(`Error while fetching URL: ${url}`)
|
console.warn(`Error while fetching URL: ${url}`)
|
||||||
effects.console.error(JSON.stringify(e))
|
console.error(JSON.stringify(e))
|
||||||
effects.console.error(e.toString())
|
console.error(e.toString())
|
||||||
return { status: "failing" as const, message: errorMessage }
|
return { status: "failing" as const, message: errorMessage }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ export const runHealthScript = async <A extends string>(
|
|||||||
effects.runCommand(runCommand, { timeoutMillis: timeout }),
|
effects.runCommand(runCommand, { timeoutMillis: timeout }),
|
||||||
timeoutPromise(timeout),
|
timeoutPromise(timeout),
|
||||||
]).catch((e) => {
|
]).catch((e) => {
|
||||||
effects.console.warn(errorMessage)
|
console.warn(errorMessage)
|
||||||
effects.console.warn(JSON.stringify(e))
|
console.warn(JSON.stringify(e))
|
||||||
effects.console.warn(e.toString())
|
console.warn(e.toString())
|
||||||
throw { status: "failing", message: errorMessage } as CheckResult
|
throw { status: "failing", message: errorMessage } as CheckResult
|
||||||
})
|
})
|
||||||
return {
|
return {
|
||||||
|
|||||||
71
lib/types.ts
71
lib/types.ts
@@ -181,63 +181,11 @@ export type NetworkInterface = {
|
|||||||
|
|
||||||
/** Used to reach out from the pure js runtime */
|
/** Used to reach out from the pure js runtime */
|
||||||
export type Effects = {
|
export type Effects = {
|
||||||
/** Usable when not sandboxed */
|
|
||||||
writeFile(input: {
|
|
||||||
path: string
|
|
||||||
volumeId: string
|
|
||||||
toWrite: string
|
|
||||||
}): Promise<void>
|
|
||||||
readFile(input: { volumeId: string; path: string }): Promise<string>
|
|
||||||
/** Usable when not sandboxed */
|
|
||||||
appendFile(input: {
|
|
||||||
path: string
|
|
||||||
volumeId: string
|
|
||||||
toWrite: string
|
|
||||||
}): Promise<void>
|
|
||||||
/**
|
|
||||||
* Move file from src to dst
|
|
||||||
* Usable when not sandboxed */
|
|
||||||
moveFile(input: {
|
|
||||||
srcVolume: string
|
|
||||||
dstVolume: string
|
|
||||||
srcPath: string
|
|
||||||
dstPath: string
|
|
||||||
}): Promise<void>
|
|
||||||
/**
|
|
||||||
* copy from src to dst
|
|
||||||
* Usable when not sandboxed */
|
|
||||||
copyFile(input: {
|
|
||||||
srcVolume: string
|
|
||||||
dstVolume: string
|
|
||||||
srcPath: string
|
|
||||||
dstPath: string
|
|
||||||
}): Promise<void>
|
|
||||||
metadata(input: { volumeId: string; path: string }): Promise<Metadata>
|
|
||||||
/** Create a directory. Usable when not sandboxed */
|
|
||||||
createDir(input: { volumeId: string; path: string }): Promise<string>
|
|
||||||
|
|
||||||
readDir(input: { volumeId: string; path: string }): Promise<string[]>
|
|
||||||
/** Remove a directory. Usable when not sandboxed */
|
|
||||||
removeDir(input: { volumeId: string; path: string }): Promise<string>
|
|
||||||
removeFile(input: { volumeId: string; path: string }): Promise<void>
|
|
||||||
|
|
||||||
/** Write a json file into an object. Usable when not sandboxed */
|
|
||||||
writeJsonFile(input: {
|
|
||||||
volumeId: string
|
|
||||||
path: string
|
|
||||||
toWrite: Record<string, unknown>
|
|
||||||
}): Promise<void>
|
|
||||||
|
|
||||||
/** Read a json file into an object */
|
|
||||||
readJsonFile(input: {
|
|
||||||
volumeId: string
|
|
||||||
path: string
|
|
||||||
}): Promise<Record<string, unknown>>
|
|
||||||
|
|
||||||
runCommand<A extends string>(
|
runCommand<A extends string>(
|
||||||
command: ValidIfNoStupidEscape<A> | [string, ...string[]],
|
command: ValidIfNoStupidEscape<A> | [string, ...string[]],
|
||||||
options?: {
|
options?: {
|
||||||
timeoutMillis?: number
|
timeoutMillis?: number
|
||||||
|
env?: Record<string, string>
|
||||||
},
|
},
|
||||||
): Promise<string>
|
): Promise<string>
|
||||||
runDaemon<A extends string>(
|
runDaemon<A extends string>(
|
||||||
@@ -252,23 +200,6 @@ export type Effects = {
|
|||||||
/** Uses the chmod on the system */
|
/** Uses the chmod on the system */
|
||||||
chmod(input: { volumeId: string; path: string; mode: string }): Promise<null>
|
chmod(input: { volumeId: string; path: string; mode: string }): Promise<null>
|
||||||
|
|
||||||
sleep(timeMs: TimeMs): Promise<null>
|
|
||||||
|
|
||||||
console: {
|
|
||||||
/** Log at the trace level */
|
|
||||||
log(whatToPrint: string): Promise<void>
|
|
||||||
/** Log at the trace level */
|
|
||||||
trace(whatToPrint: string): Promise<void>
|
|
||||||
/** Log at the warn level */
|
|
||||||
warn(whatToPrint: string): Promise<void>
|
|
||||||
/** Log at the error level */
|
|
||||||
error(whatToPrint: string): Promise<void>
|
|
||||||
/** Log at the debug level */
|
|
||||||
debug(whatToPrint: string): Promise<void>
|
|
||||||
/** Log at the info level */
|
|
||||||
info(whatToPrint: string): Promise<void>
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Sandbox mode lets us read but not write */
|
/** Sandbox mode lets us read but not write */
|
||||||
is_sandboxed(): boolean
|
is_sandboxed(): boolean
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import * as matches from "ts-matches"
|
|||||||
import * as YAML from "yaml"
|
import * as YAML from "yaml"
|
||||||
import * as TOML from "@iarna/toml"
|
import * as TOML from "@iarna/toml"
|
||||||
import * as T from "../types"
|
import * as T from "../types"
|
||||||
import { exists } from "."
|
import fs from "fs"
|
||||||
|
|
||||||
const previousPath = /(.+?)\/([^/]*)$/
|
const previousPath = /(.+?)\/([^/]*)$/
|
||||||
|
|
||||||
@@ -54,39 +54,32 @@ const previousPath = /(.+?)\/([^/]*)$/
|
|||||||
export class FileHelper<A> {
|
export class FileHelper<A> {
|
||||||
protected constructor(
|
protected constructor(
|
||||||
readonly path: string,
|
readonly path: string,
|
||||||
readonly volume: string,
|
|
||||||
readonly writeData: (dataIn: A) => string,
|
readonly writeData: (dataIn: A) => string,
|
||||||
readonly readData: (stringValue: string) => A,
|
readonly readData: (stringValue: string) => A,
|
||||||
) {}
|
) {}
|
||||||
async write(data: A, effects: T.Effects) {
|
async write(data: A, effects: T.Effects) {
|
||||||
let matched
|
if (previousPath.exec(this.path)) {
|
||||||
if ((matched = previousPath.exec(this.path))) {
|
await new Promise((resolve, reject) =>
|
||||||
await effects.createDir({
|
fs.mkdir(this.path, (err) => (!err ? resolve(null) : reject(err))),
|
||||||
volumeId: this.volume,
|
)
|
||||||
path: matched[1],
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await effects.writeFile({
|
await new Promise((resolve, reject) =>
|
||||||
path: this.path,
|
fs.writeFile(this.path, this.writeData(data), (err) =>
|
||||||
volumeId: this.volume,
|
!err ? resolve(null) : reject(err),
|
||||||
toWrite: this.writeData(data),
|
),
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
async read(effects: T.Effects) {
|
async read(effects: T.Effects) {
|
||||||
if (
|
if (!fs.existsSync(this.path)) {
|
||||||
!(await exists(effects, {
|
|
||||||
path: this.path,
|
|
||||||
volumeId: this.volume,
|
|
||||||
}))
|
|
||||||
) {
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
return this.readData(
|
return this.readData(
|
||||||
await effects.readFile({
|
await new Promise((resolve, reject) =>
|
||||||
path: this.path,
|
fs.readFile(this.path, (err, data) =>
|
||||||
volumeId: this.volume,
|
!err ? resolve(data.toString("utf-8")) : reject(err),
|
||||||
}),
|
),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -96,23 +89,17 @@ export class FileHelper<A> {
|
|||||||
*/
|
*/
|
||||||
static raw<A>(
|
static raw<A>(
|
||||||
path: string,
|
path: string,
|
||||||
volume: string,
|
|
||||||
toFile: (dataIn: A) => string,
|
toFile: (dataIn: A) => string,
|
||||||
fromFile: (rawData: string) => A,
|
fromFile: (rawData: string) => A,
|
||||||
) {
|
) {
|
||||||
return new FileHelper<A>(path, volume, toFile, fromFile)
|
return new FileHelper<A>(path, toFile, fromFile)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Create a File Helper for a .json file
|
* Create a File Helper for a .json file
|
||||||
*/
|
*/
|
||||||
static json<A>(
|
static json<A>(path: string, shape: matches.Validator<unknown, A>) {
|
||||||
path: string,
|
|
||||||
volume: string,
|
|
||||||
shape: matches.Validator<unknown, A>,
|
|
||||||
) {
|
|
||||||
return new FileHelper<A>(
|
return new FileHelper<A>(
|
||||||
path,
|
path,
|
||||||
volume,
|
|
||||||
(inData) => {
|
(inData) => {
|
||||||
return JSON.stringify(inData, null, 2)
|
return JSON.stringify(inData, null, 2)
|
||||||
},
|
},
|
||||||
@@ -126,12 +113,10 @@ export class FileHelper<A> {
|
|||||||
*/
|
*/
|
||||||
static toml<A extends Record<string, unknown>>(
|
static toml<A extends Record<string, unknown>>(
|
||||||
path: string,
|
path: string,
|
||||||
volume: string,
|
|
||||||
shape: matches.Validator<unknown, A>,
|
shape: matches.Validator<unknown, A>,
|
||||||
) {
|
) {
|
||||||
return new FileHelper<A>(
|
return new FileHelper<A>(
|
||||||
path,
|
path,
|
||||||
volume,
|
|
||||||
(inData) => {
|
(inData) => {
|
||||||
return JSON.stringify(inData, null, 2)
|
return JSON.stringify(inData, null, 2)
|
||||||
},
|
},
|
||||||
@@ -145,12 +130,10 @@ export class FileHelper<A> {
|
|||||||
*/
|
*/
|
||||||
static yaml<A extends Record<string, unknown>>(
|
static yaml<A extends Record<string, unknown>>(
|
||||||
path: string,
|
path: string,
|
||||||
volume: string,
|
|
||||||
shape: matches.Validator<unknown, A>,
|
shape: matches.Validator<unknown, A>,
|
||||||
) {
|
) {
|
||||||
return new FileHelper<A>(
|
return new FileHelper<A>(
|
||||||
path,
|
path,
|
||||||
volume,
|
|
||||||
(inData) => {
|
(inData) => {
|
||||||
return JSON.stringify(inData, null, 2)
|
return JSON.stringify(inData, null, 2)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -30,27 +30,11 @@ T extends object ? {} & {[P in keyof T]: T[P]} :
|
|||||||
|
|
||||||
export type _<T> = FlattenIntersection<T>
|
export type _<T> = FlattenIntersection<T>
|
||||||
|
|
||||||
/** Used to check if the file exists before hand */
|
|
||||||
export const exists = (
|
|
||||||
effects: T.Effects,
|
|
||||||
props: { path: string; volumeId: string },
|
|
||||||
) =>
|
|
||||||
effects.metadata(props).then(
|
|
||||||
(_) => true,
|
|
||||||
(_) => false,
|
|
||||||
)
|
|
||||||
|
|
||||||
export const isKnownError = (e: unknown): e is T.KnownError =>
|
export const isKnownError = (e: unknown): e is T.KnownError =>
|
||||||
e instanceof Object && ("error" in e || "error-code" in e)
|
e instanceof Object && ("error" in e || "error-code" in e)
|
||||||
|
|
||||||
type Cdr<A> = A extends [unknown, ...infer Cdr] ? Cdr : []
|
|
||||||
|
|
||||||
declare const affine: unique symbol
|
declare const affine: unique symbol
|
||||||
|
|
||||||
function withAffine<B>() {
|
|
||||||
return {} as { [affine]: B }
|
|
||||||
}
|
|
||||||
|
|
||||||
export type WrapperDataOptionals<WrapperData, Path extends string> = {
|
export type WrapperDataOptionals<WrapperData, Path extends string> = {
|
||||||
validator?: Parser<unknown, ExtractWrapperData<WrapperData, Path>>
|
validator?: Parser<unknown, ExtractWrapperData<WrapperData, Path>>
|
||||||
/** Defaults to what ever the package currently in */
|
/** Defaults to what ever the package currently in */
|
||||||
@@ -95,7 +79,6 @@ export type Utils<WD, WrapperOverWrite = { const: never }> = {
|
|||||||
bindLan: (port: number) => Promise<LocalBinding>
|
bindLan: (port: number) => Promise<LocalBinding>
|
||||||
networkBuilder: () => NetworkBuilder
|
networkBuilder: () => NetworkBuilder
|
||||||
torHostName: (id: string) => TorHostname
|
torHostName: (id: string) => TorHostname
|
||||||
exists: (props: { path: string; volumeId: string }) => Promise<boolean>
|
|
||||||
nullIfEmpty: typeof nullIfEmpty
|
nullIfEmpty: typeof nullIfEmpty
|
||||||
}
|
}
|
||||||
export const utils = <WrapperData = never, WrapperOverWrite = { const: never }>(
|
export const utils = <WrapperData = never, WrapperOverWrite = { const: never }>(
|
||||||
@@ -106,7 +89,6 @@ export const utils = <WrapperData = never, WrapperOverWrite = { const: never }>(
|
|||||||
readFile: <A>(fileHelper: FileHelper<A>) => fileHelper.read(effects),
|
readFile: <A>(fileHelper: FileHelper<A>) => fileHelper.read(effects),
|
||||||
writeFile: <A>(fileHelper: FileHelper<A>, data: A) =>
|
writeFile: <A>(fileHelper: FileHelper<A>, data: A) =>
|
||||||
fileHelper.write(data, effects),
|
fileHelper.write(data, effects),
|
||||||
exists: (props: { path: string; volumeId: string }) => exists(effects, props),
|
|
||||||
nullIfEmpty,
|
nullIfEmpty,
|
||||||
getWrapperData: <WrapperData = never, Path extends string = never>(
|
getWrapperData: <WrapperData = never, Path extends string = never>(
|
||||||
packageId: string,
|
packageId: string,
|
||||||
|
|||||||
Reference in New Issue
Block a user