mirror of
https://github.com/Start9Labs/start-sdk.git
synced 2026-03-26 02:11:56 +00:00
feat: Change the commands
This commit is contained in:
@@ -22,7 +22,7 @@ import {
|
||||
} from "./types"
|
||||
import * as patterns from "./util/patterns"
|
||||
import { Utils } from "./util/utils"
|
||||
import { DependencyConfig } from "./dependencyConfig/DependencyConfig"
|
||||
import { DependencyConfig, Update } from "./dependencyConfig/DependencyConfig"
|
||||
import { BackupSet, Backups } from "./backup/Backups"
|
||||
import { smtpConfig } from "./config/configConstants"
|
||||
import { Daemons } from "./mainFn/Daemons"
|
||||
@@ -231,18 +231,20 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
|
||||
localConfig,
|
||||
remoteConfig,
|
||||
dependencyConfig,
|
||||
update,
|
||||
}: {
|
||||
localConfig: Config<LocalConfig, Store> | Config<LocalConfig, never>
|
||||
remoteConfig: Config<RemoteConfig, any> | Config<RemoteConfig, never>
|
||||
dependencyConfig: (options: {
|
||||
effects: Effects
|
||||
localConfig: LocalConfig
|
||||
remoteConfig: RemoteConfig
|
||||
utils: Utils<Store>
|
||||
}) => Promise<void | DeepPartial<RemoteConfig>>
|
||||
update?: Update<void | DeepPartial<RemoteConfig>, RemoteConfig>
|
||||
}) {
|
||||
return new DependencyConfig<Store, LocalConfig, RemoteConfig>(
|
||||
dependencyConfig,
|
||||
update,
|
||||
)
|
||||
},
|
||||
},
|
||||
|
||||
@@ -134,15 +134,15 @@ export class Backups<M extends SDKManifest> {
|
||||
// path: item.dstPath,
|
||||
// })
|
||||
// }
|
||||
await effects
|
||||
.runRsync({
|
||||
...item,
|
||||
options: {
|
||||
...this.options,
|
||||
...item.options,
|
||||
},
|
||||
})
|
||||
.wait()
|
||||
// await effects
|
||||
// .runRsync({
|
||||
// ...item,
|
||||
// options: {
|
||||
// ...this.options,
|
||||
// ...item.options,
|
||||
// },
|
||||
// })
|
||||
// .wait()
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -158,18 +158,18 @@ export class Backups<M extends SDKManifest> {
|
||||
// },
|
||||
// )
|
||||
// }
|
||||
await effects
|
||||
.runRsync({
|
||||
options: {
|
||||
...this.options,
|
||||
...item.options,
|
||||
},
|
||||
srcVolume: item.dstVolume,
|
||||
dstVolume: item.srcVolume,
|
||||
srcPath: item.dstPath,
|
||||
dstPath: item.srcPath,
|
||||
})
|
||||
.wait()
|
||||
// await effects
|
||||
// .runRsync({
|
||||
// options: {
|
||||
// ...this.options,
|
||||
// ...item.options,
|
||||
// },
|
||||
// srcVolume: item.dstVolume,
|
||||
// dstVolume: item.srcVolume,
|
||||
// srcPath: item.dstPath,
|
||||
// dstPath: item.srcPath,
|
||||
// })
|
||||
// .wait()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -7,55 +7,39 @@ import { Utils, utils } from "../util/utils"
|
||||
import { deepEqual } from "../util/deepEqual"
|
||||
import { deepMerge } from "../util/deepMerge"
|
||||
|
||||
export type Update<QueryResults, RemoteConfig> = (options: {
|
||||
remoteConfig: RemoteConfig
|
||||
queryResults: QueryResults
|
||||
}) => Promise<RemoteConfig>
|
||||
|
||||
export class DependencyConfig<
|
||||
Store,
|
||||
Input extends Record<string, any>,
|
||||
RemoteConfig extends Record<string, any>,
|
||||
> {
|
||||
static defaultUpdate = async (options: {
|
||||
queryResults: unknown
|
||||
remoteConfig: unknown
|
||||
}): Promise<unknown> => {
|
||||
return deepMerge({}, options.remoteConfig, options.queryResults || {})
|
||||
}
|
||||
constructor(
|
||||
readonly dependencyConfig: (options: {
|
||||
effects: Effects
|
||||
localConfig: Input
|
||||
remoteConfig: RemoteConfig
|
||||
utils: Utils<Store>
|
||||
}) => Promise<void | DeepPartial<RemoteConfig>>,
|
||||
readonly update: Update<
|
||||
void | DeepPartial<RemoteConfig>,
|
||||
RemoteConfig
|
||||
> = DependencyConfig.defaultUpdate as any,
|
||||
) {}
|
||||
|
||||
async check(
|
||||
options: Parameters<DependencyConfigType["check"]>[0],
|
||||
): ReturnType<DependencyConfigType["check"]> {
|
||||
const origConfig = JSON.parse(JSON.stringify(options.localConfig))
|
||||
const newOptions = {
|
||||
...options,
|
||||
utils: utils<Store>(options.effects),
|
||||
async query(options: { effects: Effects; localConfig: unknown }) {
|
||||
return this.dependencyConfig({
|
||||
localConfig: options.localConfig as Input,
|
||||
remoteConfig: options.remoteConfig as RemoteConfig,
|
||||
}
|
||||
if (
|
||||
!deepEqual(
|
||||
origConfig,
|
||||
deepMerge(
|
||||
{},
|
||||
options.localConfig,
|
||||
await this.dependencyConfig(newOptions),
|
||||
),
|
||||
)
|
||||
)
|
||||
throw new Error(`Check failed`)
|
||||
}
|
||||
async autoConfigure(
|
||||
options: Parameters<DependencyConfigType["autoConfigure"]>[0],
|
||||
): ReturnType<DependencyConfigType["autoConfigure"]> {
|
||||
const newOptions = {
|
||||
...options,
|
||||
effects: options.effects,
|
||||
utils: utils<Store>(options.effects),
|
||||
localConfig: options.localConfig as Input,
|
||||
remoteConfig: options.remoteConfig as any,
|
||||
}
|
||||
return deepMerge(
|
||||
{},
|
||||
options.remoteConfig,
|
||||
await this.dependencyConfig(newOptions),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Effects } from "../../types"
|
||||
import { createUtils } from "../../util"
|
||||
import { CheckResult } from "./CheckResult"
|
||||
export function containsAddress(x: string, port: number) {
|
||||
const readPorts = x
|
||||
@@ -26,11 +27,15 @@ export async function checkPortListening(
|
||||
timeout?: number
|
||||
},
|
||||
): Promise<CheckResult> {
|
||||
const utils = createUtils(effects)
|
||||
return Promise.race<CheckResult>([
|
||||
Promise.resolve().then(async () => {
|
||||
const hasAddress =
|
||||
containsAddress(await effects.runCommand(`cat /proc/net/tcp`), port) ||
|
||||
containsAddress(await effects.runCommand("cat /proc/net/udp"), port)
|
||||
containsAddress(
|
||||
await utils.runCommand(`cat /proc/net/tcp`, {}),
|
||||
port,
|
||||
) ||
|
||||
containsAddress(await utils.runCommand("cat /proc/net/udp", {}), port)
|
||||
if (hasAddress) {
|
||||
return { status: "passing", message: options.successMessage }
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Effects } from "../../types"
|
||||
import { CheckResult } from "./CheckResult"
|
||||
import { timeoutPromise } from "./index"
|
||||
import fetch from "node-fetch"
|
||||
|
||||
/**
|
||||
* This is a helper function to check if a web url is reachable.
|
||||
@@ -17,7 +18,7 @@ export const checkWebUrl = async (
|
||||
errorMessage = `Error while fetching URL: ${url}`,
|
||||
} = {},
|
||||
): Promise<CheckResult> => {
|
||||
return Promise.race([effects.fetch(url), timeoutPromise(timeout)])
|
||||
return Promise.race([fetch(url), timeoutPromise(timeout)])
|
||||
.then((x) => ({
|
||||
status: "passing" as const,
|
||||
message: successMessage,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { CommandType, Effects } from "../../types"
|
||||
import { createUtils } from "../../util"
|
||||
import { CheckResult } from "./CheckResult"
|
||||
import { timeoutPromise } from "./index"
|
||||
|
||||
@@ -9,9 +10,9 @@ import { timeoutPromise } from "./index"
|
||||
* @param param0
|
||||
* @returns
|
||||
*/
|
||||
export const runHealthScript = async <A extends string>(
|
||||
export const runHealthScript = async (
|
||||
effects: Effects,
|
||||
runCommand: CommandType<A>,
|
||||
runCommand: string,
|
||||
{
|
||||
timeout = 30000,
|
||||
errorMessage = `Error while running command: ${runCommand}`,
|
||||
@@ -19,8 +20,9 @@ export const runHealthScript = async <A extends string>(
|
||||
`Have ran script ${runCommand} and the result: ${res}`,
|
||||
} = {},
|
||||
): Promise<CheckResult> => {
|
||||
const utils = createUtils(effects)
|
||||
const res = await Promise.race([
|
||||
effects.runCommand(runCommand, { timeoutMillis: timeout }),
|
||||
utils.runCommand(runCommand, { timeout }),
|
||||
timeoutPromise(timeout),
|
||||
]).catch((e) => {
|
||||
console.warn(errorMessage)
|
||||
|
||||
@@ -4,9 +4,10 @@ import { Trigger } from "../trigger"
|
||||
import { TriggerInput } from "../trigger/TriggerInput"
|
||||
import { defaultTrigger } from "../trigger/defaultTrigger"
|
||||
import { DaemonReturned, Effects, ValidIfNoStupidEscape } from "../types"
|
||||
import { createUtils } from "../util"
|
||||
type Daemon<Ids extends string, Command extends string, Id extends string> = {
|
||||
id: "" extends Id ? never : Id
|
||||
command: ValidIfNoStupidEscape<Command> | [string, ...string[]]
|
||||
command: string
|
||||
env?: Record<string, string>
|
||||
ready: {
|
||||
display: string | null
|
||||
@@ -95,8 +96,9 @@ export class Daemons<Ids extends string> {
|
||||
)
|
||||
daemonsStarted[daemon.id] = requiredPromise.then(async () => {
|
||||
const { command } = daemon
|
||||
const utils = createUtils(effects)
|
||||
|
||||
const child = effects.runDaemon(command, { env: daemon.env })
|
||||
const child = utils.runDaemon(command, { env: daemon.env })
|
||||
let currentInput: TriggerInput = {}
|
||||
const getCurrentInput = () => currentInput
|
||||
const trigger = (daemon.ready.trigger ?? defaultTrigger)(
|
||||
|
||||
15
lib/types.ts
15
lib/types.ts
@@ -97,16 +97,11 @@ export type VersionString = string
|
||||
* this is used to make sure that other dependencies have the values that this service could use.
|
||||
*/
|
||||
export type DependencyConfig = {
|
||||
/** Checks are called to make sure that our dependency is in the correct shape. If a known error is returned we know that the dependency needs modification */
|
||||
check(options: {
|
||||
effects: Effects
|
||||
localConfig: unknown
|
||||
remoteConfig: unknown
|
||||
}): Promise<void>
|
||||
/** This is called after we know that the dependency package needs a new configuration, this would be a transform for defaults */
|
||||
autoConfigure(options: {
|
||||
effects: Effects
|
||||
localConfig: unknown
|
||||
/** During autoconfigure, we have access to effects and local data. We are going to figure out all the data that we need and send it to update. For the sdk it is the desired delta */
|
||||
query(options: { effects: Effects; localConfig: unknown }): Promise<unknown>
|
||||
/** This is the second part. Given the query results off the previous function, we will determine what to change the remote config to. In our sdk normall we are going to use the previous as a deep merge. */
|
||||
update(options: {
|
||||
queryResults: unknown
|
||||
remoteConfig: unknown
|
||||
}): Promise<unknown>
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
checkWebUrl,
|
||||
} from "../health/checkFns"
|
||||
import {
|
||||
DaemonReturned,
|
||||
Effects,
|
||||
EnsureStorePath,
|
||||
ExtractStore,
|
||||
@@ -34,6 +35,8 @@ import {
|
||||
getNetworkInterfaces,
|
||||
} from "./getNetworkInterfaces"
|
||||
|
||||
import { exec } from "node:child_process"
|
||||
|
||||
export type Utils<Store, WrapperOverWrite = { const: never }> = {
|
||||
checkPortListening(
|
||||
port: number,
|
||||
@@ -91,6 +94,14 @@ export type Utils<Store, WrapperOverWrite = { const: never }> = {
|
||||
}
|
||||
nullIfEmpty: typeof nullIfEmpty
|
||||
readFile: <A>(fileHelper: FileHelper<A>) => ReturnType<FileHelper<A>["read"]>
|
||||
runDaemon: (
|
||||
command: string,
|
||||
options: { env?: Record<string, string> },
|
||||
) => Promise<DaemonReturned>
|
||||
runCommand: (
|
||||
command: string,
|
||||
options: { env?: Record<string, string>; timeout?: number },
|
||||
) => Promise<string>
|
||||
store: {
|
||||
get: <Path extends string>(
|
||||
packageId: string,
|
||||
@@ -111,71 +122,113 @@ export type Utils<Store, WrapperOverWrite = { const: never }> = {
|
||||
}
|
||||
export const utils = <Store = never, WrapperOverWrite = { const: never }>(
|
||||
effects: Effects,
|
||||
): Utils<Store, WrapperOverWrite> => ({
|
||||
createInterface: (options: {
|
||||
name: string
|
||||
id: string
|
||||
description: string
|
||||
hasPrimary: boolean
|
||||
disabled: boolean
|
||||
ui: boolean
|
||||
username: null | string
|
||||
path: string
|
||||
search: Record<string, string>
|
||||
}) => new NetworkInterfaceBuilder({ ...options, effects }),
|
||||
getSystemSmtp: () =>
|
||||
new GetSystemSmtp(effects) as GetSystemSmtp & WrapperOverWrite,
|
||||
): Utils<Store, WrapperOverWrite> => {
|
||||
return {
|
||||
createInterface: (options: {
|
||||
name: string
|
||||
id: string
|
||||
description: string
|
||||
hasPrimary: boolean
|
||||
disabled: boolean
|
||||
ui: boolean
|
||||
username: null | string
|
||||
path: string
|
||||
search: Record<string, string>
|
||||
}) => new NetworkInterfaceBuilder({ ...options, effects }),
|
||||
getSystemSmtp: () =>
|
||||
new GetSystemSmtp(effects) as GetSystemSmtp & WrapperOverWrite,
|
||||
|
||||
host: {
|
||||
static: (id: string) => new StaticHost({ id, effects }),
|
||||
single: (id: string) => new SingleHost({ id, effects }),
|
||||
multi: (id: string) => new MultiHost({ id, effects }),
|
||||
},
|
||||
readFile: <A>(fileHelper: FileHelper<A>) => fileHelper.read(effects),
|
||||
writeFile: <A>(fileHelper: FileHelper<A>, data: A) =>
|
||||
fileHelper.write(data, effects),
|
||||
nullIfEmpty,
|
||||
host: {
|
||||
static: (id: string) => new StaticHost({ id, effects }),
|
||||
single: (id: string) => new SingleHost({ id, effects }),
|
||||
multi: (id: string) => new MultiHost({ id, effects }),
|
||||
},
|
||||
readFile: <A>(fileHelper: FileHelper<A>) => fileHelper.read(effects),
|
||||
writeFile: <A>(fileHelper: FileHelper<A>, data: A) =>
|
||||
fileHelper.write(data, effects),
|
||||
nullIfEmpty,
|
||||
|
||||
networkInterface: {
|
||||
getOwn: (interfaceId: InterfaceId) =>
|
||||
getNetworkInterface(effects, { interfaceId }) as GetNetworkInterface &
|
||||
WrapperOverWrite,
|
||||
get: (opts: { interfaceId: InterfaceId; packageId: PackageId }) =>
|
||||
getNetworkInterface(effects, opts) as GetNetworkInterface &
|
||||
WrapperOverWrite,
|
||||
getAllOwn: () =>
|
||||
getNetworkInterfaces(effects, {}) as GetNetworkInterfaces &
|
||||
WrapperOverWrite,
|
||||
getAll: (opts: { packageId: PackageId }) =>
|
||||
getNetworkInterfaces(effects, opts) as GetNetworkInterfaces &
|
||||
WrapperOverWrite,
|
||||
},
|
||||
store: {
|
||||
get: <Path extends string = never>(
|
||||
packageId: string,
|
||||
path: EnsureStorePath<Store, Path>,
|
||||
) =>
|
||||
getStore<Store, Path>(effects, path as any, {
|
||||
packageId,
|
||||
}) as any,
|
||||
getOwn: <Path extends string>(path: EnsureStorePath<Store, Path>) =>
|
||||
getStore<Store, Path>(effects, path as any) as any,
|
||||
setOwn: <Path extends string | never>(
|
||||
path: EnsureStorePath<Store, Path>,
|
||||
value: ExtractStore<Store, Path>,
|
||||
) => effects.store.set<Store, Path>({ value, path: path as any }),
|
||||
},
|
||||
checkPortListening: checkPortListening.bind(null, effects),
|
||||
checkWebUrl: checkWebUrl.bind(null, effects),
|
||||
networkInterface: {
|
||||
getOwn: (interfaceId: InterfaceId) =>
|
||||
getNetworkInterface(effects, { interfaceId }) as GetNetworkInterface &
|
||||
WrapperOverWrite,
|
||||
get: (opts: { interfaceId: InterfaceId; packageId: PackageId }) =>
|
||||
getNetworkInterface(effects, opts) as GetNetworkInterface &
|
||||
WrapperOverWrite,
|
||||
getAllOwn: () =>
|
||||
getNetworkInterfaces(effects, {}) as GetNetworkInterfaces &
|
||||
WrapperOverWrite,
|
||||
getAll: (opts: { packageId: PackageId }) =>
|
||||
getNetworkInterfaces(effects, opts) as GetNetworkInterfaces &
|
||||
WrapperOverWrite,
|
||||
},
|
||||
store: {
|
||||
get: <Path extends string = never>(
|
||||
packageId: string,
|
||||
path: EnsureStorePath<Store, Path>,
|
||||
) =>
|
||||
getStore<Store, Path>(effects, path as any, {
|
||||
packageId,
|
||||
}) as any,
|
||||
getOwn: <Path extends string>(path: EnsureStorePath<Store, Path>) =>
|
||||
getStore<Store, Path>(effects, path as any) as any,
|
||||
setOwn: <Path extends string | never>(
|
||||
path: EnsureStorePath<Store, Path>,
|
||||
value: ExtractStore<Store, Path>,
|
||||
) => effects.store.set<Store, Path>({ value, path: path as any }),
|
||||
},
|
||||
|
||||
mountDependencies: <
|
||||
In extends
|
||||
| Record<ManifestId, Record<VolumeName, Record<NamedPath, Path>>>
|
||||
| Record<VolumeName, Record<NamedPath, Path>>
|
||||
| Record<NamedPath, Path>
|
||||
| Path,
|
||||
>(
|
||||
value: In,
|
||||
) => mountDependencies(effects, value),
|
||||
})
|
||||
runDaemon: async (
|
||||
command: string,
|
||||
options: { env?: Record<string, string> },
|
||||
): Promise<DaemonReturned> => {
|
||||
let childProcess: null | {
|
||||
kill(signal?: number | string): void
|
||||
} = null
|
||||
const answer = new Promise<string>(
|
||||
(resolve, reject) =>
|
||||
(childProcess = exec(command, options, (error, stdout, stderr) => {
|
||||
if (error) return reject(error.toString())
|
||||
if (stderr) return reject(stderr.toString())
|
||||
return resolve(stdout.toString())
|
||||
})),
|
||||
)
|
||||
|
||||
return {
|
||||
wait() {
|
||||
return answer
|
||||
},
|
||||
async term() {
|
||||
childProcess?.kill()
|
||||
},
|
||||
}
|
||||
},
|
||||
runCommand: async (
|
||||
command: string,
|
||||
options: { env?: Record<string, string>; timeout?: number },
|
||||
): Promise<string> => {
|
||||
const answer = new Promise<string>((resolve, reject) =>
|
||||
exec(command, options, (error, stdout, stderr) => {
|
||||
if (error) return reject(error.toString())
|
||||
if (stderr) return reject(stderr.toString())
|
||||
return resolve(stdout.toString())
|
||||
}),
|
||||
)
|
||||
|
||||
return answer
|
||||
},
|
||||
checkPortListening: checkPortListening.bind(null, effects),
|
||||
checkWebUrl: checkWebUrl.bind(null, effects),
|
||||
|
||||
mountDependencies: <
|
||||
In extends
|
||||
| Record<ManifestId, Record<VolumeName, Record<NamedPath, Path>>>
|
||||
| Record<VolumeName, Record<NamedPath, Path>>
|
||||
| Record<NamedPath, Path>
|
||||
| Path,
|
||||
>(
|
||||
value: In,
|
||||
) => mountDependencies(effects, value),
|
||||
}
|
||||
}
|
||||
function noop(): void {}
|
||||
|
||||
85
package-lock.json
generated
85
package-lock.json
generated
@@ -10,6 +10,7 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@iarna/toml": "^2.2.5",
|
||||
"node-fetch": "^3.3.1",
|
||||
"ts-matches": "^5.4.1",
|
||||
"yaml": "^2.2.2"
|
||||
},
|
||||
@@ -2205,6 +2206,14 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/data-uri-to-buffer": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
|
||||
"integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
@@ -2471,6 +2480,28 @@
|
||||
"bser": "2.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/fetch-blob": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
|
||||
"integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/jimmywarting"
|
||||
},
|
||||
{
|
||||
"type": "paypal",
|
||||
"url": "https://paypal.me/jimmywarting"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"node-domexception": "^1.0.0",
|
||||
"web-streams-polyfill": "^3.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.20 || >= 14.13"
|
||||
}
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
@@ -2496,6 +2527,17 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/formdata-polyfill": {
|
||||
"version": "4.0.10",
|
||||
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
|
||||
"integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
|
||||
"dependencies": {
|
||||
"fetch-blob": "^3.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.20.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
@@ -3719,6 +3761,41 @@
|
||||
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/node-domexception": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
|
||||
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/jimmywarting"
|
||||
},
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://paypal.me/jimmywarting"
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz",
|
||||
"integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==",
|
||||
"dependencies": {
|
||||
"data-uri-to-buffer": "^4.0.0",
|
||||
"fetch-blob": "^3.1.4",
|
||||
"formdata-polyfill": "^4.0.10"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/node-fetch"
|
||||
}
|
||||
},
|
||||
"node_modules/node-int64": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
|
||||
@@ -5107,6 +5184,14 @@
|
||||
"makeerror": "1.0.12"
|
||||
}
|
||||
},
|
||||
"node_modules/web-streams-polyfill": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
|
||||
"integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==",
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
"homepage": "https://github.com/Start9Labs/start-sdk#readme",
|
||||
"dependencies": {
|
||||
"@iarna/toml": "^2.2.5",
|
||||
"node-fetch": "^3.3.1",
|
||||
"ts-matches": "^5.4.1",
|
||||
"yaml": "^2.2.2"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user