mirror of
https://github.com/Start9Labs/start-sdk.git
synced 2026-03-26 02:11:56 +00:00
feat: creating the rest of the sdk
This commit is contained in:
202
lib/StartSDK.ts
202
lib/StartSDK.ts
@@ -1,11 +1,13 @@
|
||||
import { AnyParser } from "ts-matches"
|
||||
import { SDKManifest } from "./manifest/ManifestTypes"
|
||||
import { ManifestVersion, SDKManifest } from "./manifest/ManifestTypes"
|
||||
import { RequiredDefault, Value } from "./config/builder/value"
|
||||
import { Config, ExtractConfigType, LazyBuild } from "./config/builder/config"
|
||||
import {
|
||||
DefaultString,
|
||||
ListValueSpecText,
|
||||
Pattern,
|
||||
RandomString,
|
||||
UniqueBy,
|
||||
ValueSpecDatetime,
|
||||
ValueSpecText,
|
||||
} from "./config/configTypes"
|
||||
@@ -18,10 +20,34 @@ import {
|
||||
Metadata,
|
||||
BackupOptions,
|
||||
} from "./types"
|
||||
import { Utils } from "./util"
|
||||
import { Utils } from "./util/utils"
|
||||
import { AutoConfig, AutoConfigFrom } from "./autoconfig/AutoConfig"
|
||||
import { BackupSet, Backups } from "./backup/Backups"
|
||||
import { smtpConfig } from "./config/configConstants"
|
||||
import { Daemons } from "./mainFn/Daemons"
|
||||
import { healthCheck } from "./health/HealthCheck"
|
||||
import {
|
||||
checkPortListening,
|
||||
containsAddress,
|
||||
} from "./health/checkFns/checkPortListening"
|
||||
import { checkWebUrl, runHealthScript } from "./health/checkFns"
|
||||
import { List } from "./config/builder/list"
|
||||
import { Migration } from "./inits/migrations/Migration"
|
||||
import { Install, InstallFn, setupInstall } from "./inits/setupInstall"
|
||||
import { setupActions } from "./actions/setupActions"
|
||||
import { setupAutoConfig } from "./autoconfig/setupAutoConfig"
|
||||
import { SetupBackupsParams, setupBackups } from "./backup/setupBackups"
|
||||
import { setupInit } from "./inits/setupInit"
|
||||
import {
|
||||
EnsureUniqueId,
|
||||
Migrations,
|
||||
setupMigrations,
|
||||
} from "./inits/migrations/setupMigrations"
|
||||
import { Uninstall, UninstallFn, setupUninstall } from "./inits/setupUninstall"
|
||||
import { setupMain } from "./mainFn"
|
||||
import { defaultTrigger } from "./trigger/defaultTrigger"
|
||||
import { changeOnFirstSuccess, cooldownTrigger } from "./trigger"
|
||||
import setupConfig, { Read, Save } from "./config/setupConfig"
|
||||
|
||||
// prettier-ignore
|
||||
type AnyNeverCond<T extends any[], Then, Else> =
|
||||
@@ -30,7 +56,7 @@ type AnyNeverCond<T extends any[], Then, Else> =
|
||||
T extends [any, ...infer U] ? AnyNeverCond<U,Then, Else> :
|
||||
never
|
||||
|
||||
class StartSDK<Manifest extends SDKManifest, Store> {
|
||||
export class StartSDK<Manifest extends SDKManifest, Store> {
|
||||
private constructor() {}
|
||||
private anyOf<A>(
|
||||
a: A,
|
||||
@@ -65,10 +91,10 @@ class StartSDK<Manifest extends SDKManifest, Store> {
|
||||
},
|
||||
Config: {
|
||||
of: <
|
||||
Spec extends Record<string, Value<any, Manifest> | Value<any, never>>,
|
||||
Spec extends Record<string, Value<any, Store> | Value<any, never>>,
|
||||
>(
|
||||
spec: Spec,
|
||||
) => Config.of(spec),
|
||||
) => Config.of<Spec, Store>(spec),
|
||||
},
|
||||
configConstants: { smtpConfig },
|
||||
createAction: <
|
||||
@@ -88,22 +114,137 @@ class StartSDK<Manifest extends SDKManifest, Store> {
|
||||
input: Type
|
||||
}) => Promise<ActionResult>,
|
||||
) => createAction<Store, ConfigType, Type>(metaData, fn),
|
||||
// TODO Daemons
|
||||
// TODO HealthCheck
|
||||
// TODO healthCheckFns
|
||||
// TODO List
|
||||
// TODO mainNetwork
|
||||
// TODO Migration
|
||||
// TODO setupActions
|
||||
// TODO setupAutoConfig
|
||||
// TODO setupBackup
|
||||
// TODO setupInit
|
||||
// TODO setupInstall
|
||||
// TODO setupMain
|
||||
// TODO setupManifest
|
||||
// TODO setupMigrations
|
||||
// TODO setupUninstall
|
||||
// TODO trigger changeOnFirstSuccess, cooldown, default
|
||||
Daemons: { of: Daemons.of },
|
||||
healthCheck: {
|
||||
checkPortListening,
|
||||
checkWebUrl,
|
||||
of: healthCheck,
|
||||
runHealthScript,
|
||||
},
|
||||
List: {
|
||||
text: List.text,
|
||||
number: List.number,
|
||||
obj: <Type extends Record<string, any>>(
|
||||
a: {
|
||||
name: string
|
||||
description?: string | null
|
||||
warning?: string | null
|
||||
/** Default [] */
|
||||
default?: []
|
||||
minLength?: number | null
|
||||
maxLength?: number | null
|
||||
},
|
||||
aSpec: {
|
||||
spec: Config<Type, Store>
|
||||
displayAs?: null | string
|
||||
uniqueBy?: null | UniqueBy
|
||||
},
|
||||
) => List.obj<Type, Store>(a, aSpec),
|
||||
dynamicText: (
|
||||
getA: LazyBuild<
|
||||
Store,
|
||||
{
|
||||
name: string
|
||||
description?: string | null
|
||||
warning?: string | null
|
||||
/** Default = [] */
|
||||
default?: string[]
|
||||
minLength?: number | null
|
||||
maxLength?: number | null
|
||||
disabled?: false | string
|
||||
generate?: null | RandomString
|
||||
spec: {
|
||||
/** Default = false */
|
||||
masked?: boolean
|
||||
placeholder?: string | null
|
||||
minLength?: number | null
|
||||
maxLength?: number | null
|
||||
patterns: Pattern[]
|
||||
/** Default = "text" */
|
||||
inputmode?: ListValueSpecText["inputmode"]
|
||||
}
|
||||
}
|
||||
>,
|
||||
) => List.dynamicText<Store>(getA),
|
||||
dynamicNumber: (
|
||||
getA: LazyBuild<
|
||||
Store,
|
||||
{
|
||||
name: string
|
||||
description?: string | null
|
||||
warning?: string | null
|
||||
/** Default = [] */
|
||||
default?: string[]
|
||||
minLength?: number | null
|
||||
maxLength?: number | null
|
||||
disabled?: false | string
|
||||
spec: {
|
||||
integer: boolean
|
||||
min?: number | null
|
||||
max?: number | null
|
||||
step?: string | null
|
||||
units?: string | null
|
||||
placeholder?: string | null
|
||||
}
|
||||
}
|
||||
>,
|
||||
) => List.dynamicNumber<Store>(getA),
|
||||
},
|
||||
Migration: {
|
||||
of: <Version extends ManifestVersion>(options: {
|
||||
version: Version
|
||||
up: (opts: { effects: Effects; utils: Utils<Store> }) => Promise<void>
|
||||
down: (opts: {
|
||||
effects: Effects
|
||||
utils: Utils<Store>
|
||||
}) => Promise<void>
|
||||
}) => Migration.of<Store, Version>(options),
|
||||
},
|
||||
setupActions,
|
||||
setupAutoConfig: <
|
||||
Input,
|
||||
NestedConfigs extends {
|
||||
[key in keyof Manifest["dependencies"]]: unknown
|
||||
},
|
||||
>(
|
||||
configs: AutoConfigFrom<Store, Input, NestedConfigs>,
|
||||
) => setupAutoConfig<Store, Input, Manifest, NestedConfigs>(configs),
|
||||
setupBackups: (...args: SetupBackupsParams<Manifest>) =>
|
||||
setupBackups<Manifest>(...args),
|
||||
setupConfig: <
|
||||
ConfigType extends
|
||||
| Record<string, any>
|
||||
| Config<any, any>
|
||||
| Config<any, never>,
|
||||
Type extends Record<string, any> = ExtractConfigType<ConfigType>,
|
||||
>(
|
||||
spec: Config<Type, Store> | Config<Type, never>,
|
||||
write: Save<Store, Type, Manifest>,
|
||||
read: Read<Store, Type>,
|
||||
) => setupConfig<Store, ConfigType, Manifest, Type>(spec, write, read),
|
||||
setupInit: (
|
||||
migrations: Migrations<Store>,
|
||||
install: Install<Store>,
|
||||
uninstall: Uninstall<Store>,
|
||||
) => setupInit<Store>(migrations, install, uninstall),
|
||||
setupInstall: (fn: InstallFn<Store>) => Install.of(fn),
|
||||
setupMain: (
|
||||
fn: (o: {
|
||||
effects: Effects
|
||||
started(onTerm: () => void): null
|
||||
utils: Utils<Store, {}>
|
||||
}) => Promise<Daemons<any>>,
|
||||
) => setupMain<Store>(fn),
|
||||
setupMigrations: <Migrations extends Array<Migration<Store, any>>>(
|
||||
manifest: SDKManifest,
|
||||
...migrations: EnsureUniqueId<Migrations>
|
||||
) => setupMigrations<Store, Migrations>(manifest, ...migrations),
|
||||
setupUninstall: (fn: UninstallFn<Store>) => setupUninstall<Store>(fn),
|
||||
trigger: {
|
||||
defaultTrigger,
|
||||
cooldownTrigger,
|
||||
changeOnFirstSuccess,
|
||||
},
|
||||
Value: {
|
||||
toggle: Value.toggle,
|
||||
text: Value.text,
|
||||
@@ -261,13 +402,18 @@ class StartSDK<Manifest extends SDKManifest, Store> {
|
||||
aVariants,
|
||||
),
|
||||
},
|
||||
// TODO Variants
|
||||
Variants: {
|
||||
of: <
|
||||
VariantValues extends {
|
||||
[K in string]: {
|
||||
name: string
|
||||
spec: Config<any, Store>
|
||||
}
|
||||
},
|
||||
>(
|
||||
a: VariantValues,
|
||||
) => Variants.of<VariantValues, Store>(a),
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
// TODO Test output.ts with sdk
|
||||
|
||||
// const test = StartSDK.of()
|
||||
// .withManifest<any>()
|
||||
// .withStore<{}>()
|
||||
// .Value.dynamicToggle({} as any, {} as any)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Config, ExtractConfigType } from "../config/builder/config"
|
||||
import { ActionMetaData, ActionResult, Effects, ExportedAction } from "../types"
|
||||
import { Utils, createUtils, utils } from "../util"
|
||||
import { createUtils } from "../util"
|
||||
import { Utils, utils } from "../util/utils"
|
||||
|
||||
export class CreatedAction<
|
||||
Store,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { AutoConfigure, DeepPartial, Effects, ExpectedExports } from "../types"
|
||||
import { Utils, utils } from "../util"
|
||||
import { Utils, utils } from "../util/utils"
|
||||
import { deepEqual } from "../util/deepEqual"
|
||||
import { deepMerge } from "../util/deepMerge"
|
||||
|
||||
|
||||
@@ -1,28 +1,24 @@
|
||||
import { SDKManifest } from "../manifest/ManifestTypes"
|
||||
import { WrapperDataContract } from "../wrapperData/wrapperDataContract"
|
||||
import { AutoConfig, AutoConfigFrom } from "./AutoConfig"
|
||||
|
||||
export function setupAutoConfig<
|
||||
WD,
|
||||
Store,
|
||||
Input,
|
||||
Manifest extends SDKManifest,
|
||||
NestedConfigs extends {
|
||||
[key in keyof Manifest["dependencies"]]: unknown
|
||||
},
|
||||
>(
|
||||
wrapperDataContract: WrapperDataContract<WD>,
|
||||
configs: AutoConfigFrom<WD, Input, NestedConfigs>,
|
||||
) {
|
||||
>(configs: AutoConfigFrom<Store, Input, NestedConfigs>) {
|
||||
type C = typeof configs
|
||||
const answer = { ...configs } as unknown as {
|
||||
[k in keyof C]: AutoConfig<WD, Input, NestedConfigs>
|
||||
[k in keyof C]: AutoConfig<Store, Input, NestedConfigs>
|
||||
}
|
||||
for (const key in configs) {
|
||||
answer[key as keyof typeof configs] = new AutoConfig<
|
||||
WD,
|
||||
Store,
|
||||
Input,
|
||||
NestedConfigs
|
||||
>(wrapperDataContract, configs, key as keyof typeof configs)
|
||||
>(configs, key as keyof typeof configs)
|
||||
}
|
||||
return answer
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import { ValueSpec } from "../configTypes"
|
||||
import { Utils } from "../../util"
|
||||
import { Utils } from "../../util/utils"
|
||||
import { Value } from "./value"
|
||||
import { _ } from "../../util"
|
||||
import { Effects } from "../../types"
|
||||
import { Parser, object } from "ts-matches"
|
||||
|
||||
export type LazyBuildOptions<WD> = {
|
||||
export type LazyBuildOptions<Store> = {
|
||||
effects: Effects
|
||||
utils: Utils<WD>
|
||||
utils: Utils<Store>
|
||||
}
|
||||
export type LazyBuild<WD, ExpectedOut> = (
|
||||
options: LazyBuildOptions<WD>,
|
||||
export type LazyBuild<Store, ExpectedOut> = (
|
||||
options: LazyBuildOptions<Store>,
|
||||
) => Promise<ExpectedOut> | ExpectedOut
|
||||
|
||||
// prettier-ignore
|
||||
@@ -18,8 +18,8 @@ export type ExtractConfigType<A extends Record<string, any> | Config<Record<stri
|
||||
A extends Config<infer B, any> | Config<infer B, never> ? B :
|
||||
A
|
||||
|
||||
export type ConfigSpecOf<A extends Record<string, any>, WD = never> = {
|
||||
[K in keyof A]: Value<A[K], WD>
|
||||
export type ConfigSpecOf<A extends Record<string, any>, Store = never> = {
|
||||
[K in keyof A]: Value<A[K], Store>
|
||||
}
|
||||
|
||||
export type MaybeLazyValues<A> = LazyBuild<any, A> | A
|
||||
@@ -79,14 +79,14 @@ export const addNodesSpec = Config.of({ hostname: hostname, port: port });
|
||||
|
||||
```
|
||||
*/
|
||||
export class Config<Type extends Record<string, any>, WD> {
|
||||
export class Config<Type extends Record<string, any>, Store> {
|
||||
private constructor(
|
||||
private readonly spec: {
|
||||
[K in keyof Type]: Value<Type[K], WD> | Value<Type[K], never>
|
||||
[K in keyof Type]: Value<Type[K], Store> | Value<Type[K], never>
|
||||
},
|
||||
public validator: Parser<unknown, Type>,
|
||||
) {}
|
||||
async build(options: LazyBuildOptions<WD>) {
|
||||
async build(options: LazyBuildOptions<Store>) {
|
||||
const answer = {} as {
|
||||
[K in keyof Type]: ValueSpec
|
||||
}
|
||||
@@ -96,9 +96,10 @@ export class Config<Type extends Record<string, any>, WD> {
|
||||
return answer
|
||||
}
|
||||
|
||||
static of<Spec extends Record<string, Value<any, any> | Value<any, never>>>(
|
||||
spec: Spec,
|
||||
) {
|
||||
static of<
|
||||
Spec extends Record<string, Value<any, Store> | Value<any, never>>,
|
||||
Store,
|
||||
>(spec: Spec) {
|
||||
const validatorObj = {} as {
|
||||
[K in keyof Spec]: Parser<unknown, any>
|
||||
}
|
||||
@@ -109,14 +110,12 @@ export class Config<Type extends Record<string, any>, WD> {
|
||||
return new Config<
|
||||
{
|
||||
[K in keyof Spec]: Spec[K] extends
|
||||
| Value<infer T, any>
|
||||
| Value<infer T, Store>
|
||||
| Value<infer T, never>
|
||||
? T
|
||||
: never
|
||||
},
|
||||
{
|
||||
[K in keyof Spec]: Spec[K] extends Value<any, infer WD> ? WD : never
|
||||
}[keyof Spec]
|
||||
Store
|
||||
>(spec, validator as any)
|
||||
}
|
||||
|
||||
@@ -129,12 +128,12 @@ export class Config<Type extends Record<string, any>, WD> {
|
||||
required: false,
|
||||
})
|
||||
|
||||
return Config.of<WrapperData>()({
|
||||
myValue: a.withWrapperData(),
|
||||
return Config.of<Store>()({
|
||||
myValue: a.withStore(),
|
||||
})
|
||||
```
|
||||
*/
|
||||
withWrapperData<NewWrapperData extends WD extends never ? any : WD>() {
|
||||
return this as any as Config<Type, NewWrapperData>
|
||||
withStore<NewStore extends Store extends never ? any : Store>() {
|
||||
return this as any as Config<Type, NewStore>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
ValueSpecText,
|
||||
} from "../configTypes"
|
||||
import { Parser, arrayOf, number, string } from "ts-matches"
|
||||
import { WrapperDataContract } from "../../wrapperData/wrapperDataContract"
|
||||
/**
|
||||
* Used as a subtype of Value.list
|
||||
```ts
|
||||
@@ -23,9 +22,9 @@ export const authorizationList = List.string({
|
||||
export const auth = Value.list(authorizationList);
|
||||
```
|
||||
*/
|
||||
export class List<Type, WD> {
|
||||
export class List<Type, Store> {
|
||||
private constructor(
|
||||
public build: LazyBuild<WD, ValueSpecList>,
|
||||
public build: LazyBuild<Store, ValueSpecList>,
|
||||
public validator: Parser<unknown, Type>,
|
||||
) {}
|
||||
static text(
|
||||
@@ -74,10 +73,9 @@ export class List<Type, WD> {
|
||||
} satisfies ValueSpecListOf<"text">
|
||||
}, arrayOf(string))
|
||||
}
|
||||
static dynamicText<WD = never>(
|
||||
_wrapperDataContract: WrapperDataContract<WD>,
|
||||
static dynamicText<Store = never>(
|
||||
getA: LazyBuild<
|
||||
WD,
|
||||
Store,
|
||||
{
|
||||
name: string
|
||||
description?: string | null
|
||||
@@ -101,7 +99,7 @@ export class List<Type, WD> {
|
||||
}
|
||||
>,
|
||||
) {
|
||||
return new List<string[], WD>(async (options) => {
|
||||
return new List<string[], Store>(async (options) => {
|
||||
const { spec: aSpec, ...a } = await getA(options)
|
||||
const spec = {
|
||||
type: "text" as const,
|
||||
@@ -168,10 +166,9 @@ export class List<Type, WD> {
|
||||
} satisfies ValueSpecListOf<"number">
|
||||
}, arrayOf(number))
|
||||
}
|
||||
static dynamicNumber<WD = never>(
|
||||
_wrapperDataContract: WrapperDataContract<WD>,
|
||||
static dynamicNumber<Store = never>(
|
||||
getA: LazyBuild<
|
||||
WD,
|
||||
Store,
|
||||
{
|
||||
name: string
|
||||
description?: string | null
|
||||
@@ -192,7 +189,7 @@ export class List<Type, WD> {
|
||||
}
|
||||
>,
|
||||
) {
|
||||
return new List<number[], WD>(async (options) => {
|
||||
return new List<number[], Store>(async (options) => {
|
||||
const { spec: aSpec, ...a } = await getA(options)
|
||||
const spec = {
|
||||
type: "number" as const,
|
||||
@@ -216,7 +213,7 @@ export class List<Type, WD> {
|
||||
}
|
||||
}, arrayOf(number))
|
||||
}
|
||||
static obj<Type extends Record<string, any>, WrapperData>(
|
||||
static obj<Type extends Record<string, any>, Store>(
|
||||
a: {
|
||||
name: string
|
||||
description?: string | null
|
||||
@@ -227,12 +224,12 @@ export class List<Type, WD> {
|
||||
maxLength?: number | null
|
||||
},
|
||||
aSpec: {
|
||||
spec: Config<Type, WrapperData>
|
||||
spec: Config<Type, Store>
|
||||
displayAs?: null | string
|
||||
uniqueBy?: null | UniqueBy
|
||||
},
|
||||
) {
|
||||
return new List<Type[], WrapperData>(async (options) => {
|
||||
return new List<Type[], Store>(async (options) => {
|
||||
const { spec: previousSpecSpec, ...restSpec } = aSpec
|
||||
const specSpec = await previousSpecSpec.build(options)
|
||||
const spec = {
|
||||
@@ -268,12 +265,12 @@ export class List<Type, WD> {
|
||||
required: false,
|
||||
})
|
||||
|
||||
return Config.of<WrapperData>()({
|
||||
myValue: a.withWrapperData(),
|
||||
return Config.of<Store>()({
|
||||
myValue: a.withStore(),
|
||||
})
|
||||
```
|
||||
*/
|
||||
withWrapperData<NewWrapperData extends WD extends never ? any : WD>() {
|
||||
return this as any as List<Type, NewWrapperData>
|
||||
withStore<NewStore extends Store extends never ? any : Store>() {
|
||||
return this as any as List<Type, NewStore>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,9 +94,9 @@ const username = Value.string({
|
||||
});
|
||||
```
|
||||
*/
|
||||
export class Value<Type, WD> {
|
||||
export class Value<Type, Store> {
|
||||
protected constructor(
|
||||
public build: LazyBuild<WD, ValueSpec>,
|
||||
public build: LazyBuild<Store, ValueSpec>,
|
||||
public validator: Parser<unknown, Type>,
|
||||
) {}
|
||||
static toggle(a: {
|
||||
@@ -120,9 +120,9 @@ export class Value<Type, WD> {
|
||||
boolean,
|
||||
)
|
||||
}
|
||||
static dynamicToggle<WD = never>(
|
||||
static dynamicToggle<Store = never>(
|
||||
a: LazyBuild<
|
||||
WD,
|
||||
Store,
|
||||
{
|
||||
name: string
|
||||
description?: string | null
|
||||
@@ -132,7 +132,7 @@ export class Value<Type, WD> {
|
||||
}
|
||||
>,
|
||||
) {
|
||||
return new Value<boolean, WD>(
|
||||
return new Value<boolean, Store>(
|
||||
async (options) => ({
|
||||
description: null,
|
||||
warning: null,
|
||||
@@ -183,9 +183,9 @@ export class Value<Type, WD> {
|
||||
asRequiredParser(string, a),
|
||||
)
|
||||
}
|
||||
static dynamicText<WD = never>(
|
||||
static dynamicText<Store = never>(
|
||||
getA: LazyBuild<
|
||||
WD,
|
||||
Store,
|
||||
{
|
||||
name: string
|
||||
description?: string | null
|
||||
@@ -204,7 +204,7 @@ export class Value<Type, WD> {
|
||||
}
|
||||
>,
|
||||
) {
|
||||
return new Value<string | null | undefined, WD>(async (options) => {
|
||||
return new Value<string | null | undefined, Store>(async (options) => {
|
||||
const a = await getA(options)
|
||||
return {
|
||||
type: "text" as const,
|
||||
@@ -254,9 +254,9 @@ export class Value<Type, WD> {
|
||||
string,
|
||||
)
|
||||
}
|
||||
static dynamicTextarea<WD = never>(
|
||||
static dynamicTextarea<Store = never>(
|
||||
getA: LazyBuild<
|
||||
WD,
|
||||
Store,
|
||||
{
|
||||
name: string
|
||||
description?: string | null
|
||||
@@ -270,7 +270,7 @@ export class Value<Type, WD> {
|
||||
}
|
||||
>,
|
||||
) {
|
||||
return new Value<string, WD>(async (options) => {
|
||||
return new Value<string, Store>(async (options) => {
|
||||
const a = await getA(options)
|
||||
return {
|
||||
description: null,
|
||||
@@ -320,9 +320,9 @@ export class Value<Type, WD> {
|
||||
asRequiredParser(number, a),
|
||||
)
|
||||
}
|
||||
static dynamicNumber<WD = never>(
|
||||
static dynamicNumber<Store = never>(
|
||||
getA: LazyBuild<
|
||||
WD,
|
||||
Store,
|
||||
{
|
||||
name: string
|
||||
description?: string | null
|
||||
@@ -339,7 +339,7 @@ export class Value<Type, WD> {
|
||||
}
|
||||
>,
|
||||
) {
|
||||
return new Value<number | null | undefined, WD>(async (options) => {
|
||||
return new Value<number | null | undefined, Store>(async (options) => {
|
||||
const a = await getA(options)
|
||||
return {
|
||||
type: "number" as const,
|
||||
@@ -381,9 +381,9 @@ export class Value<Type, WD> {
|
||||
)
|
||||
}
|
||||
|
||||
static dynamicColor<WD = never>(
|
||||
static dynamicColor<Store = never>(
|
||||
getA: LazyBuild<
|
||||
WD,
|
||||
Store,
|
||||
{
|
||||
name: string
|
||||
description?: string | null
|
||||
@@ -394,7 +394,7 @@ export class Value<Type, WD> {
|
||||
}
|
||||
>,
|
||||
) {
|
||||
return new Value<string | null | undefined, WD>(async (options) => {
|
||||
return new Value<string | null | undefined, Store>(async (options) => {
|
||||
const a = await getA(options)
|
||||
return {
|
||||
type: "color" as const,
|
||||
@@ -438,9 +438,9 @@ export class Value<Type, WD> {
|
||||
asRequiredParser(string, a),
|
||||
)
|
||||
}
|
||||
static dynamicDatetime<WD = never>(
|
||||
static dynamicDatetime<Store = never>(
|
||||
getA: LazyBuild<
|
||||
WD,
|
||||
Store,
|
||||
{
|
||||
name: string
|
||||
description?: string | null
|
||||
@@ -455,7 +455,7 @@ export class Value<Type, WD> {
|
||||
}
|
||||
>,
|
||||
) {
|
||||
return new Value<string | null | undefined, WD>(async (options) => {
|
||||
return new Value<string | null | undefined, Store>(async (options) => {
|
||||
const a = await getA(options)
|
||||
return {
|
||||
type: "datetime" as const,
|
||||
@@ -503,9 +503,9 @@ export class Value<Type, WD> {
|
||||
) as any,
|
||||
)
|
||||
}
|
||||
static dynamicSelect<WD = never>(
|
||||
static dynamicSelect<Store = never>(
|
||||
getA: LazyBuild<
|
||||
WD,
|
||||
Store,
|
||||
{
|
||||
name: string
|
||||
description?: string | null
|
||||
@@ -516,7 +516,7 @@ export class Value<Type, WD> {
|
||||
}
|
||||
>,
|
||||
) {
|
||||
return new Value<string | null | undefined, WD>(async (options) => {
|
||||
return new Value<string | null | undefined, Store>(async (options) => {
|
||||
const a = await getA(options)
|
||||
return {
|
||||
description: null,
|
||||
@@ -557,9 +557,9 @@ export class Value<Type, WD> {
|
||||
),
|
||||
)
|
||||
}
|
||||
static dynamicMultiselect<WD = never>(
|
||||
static dynamicMultiselect<Store = never>(
|
||||
getA: LazyBuild<
|
||||
WD,
|
||||
Store,
|
||||
{
|
||||
name: string
|
||||
description?: string | null
|
||||
@@ -572,7 +572,7 @@ export class Value<Type, WD> {
|
||||
}
|
||||
>,
|
||||
) {
|
||||
return new Value<string[], WD>(async (options) => {
|
||||
return new Value<string[], Store>(async (options) => {
|
||||
const a = await getA(options)
|
||||
return {
|
||||
type: "multiselect" as const,
|
||||
@@ -586,15 +586,15 @@ export class Value<Type, WD> {
|
||||
}
|
||||
}, arrayOf(string))
|
||||
}
|
||||
static object<Type extends Record<string, any>, WrapperData>(
|
||||
static object<Type extends Record<string, any>, Store>(
|
||||
a: {
|
||||
name: string
|
||||
description?: string | null
|
||||
warning?: string | null
|
||||
},
|
||||
previousSpec: Config<Type, WrapperData>,
|
||||
previousSpec: Config<Type, Store>,
|
||||
) {
|
||||
return new Value<Type, WrapperData>(async (options) => {
|
||||
return new Value<Type, Store>(async (options) => {
|
||||
const spec = await previousSpec.build(options as any)
|
||||
return {
|
||||
type: "object" as const,
|
||||
@@ -605,7 +605,7 @@ export class Value<Type, WD> {
|
||||
}
|
||||
}, previousSpec.validator)
|
||||
}
|
||||
static union<Required extends RequiredDefault<string>, Type, WrapperData>(
|
||||
static union<Required extends RequiredDefault<string>, Type, Store>(
|
||||
a: {
|
||||
name: string
|
||||
description?: string | null
|
||||
@@ -615,9 +615,9 @@ export class Value<Type, WD> {
|
||||
Default is false */
|
||||
immutable?: boolean
|
||||
},
|
||||
aVariants: Variants<Type, WrapperData>,
|
||||
aVariants: Variants<Type, Store>,
|
||||
) {
|
||||
return new Value<AsRequired<Type, Required>, WrapperData>(
|
||||
return new Value<AsRequired<Type, Required>, Store>(
|
||||
async (options) => ({
|
||||
type: "union" as const,
|
||||
description: null,
|
||||
@@ -633,18 +633,18 @@ export class Value<Type, WD> {
|
||||
static filteredUnion<
|
||||
Required extends RequiredDefault<string>,
|
||||
Type extends Record<string, any>,
|
||||
WD = never,
|
||||
Store = never,
|
||||
>(
|
||||
getDisabledFn: LazyBuild<WD, string[]>,
|
||||
getDisabledFn: LazyBuild<Store, string[]>,
|
||||
a: {
|
||||
name: string
|
||||
description?: string | null
|
||||
warning?: string | null
|
||||
required: Required
|
||||
},
|
||||
aVariants: Variants<Type, WD> | Variants<Type, never>,
|
||||
aVariants: Variants<Type, Store> | Variants<Type, never>,
|
||||
) {
|
||||
return new Value<AsRequired<Type, Required>, WD>(
|
||||
return new Value<AsRequired<Type, Required>, Store>(
|
||||
async (options) => ({
|
||||
type: "union" as const,
|
||||
description: null,
|
||||
@@ -659,11 +659,8 @@ export class Value<Type, WD> {
|
||||
)
|
||||
}
|
||||
|
||||
static list<Type, WrapperData>(a: List<Type, WrapperData>) {
|
||||
return new Value<Type, WrapperData>(
|
||||
(options) => a.build(options),
|
||||
a.validator,
|
||||
)
|
||||
static list<Type, Store>(a: List<Type, Store>) {
|
||||
return new Value<Type, Store>((options) => a.build(options), a.validator)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -675,12 +672,12 @@ export class Value<Type, WD> {
|
||||
required: false,
|
||||
})
|
||||
|
||||
return Config.of<WrapperData>()({
|
||||
myValue: a.withWrapperData(),
|
||||
return Config.of<Store>()({
|
||||
myValue: a.withStore(),
|
||||
})
|
||||
```
|
||||
*/
|
||||
withWrapperData<NewWrapperData extends WD extends never ? any : WD>() {
|
||||
return this as any as Value<Type, NewWrapperData>
|
||||
withStore<NewStore extends Store extends never ? any : Store>() {
|
||||
return this as any as Value<Type, NewStore>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,24 +51,20 @@ export const pruning = Value.union(
|
||||
);
|
||||
```
|
||||
*/
|
||||
export class Variants<Type, WD> {
|
||||
export class Variants<Type, Store> {
|
||||
static text: any
|
||||
private constructor(
|
||||
public build: LazyBuild<WD, ValueSpecUnion["variants"]>,
|
||||
public build: LazyBuild<Store, ValueSpecUnion["variants"]>,
|
||||
public validator: Parser<unknown, Type>,
|
||||
) {}
|
||||
// A extends {
|
||||
// [key: string]: {
|
||||
// name: string
|
||||
// spec: InputSpec
|
||||
// }
|
||||
// },
|
||||
static of<
|
||||
VariantValues extends {
|
||||
[K in string]: {
|
||||
name: string
|
||||
spec: Config<any, any> | Config<any, never>
|
||||
spec: Config<any, Store> | Config<any, never>
|
||||
}
|
||||
},
|
||||
Store,
|
||||
>(a: VariantValues) {
|
||||
const validator = anyOf(
|
||||
...Object.entries(a).map(([name, { spec }]) =>
|
||||
@@ -83,21 +79,13 @@ export class Variants<Type, WD> {
|
||||
{
|
||||
[K in keyof VariantValues]: {
|
||||
unionSelectKey: K
|
||||
unionValueKey: VariantValues[K]["spec"] extends
|
||||
| Config<infer B, any>
|
||||
| Config<infer B, never>
|
||||
? B
|
||||
: never
|
||||
// prettier-ignore
|
||||
unionValueKey:
|
||||
VariantValues[K]["spec"] extends (Config<infer B, Store> | Config<infer B, never>) ? B :
|
||||
never
|
||||
}
|
||||
}[keyof VariantValues],
|
||||
{
|
||||
[K in keyof VariantValues]: VariantValues[K] extends Config<
|
||||
any,
|
||||
infer C
|
||||
>
|
||||
? C
|
||||
: never
|
||||
}[keyof VariantValues]
|
||||
Store
|
||||
>(async (options) => {
|
||||
const variants = {} as {
|
||||
[K in keyof VariantValues]: { name: string; spec: InputSpec }
|
||||
@@ -121,12 +109,12 @@ export class Variants<Type, WD> {
|
||||
required: false,
|
||||
})
|
||||
|
||||
return Config.of<WrapperData>()({
|
||||
myValue: a.withWrapperData(),
|
||||
return Config.of<Store>()({
|
||||
myValue: a.withStore(),
|
||||
})
|
||||
```
|
||||
*/
|
||||
withWrapperData<NewWrapperData extends WD extends never ? any : WD>() {
|
||||
return this as any as Variants<Type, NewWrapperData>
|
||||
withStore<NewStore extends Store extends never ? any : Store>() {
|
||||
return this as any as Variants<Type, NewStore>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ export const smtpConfig = Value.filteredUnion(
|
||||
system: { name: "System Credentials", spec: Config.of({}) },
|
||||
custom: {
|
||||
name: "Custom Credentials",
|
||||
spec: Config.of<ConfigSpecOf<SmtpValue>>({
|
||||
spec: Config.of<ConfigSpecOf<SmtpValue>, never>({
|
||||
server: Value.text({
|
||||
name: "SMTP Server",
|
||||
required: {
|
||||
|
||||
@@ -2,9 +2,8 @@ import { Effects, ExpectedExports } from "../types"
|
||||
import { SDKManifest } from "../manifest/ManifestTypes"
|
||||
import * as D from "./configDependencies"
|
||||
import { Config, ExtractConfigType } from "./builder/config"
|
||||
import { Utils, utils } from "../util"
|
||||
import { Utils, utils } from "../util/utils"
|
||||
import nullIfEmpty from "../util/nullIfEmpty"
|
||||
import { WrapperDataContract } from "../wrapperData/wrapperDataContract"
|
||||
|
||||
declare const dependencyProof: unique symbol
|
||||
export type DependenciesReceipt = void & {
|
||||
@@ -12,7 +11,7 @@ export type DependenciesReceipt = void & {
|
||||
}
|
||||
|
||||
export type Save<
|
||||
WD,
|
||||
Store,
|
||||
A extends
|
||||
| Record<string, any>
|
||||
| Config<Record<string, any>, any>
|
||||
@@ -21,21 +20,21 @@ export type Save<
|
||||
> = (options: {
|
||||
effects: Effects
|
||||
input: ExtractConfigType<A> & Record<string, any>
|
||||
utils: Utils<WD>
|
||||
utils: Utils<Store>
|
||||
dependencies: D.ConfigDependencies<Manifest>
|
||||
}) => Promise<{
|
||||
dependenciesReceipt: DependenciesReceipt
|
||||
restart: boolean
|
||||
}>
|
||||
export type Read<
|
||||
WD,
|
||||
Store,
|
||||
A extends
|
||||
| Record<string, any>
|
||||
| Config<Record<string, any>, any>
|
||||
| Config<Record<string, any>, never>,
|
||||
> = (options: {
|
||||
effects: Effects
|
||||
utils: Utils<WD>
|
||||
utils: Utils<Store>
|
||||
}) => Promise<void | (ExtractConfigType<A> & Record<string, any>)>
|
||||
/**
|
||||
* We want to setup a config export with a get and set, this
|
||||
@@ -45,7 +44,7 @@ export type Read<
|
||||
* @returns
|
||||
*/
|
||||
export function setupConfig<
|
||||
WD,
|
||||
Store,
|
||||
ConfigType extends
|
||||
| Record<string, any>
|
||||
| Config<any, any>
|
||||
@@ -53,11 +52,9 @@ export function setupConfig<
|
||||
Manifest extends SDKManifest,
|
||||
Type extends Record<string, any> = ExtractConfigType<ConfigType>,
|
||||
>(
|
||||
wrapperDataContract: WrapperDataContract<WD>,
|
||||
_manifest: Manifest,
|
||||
spec: Config<Type, WD> | Config<Type, never>,
|
||||
write: Save<WD, Type, Manifest>,
|
||||
read: Read<WD, Type>,
|
||||
spec: Config<Type, Store> | Config<Type, never>,
|
||||
write: Save<Store, Type, Manifest>,
|
||||
read: Read<Store, Type>,
|
||||
) {
|
||||
const validator = spec.validator
|
||||
return {
|
||||
@@ -69,7 +66,7 @@ export function setupConfig<
|
||||
const { restart } = await write({
|
||||
input: JSON.parse(JSON.stringify(input)),
|
||||
effects,
|
||||
utils: utils(wrapperDataContract, effects),
|
||||
utils: utils(effects),
|
||||
dependencies: D.configDependenciesSet<Manifest>(),
|
||||
})
|
||||
if (restart) {
|
||||
@@ -77,7 +74,7 @@ export function setupConfig<
|
||||
}
|
||||
}) as ExpectedExports.setConfig,
|
||||
getConfig: (async ({ effects }) => {
|
||||
const myUtils = utils(wrapperDataContract, effects)
|
||||
const myUtils = utils<Store>(effects)
|
||||
const configValue = nullIfEmpty(
|
||||
(await read({ effects, utils: myUtils })) || null,
|
||||
)
|
||||
|
||||
@@ -2,9 +2,9 @@ import { InterfaceReceipt } from "../mainFn/interfaceReceipt"
|
||||
import { Daemon, Effects } from "../types"
|
||||
import { CheckResult } from "./checkFns/CheckResult"
|
||||
import { HealthReceipt } from "./HealthReceipt"
|
||||
import { Trigger } from "./trigger"
|
||||
import { TriggerInput } from "./trigger/TriggerInput"
|
||||
import { defaultTrigger } from "./trigger/defaultTrigger"
|
||||
import { Trigger } from "../trigger"
|
||||
import { TriggerInput } from "../trigger/TriggerInput"
|
||||
import { defaultTrigger } from "../trigger/defaultTrigger"
|
||||
import { once } from "../util/once"
|
||||
|
||||
export function healthCheck(o: {
|
||||
|
||||
@@ -19,5 +19,3 @@ import "./inits"
|
||||
export * as matches from "ts-matches"
|
||||
export * as YAML from "yaml"
|
||||
export * as TOML from "@iarna/toml"
|
||||
|
||||
export class<Manifest extends SDKManifest>
|
||||
@@ -1,33 +1,28 @@
|
||||
import { ManifestVersion } from "../../manifest/ManifestTypes"
|
||||
import { Effects } from "../../types"
|
||||
import { Utils } from "../../util"
|
||||
import { WrapperDataContract } from "../../wrapperData/wrapperDataContract"
|
||||
import { Utils } from "../../util/utils"
|
||||
|
||||
export class Migration<WD, Version extends ManifestVersion> {
|
||||
export class Migration<Store, Version extends ManifestVersion> {
|
||||
constructor(
|
||||
readonly wrapperDataContract: WrapperDataContract<WD>,
|
||||
readonly options: {
|
||||
version: Version
|
||||
up: (opts: { effects: Effects; utils: Utils<WD> }) => Promise<void>
|
||||
down: (opts: { effects: Effects; utils: Utils<WD> }) => Promise<void>
|
||||
up: (opts: { effects: Effects; utils: Utils<Store> }) => Promise<void>
|
||||
down: (opts: { effects: Effects; utils: Utils<Store> }) => Promise<void>
|
||||
},
|
||||
) {}
|
||||
static of<WD, Version extends ManifestVersion>(
|
||||
wrapperDataContract: WrapperDataContract<WD>,
|
||||
options: {
|
||||
version: Version
|
||||
up: (opts: { effects: Effects; utils: Utils<WD> }) => Promise<void>
|
||||
down: (opts: { effects: Effects; utils: Utils<WD> }) => Promise<void>
|
||||
},
|
||||
) {
|
||||
return new Migration(wrapperDataContract, options)
|
||||
static of<Store, Version extends ManifestVersion>(options: {
|
||||
version: Version
|
||||
up: (opts: { effects: Effects; utils: Utils<Store> }) => Promise<void>
|
||||
down: (opts: { effects: Effects; utils: Utils<Store> }) => Promise<void>
|
||||
}) {
|
||||
return new Migration(options)
|
||||
}
|
||||
|
||||
async up(opts: { effects: Effects; utils: Utils<WD> }) {
|
||||
async up(opts: { effects: Effects; utils: Utils<Store> }) {
|
||||
this.up(opts)
|
||||
}
|
||||
|
||||
async down(opts: { effects: Effects; utils: Utils<WD> }) {
|
||||
async down(opts: { effects: Effects; utils: Utils<Store> }) {
|
||||
this.down(opts)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,39 +4,32 @@ import { SDKManifest } from "../../manifest/ManifestTypes"
|
||||
import { ExpectedExports } from "../../types"
|
||||
import { createUtils } from "../../util"
|
||||
import { once } from "../../util/once"
|
||||
import { WrapperDataContract } from "../../wrapperData/wrapperDataContract"
|
||||
import { Migration } from "./Migration"
|
||||
|
||||
export class Migrations<WD> {
|
||||
export class Migrations<Store> {
|
||||
private constructor(
|
||||
readonly wrapperDataContract: WrapperDataContract<WD>,
|
||||
readonly manifest: SDKManifest,
|
||||
readonly migrations: Array<Migration<WD, any>>,
|
||||
readonly migrations: Array<Migration<Store, any>>,
|
||||
) {}
|
||||
private sortedMigrations = once(() => {
|
||||
const migrationsAsVersions = (
|
||||
this.migrations as Array<Migration<WD, any>>
|
||||
this.migrations as Array<Migration<Store, any>>
|
||||
).map((x) => [EmVer.parse(x.options.version), x] as const)
|
||||
migrationsAsVersions.sort((a, b) => a[0].compareForSort(b[0]))
|
||||
return migrationsAsVersions
|
||||
})
|
||||
private currentVersion = once(() => EmVer.parse(this.manifest.version))
|
||||
static of<WD, Migrations extends Array<Migration<WD, any>>>(
|
||||
wrapperDataContract: WrapperDataContract<WD>,
|
||||
static of<Store, Migrations extends Array<Migration<Store, any>>>(
|
||||
manifest: SDKManifest,
|
||||
...migrations: EnsureUniqueId<Migrations>
|
||||
) {
|
||||
return new Migrations(
|
||||
wrapperDataContract,
|
||||
manifest,
|
||||
migrations as Array<Migration<WD, any>>,
|
||||
)
|
||||
return new Migrations(manifest, migrations as Array<Migration<Store, any>>)
|
||||
}
|
||||
async init({
|
||||
effects,
|
||||
previousVersion,
|
||||
}: Parameters<ExpectedExports.init>[0]) {
|
||||
const utils = createUtils(this.wrapperDataContract, effects)
|
||||
const utils = createUtils<Store>(effects)
|
||||
if (!!previousVersion) {
|
||||
const previousVersionEmVer = EmVer.parse(previousVersion)
|
||||
for (const [_, migration] of this.sortedMigrations()
|
||||
@@ -50,7 +43,7 @@ export class Migrations<WD> {
|
||||
effects,
|
||||
nextVersion,
|
||||
}: Parameters<ExpectedExports.uninit>[0]) {
|
||||
const utils = createUtils(this.wrapperDataContract, effects)
|
||||
const utils = createUtils<Store>(effects)
|
||||
if (!!nextVersion) {
|
||||
const nextVersionEmVer = EmVer.parse(nextVersion)
|
||||
const reversed = [...this.sortedMigrations()].reverse()
|
||||
@@ -64,14 +57,10 @@ export class Migrations<WD> {
|
||||
}
|
||||
|
||||
export function setupMigrations<
|
||||
WD,
|
||||
Migrations extends Array<Migration<WD, any>>,
|
||||
>(
|
||||
wrapperDataContract: WrapperDataContract<WD>,
|
||||
manifest: SDKManifest,
|
||||
...migrations: EnsureUniqueId<Migrations>
|
||||
) {
|
||||
return Migrations.of(wrapperDataContract, manifest, ...migrations)
|
||||
Store,
|
||||
Migrations extends Array<Migration<Store, any>>,
|
||||
>(manifest: SDKManifest, ...migrations: EnsureUniqueId<Migrations>) {
|
||||
return Migrations.of(manifest, ...migrations)
|
||||
}
|
||||
|
||||
// prettier-ignore
|
||||
|
||||
@@ -3,10 +3,10 @@ import { Migrations } from "./migrations/setupMigrations"
|
||||
import { Install } from "./setupInstall"
|
||||
import { Uninstall } from "./setupUninstall"
|
||||
|
||||
export function setupInit<WrapperData>(
|
||||
migrations: Migrations<WrapperData>,
|
||||
install: Install<WrapperData>,
|
||||
uninstall: Uninstall<WrapperData>,
|
||||
export function setupInit<Store>(
|
||||
migrations: Migrations<Store>,
|
||||
install: Install<Store>,
|
||||
uninstall: Uninstall<Store>,
|
||||
): {
|
||||
init: ExpectedExports.init
|
||||
uninit: ExpectedExports.uninit
|
||||
|
||||
@@ -1,21 +1,14 @@
|
||||
import { Effects, ExpectedExports } from "../types"
|
||||
import { Utils, utils } from "../util"
|
||||
import { WrapperDataContract } from "../wrapperData/wrapperDataContract"
|
||||
import { Utils, utils } from "../util/utils"
|
||||
|
||||
export type InstallFn<WD> = (opts: {
|
||||
export type InstallFn<Store> = (opts: {
|
||||
effects: Effects
|
||||
utils: Utils<WD>
|
||||
utils: Utils<Store>
|
||||
}) => Promise<void>
|
||||
export class Install<WD> {
|
||||
private constructor(
|
||||
readonly wrapperDataContract: WrapperDataContract<WD>,
|
||||
readonly fn: InstallFn<WD>,
|
||||
) {}
|
||||
static of<WD>(
|
||||
wrapperDataContract: WrapperDataContract<WD>,
|
||||
fn: InstallFn<WD>,
|
||||
) {
|
||||
return new Install(wrapperDataContract, fn)
|
||||
export class Install<Store> {
|
||||
private constructor(readonly fn: InstallFn<Store>) {}
|
||||
static of<Store>(fn: InstallFn<Store>) {
|
||||
return new Install(fn)
|
||||
}
|
||||
|
||||
async init({
|
||||
@@ -25,14 +18,11 @@ export class Install<WD> {
|
||||
if (!previousVersion)
|
||||
await this.fn({
|
||||
effects,
|
||||
utils: utils(this.wrapperDataContract, effects),
|
||||
utils: utils(effects),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function setupInstall<WD>(
|
||||
wrapperDataContract: WrapperDataContract<WD>,
|
||||
fn: InstallFn<WD>,
|
||||
) {
|
||||
return Install.of(wrapperDataContract, fn)
|
||||
export function setupInstall<Store>(fn: InstallFn<Store>) {
|
||||
return Install.of(fn)
|
||||
}
|
||||
|
||||
@@ -1,21 +1,14 @@
|
||||
import { Effects, ExpectedExports } from "../types"
|
||||
import { Utils, utils } from "../util"
|
||||
import { WrapperDataContract } from "../wrapperData/wrapperDataContract"
|
||||
import { Utils, utils } from "../util/utils"
|
||||
|
||||
export type UninstallFn<WrapperData> = (opts: {
|
||||
export type UninstallFn<Store> = (opts: {
|
||||
effects: Effects
|
||||
utils: Utils<WrapperData>
|
||||
utils: Utils<Store>
|
||||
}) => Promise<void>
|
||||
export class Uninstall<WD> {
|
||||
private constructor(
|
||||
readonly wrapperDataContract: WrapperDataContract<WD>,
|
||||
readonly fn: UninstallFn<WD>,
|
||||
) {}
|
||||
static of<WD>(
|
||||
wrapperDataContract: WrapperDataContract<WD>,
|
||||
fn: UninstallFn<WD>,
|
||||
) {
|
||||
return new Uninstall(wrapperDataContract, fn)
|
||||
export class Uninstall<Store> {
|
||||
private constructor(readonly fn: UninstallFn<Store>) {}
|
||||
static of<Store>(fn: UninstallFn<Store>) {
|
||||
return new Uninstall(fn)
|
||||
}
|
||||
|
||||
async uninit({
|
||||
@@ -25,14 +18,11 @@ export class Uninstall<WD> {
|
||||
if (!nextVersion)
|
||||
await this.fn({
|
||||
effects,
|
||||
utils: utils(this.wrapperDataContract, effects),
|
||||
utils: utils(effects),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function setupUninstall<WD>(
|
||||
wrapperDataContract: WrapperDataContract<WD>,
|
||||
fn: UninstallFn<WD>,
|
||||
) {
|
||||
return Uninstall.of(wrapperDataContract, fn)
|
||||
export function setupUninstall<Store>(fn: UninstallFn<Store>) {
|
||||
return Uninstall.of(fn)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { HealthReceipt } from "../health/HealthReceipt"
|
||||
import { CheckResult } from "../health/checkFns"
|
||||
import { Trigger } from "../health/trigger"
|
||||
import { TriggerInput } from "../health/trigger/TriggerInput"
|
||||
import { defaultTrigger } from "../health/trigger/defaultTrigger"
|
||||
import { Trigger } from "../trigger"
|
||||
import { TriggerInput } from "../trigger/TriggerInput"
|
||||
import { defaultTrigger } from "../trigger/defaultTrigger"
|
||||
import { DaemonReturned, Effects, ValidIfNoStupidEscape } from "../types"
|
||||
import { InterfaceReceipt } from "./interfaceReceipt"
|
||||
type Daemon<Ids extends string, Command extends string, Id extends string> = {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Effects, ExpectedExports } from "../types"
|
||||
import { createMainUtils, Utils, utils } from "../util"
|
||||
import { createMainUtils } from "../util"
|
||||
import { Utils, utils } from "../util/utils"
|
||||
import { Daemons } from "./Daemons"
|
||||
import "./exportInterfaces"
|
||||
import "./LocalBinding"
|
||||
@@ -11,7 +12,6 @@ import "./TorBinding"
|
||||
import "./TorHostname"
|
||||
|
||||
import "./Daemons"
|
||||
import { WrapperDataContract } from "../wrapperData/wrapperDataContract"
|
||||
|
||||
/**
|
||||
* Used to ensure that the main function is running with the valid proofs.
|
||||
@@ -23,18 +23,17 @@ import { WrapperDataContract } from "../wrapperData/wrapperDataContract"
|
||||
* @param fn
|
||||
* @returns
|
||||
*/
|
||||
export const setupMain = <WD>(
|
||||
wrapperDataContract: WrapperDataContract<WD>,
|
||||
export const setupMain = <Store>(
|
||||
fn: (o: {
|
||||
effects: Effects
|
||||
started(onTerm: () => void): null
|
||||
utils: Utils<WD, {}>
|
||||
utils: Utils<Store, {}>
|
||||
}) => Promise<Daemons<any>>,
|
||||
): ExpectedExports.main => {
|
||||
return async (options) => {
|
||||
const result = await fn({
|
||||
...options,
|
||||
utils: createMainUtils(wrapperDataContract, options.effects),
|
||||
utils: createMainUtils<Store>(options.effects),
|
||||
})
|
||||
await result.build().then((x) => x.wait())
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Parser } from "ts-matches"
|
||||
import { Effects, EnsureWrapperDataPath, ExtractWrapperData } from "../types"
|
||||
import { Effects, EnsureStorePath } from "../types"
|
||||
import { NoAny } from "../util"
|
||||
|
||||
export class GetWrapperData<WrapperData, Path extends string> {
|
||||
export class GetStore<Store, Path extends string> {
|
||||
constructor(
|
||||
readonly effects: Effects,
|
||||
readonly path: Path & EnsureWrapperDataPath<WrapperData, Path>,
|
||||
readonly path: Path & EnsureStorePath<Store, Path>,
|
||||
readonly options: {
|
||||
/** Defaults to what ever the package currently in */
|
||||
packageId?: string | undefined
|
||||
@@ -13,20 +13,20 @@ export class GetWrapperData<WrapperData, Path extends string> {
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Returns the value of WrapperData at the provided path. Restart the service if the value changes
|
||||
* Returns the value of Store at the provided path. Restart the service if the value changes
|
||||
*/
|
||||
const() {
|
||||
return this.effects.getWrapperData<WrapperData, Path>({
|
||||
return this.effects.store.get<Store, Path>({
|
||||
...this.options,
|
||||
path: this.path as any,
|
||||
callback: this.effects.restart,
|
||||
})
|
||||
}
|
||||
/**
|
||||
* Returns the value of WrapperData at the provided path. Does nothing if the value changes
|
||||
* Returns the value of Store at the provided path. Does nothing if the value changes
|
||||
*/
|
||||
once() {
|
||||
return this.effects.getWrapperData<WrapperData, Path>({
|
||||
return this.effects.store.get<Store, Path>({
|
||||
...this.options,
|
||||
path: this.path as any,
|
||||
callback: () => {},
|
||||
@@ -34,7 +34,7 @@ export class GetWrapperData<WrapperData, Path extends string> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Watches the value of WrapperData at the provided path. Takes a custom callback function to run whenever the value changes
|
||||
* Watches the value of Store at the provided path. Takes a custom callback function to run whenever the value changes
|
||||
*/
|
||||
async *watch() {
|
||||
while (true) {
|
||||
@@ -42,7 +42,7 @@ export class GetWrapperData<WrapperData, Path extends string> {
|
||||
const waitForNext = new Promise<void>((resolve) => {
|
||||
callback = resolve
|
||||
})
|
||||
yield await this.effects.getWrapperData<WrapperData, Path>({
|
||||
yield await this.effects.store.get<Store, Path>({
|
||||
...this.options,
|
||||
path: this.path as any,
|
||||
callback: () => callback(),
|
||||
@@ -51,13 +51,13 @@ export class GetWrapperData<WrapperData, Path extends string> {
|
||||
}
|
||||
}
|
||||
}
|
||||
export function getWrapperData<WrapperData, Path extends string>(
|
||||
export function getStore<Store, Path extends string>(
|
||||
effects: Effects,
|
||||
path: Path & EnsureWrapperDataPath<WrapperData, Path>,
|
||||
path: Path & EnsureStorePath<Store, Path>,
|
||||
options: {
|
||||
/** Defaults to what ever the package currently in */
|
||||
packageId?: string | undefined
|
||||
} = {},
|
||||
) {
|
||||
return new GetWrapperData<WrapperData, Path>(effects, path as any, options)
|
||||
return new GetStore<Store, Path>(effects, path as any, options)
|
||||
}
|
||||
@@ -4,13 +4,7 @@ import { List } from "../config/builder/list"
|
||||
import { Value } from "../config/builder/value"
|
||||
import { Variants } from "../config/builder/variants"
|
||||
import { ValueSpec } from "../config/configTypes"
|
||||
import { Parser } from "ts-matches"
|
||||
import {
|
||||
createWrapperDataContract,
|
||||
neverWrapperDataContract,
|
||||
} from "../wrapperData/wrapperDataContract"
|
||||
|
||||
type test = unknown | { test: 5 }
|
||||
describe("builder tests", () => {
|
||||
test("text", async () => {
|
||||
const bitcoinPropertiesBuilt: {
|
||||
@@ -303,7 +297,7 @@ describe("values", () => {
|
||||
utils: "utils",
|
||||
} as any
|
||||
test("toggle", async () => {
|
||||
const value = Value.dynamicToggle(neverWrapperDataContract, async () => ({
|
||||
const value = Value.dynamicToggle(async () => ({
|
||||
name: "Testing",
|
||||
description: null,
|
||||
warning: null,
|
||||
@@ -321,7 +315,7 @@ describe("values", () => {
|
||||
})
|
||||
})
|
||||
test("text", async () => {
|
||||
const value = Value.dynamicText(neverWrapperDataContract, async () => ({
|
||||
const value = Value.dynamicText(async () => ({
|
||||
name: "Testing",
|
||||
required: { default: null },
|
||||
}))
|
||||
@@ -337,7 +331,7 @@ describe("values", () => {
|
||||
})
|
||||
})
|
||||
test("text with default", async () => {
|
||||
const value = Value.dynamicText(neverWrapperDataContract, async () => ({
|
||||
const value = Value.dynamicText(async () => ({
|
||||
name: "Testing",
|
||||
required: { default: "this is a default value" },
|
||||
}))
|
||||
@@ -352,7 +346,7 @@ describe("values", () => {
|
||||
})
|
||||
})
|
||||
test("optional text", async () => {
|
||||
const value = Value.dynamicText(neverWrapperDataContract, async () => ({
|
||||
const value = Value.dynamicText(async () => ({
|
||||
name: "Testing",
|
||||
required: false,
|
||||
}))
|
||||
@@ -368,7 +362,7 @@ describe("values", () => {
|
||||
})
|
||||
})
|
||||
test("color", async () => {
|
||||
const value = Value.dynamicColor(neverWrapperDataContract, async () => ({
|
||||
const value = Value.dynamicColor(async () => ({
|
||||
name: "Testing",
|
||||
required: false,
|
||||
description: null,
|
||||
@@ -387,20 +381,17 @@ describe("values", () => {
|
||||
})
|
||||
})
|
||||
test("datetime", async () => {
|
||||
const value = Value.dynamicDatetime(
|
||||
createWrapperDataContract<{ test: "a" }>(),
|
||||
async ({ utils }) => {
|
||||
;async () => {
|
||||
;(await utils.getOwnWrapperData("/test").once()) satisfies "a"
|
||||
}
|
||||
const value = Value.dynamicDatetime<{ test: "a" }>(async ({ utils }) => {
|
||||
;async () => {
|
||||
;(await utils.store.getOwn("/test").once()) satisfies "a"
|
||||
}
|
||||
|
||||
return {
|
||||
name: "Testing",
|
||||
required: { default: null },
|
||||
inputmode: "date",
|
||||
}
|
||||
},
|
||||
)
|
||||
return {
|
||||
name: "Testing",
|
||||
required: { default: null },
|
||||
inputmode: "date",
|
||||
}
|
||||
})
|
||||
const validator = value.validator
|
||||
validator.unsafeCast("2021-01-01")
|
||||
validator.unsafeCast(null)
|
||||
@@ -415,18 +406,15 @@ describe("values", () => {
|
||||
})
|
||||
})
|
||||
test("textarea", async () => {
|
||||
const value = Value.dynamicTextarea(
|
||||
neverWrapperDataContract,
|
||||
async () => ({
|
||||
name: "Testing",
|
||||
required: false,
|
||||
description: null,
|
||||
warning: null,
|
||||
minLength: null,
|
||||
maxLength: null,
|
||||
placeholder: null,
|
||||
}),
|
||||
)
|
||||
const value = Value.dynamicTextarea(async () => ({
|
||||
name: "Testing",
|
||||
required: false,
|
||||
description: null,
|
||||
warning: null,
|
||||
minLength: null,
|
||||
maxLength: null,
|
||||
placeholder: null,
|
||||
}))
|
||||
const validator = value.validator
|
||||
validator.unsafeCast("test text")
|
||||
expect(() => validator.unsafeCast(null)).toThrowError()
|
||||
@@ -437,7 +425,7 @@ describe("values", () => {
|
||||
})
|
||||
})
|
||||
test("number", async () => {
|
||||
const value = Value.dynamicNumber(neverWrapperDataContract, () => ({
|
||||
const value = Value.dynamicNumber(() => ({
|
||||
name: "Testing",
|
||||
required: { default: null },
|
||||
integer: false,
|
||||
@@ -511,7 +499,6 @@ describe("values", () => {
|
||||
describe("filtering", () => {
|
||||
test("union", async () => {
|
||||
const value = Value.filteredUnion(
|
||||
neverWrapperDataContract,
|
||||
() => ["a", "c"],
|
||||
{
|
||||
name: "Testing",
|
||||
@@ -620,7 +607,7 @@ describe("Builder List", () => {
|
||||
describe("dynamic", () => {
|
||||
test("text", async () => {
|
||||
const value = Value.list(
|
||||
List.dynamicText(neverWrapperDataContract, () => ({
|
||||
List.dynamicText(() => ({
|
||||
name: "test",
|
||||
spec: { patterns: [] },
|
||||
})),
|
||||
@@ -638,7 +625,7 @@ describe("Builder List", () => {
|
||||
})
|
||||
test("number", async () => {
|
||||
const value = Value.list(
|
||||
List.dynamicNumber(neverWrapperDataContract, () => ({
|
||||
List.dynamicNumber(() => ({
|
||||
name: "test",
|
||||
spec: { integer: true },
|
||||
})),
|
||||
|
||||
@@ -423,7 +423,6 @@ oldSpecToBuilder(
|
||||
},
|
||||
{
|
||||
// convert this to `start-sdk/lib` for conversions
|
||||
startSdk: "../..",
|
||||
wrapperData: "./output.wrapperData",
|
||||
startSdk: "./output.sdk",
|
||||
},
|
||||
)
|
||||
|
||||
@@ -1 +1,7 @@
|
||||
export type WrapperData = {}
|
||||
import { StartSDK } from "../StartSDK"
|
||||
|
||||
export type WrapperData = any
|
||||
export const sdk = StartSDK.of()
|
||||
.withManifest<WrapperData>()
|
||||
.withStore<{ storeRoot: { storeLeaf: "value" } }>()
|
||||
.build()
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { Effects } from "../types"
|
||||
import { createMainUtils, utils } from "../util"
|
||||
import { createWrapperDataContract } from "../wrapperData/wrapperDataContract"
|
||||
import { createMainUtils } from "../util"
|
||||
import { utils } from "../util/utils"
|
||||
|
||||
type WrapperType = {
|
||||
config: {
|
||||
someValue: "a" | "b"
|
||||
}
|
||||
}
|
||||
const wrapperDataContract = createWrapperDataContract<WrapperType>()
|
||||
const todo = <A>(): A => {
|
||||
throw new Error("not implemented")
|
||||
}
|
||||
@@ -15,97 +14,94 @@ const noop = () => {}
|
||||
describe("wrapperData", () => {
|
||||
test("types", async () => {
|
||||
;async () => {
|
||||
utils(wrapperDataContract, todo<Effects>()).setOwnWrapperData("/config", {
|
||||
utils<WrapperType>(todo<Effects>()).store.setOwn("/config", {
|
||||
someValue: "a",
|
||||
})
|
||||
utils(wrapperDataContract, todo<Effects>()).setOwnWrapperData(
|
||||
"/config/someValue",
|
||||
"b",
|
||||
)
|
||||
utils(wrapperDataContract, todo<Effects>()).setOwnWrapperData("", {
|
||||
utils<WrapperType>(todo<Effects>()).store.setOwn("/config/someValue", "b")
|
||||
utils<WrapperType>(todo<Effects>()).store.setOwn("", {
|
||||
config: { someValue: "b" },
|
||||
})
|
||||
utils(wrapperDataContract, todo<Effects>()).setOwnWrapperData(
|
||||
utils<WrapperType>(todo<Effects>()).store.setOwn(
|
||||
"/config/someValue",
|
||||
|
||||
// @ts-expect-error Type is wrong for the setting value
|
||||
5,
|
||||
)
|
||||
utils(wrapperDataContract, todo<Effects>()).setOwnWrapperData(
|
||||
utils(todo<Effects>()).store.setOwn(
|
||||
// @ts-expect-error Path is wrong
|
||||
"/config/someVae3lue",
|
||||
"someValue",
|
||||
)
|
||||
|
||||
todo<Effects>().setWrapperData<WrapperType, "/config/someValue">({
|
||||
todo<Effects>().store.set<WrapperType, "/config/someValue">({
|
||||
path: "/config/someValue",
|
||||
value: "b",
|
||||
})
|
||||
todo<Effects>().setWrapperData<WrapperType, "/config/some2Value">({
|
||||
todo<Effects>().store.set<WrapperType, "/config/some2Value">({
|
||||
//@ts-expect-error Path is wrong
|
||||
path: "/config/someValue",
|
||||
//@ts-expect-error Path is wrong
|
||||
value: "someValueIn",
|
||||
})
|
||||
todo<Effects>().setWrapperData<WrapperType, "/config/someValue">({
|
||||
todo<Effects>().store.set<WrapperType, "/config/someValue">({
|
||||
//@ts-expect-error Path is wrong
|
||||
path: "/config/some2Value",
|
||||
value: "a",
|
||||
})
|
||||
;(await createMainUtils(wrapperDataContract, todo<Effects>())
|
||||
.getOwnWrapperData("/config/someValue")
|
||||
;(await createMainUtils<WrapperType>(todo<Effects>())
|
||||
.store.getOwn("/config/someValue")
|
||||
.const()) satisfies string
|
||||
;(await createMainUtils(wrapperDataContract, todo<Effects>())
|
||||
.getOwnWrapperData("/config")
|
||||
;(await createMainUtils<WrapperType>(todo<Effects>())
|
||||
.store.getOwn("/config")
|
||||
.const()) satisfies WrapperType["config"]
|
||||
await createMainUtils(wrapperDataContract, todo<Effects>())
|
||||
await createMainUtils(todo<Effects>())
|
||||
// @ts-expect-error Path is wrong
|
||||
.getOwnWrapperData("/config/somdsfeValue")
|
||||
.store.getOwn("/config/somdsfeValue")
|
||||
.const()
|
||||
/// ----------------- ERRORS -----------------
|
||||
|
||||
utils(wrapperDataContract, todo<Effects>()).setOwnWrapperData("", {
|
||||
utils<WrapperType>(todo<Effects>()).store.setOwn("", {
|
||||
// @ts-expect-error Type is wrong for the setting value
|
||||
config: { someValue: "notInAOrB" },
|
||||
})
|
||||
utils(wrapperDataContract, todo<Effects>()).setOwnWrapperData(
|
||||
utils<WrapperType>(todo<Effects>()).store.setOwn(
|
||||
"/config/someValue",
|
||||
// @ts-expect-error Type is wrong for the setting value
|
||||
"notInAOrB",
|
||||
)
|
||||
;(await utils(wrapperDataContract, todo<Effects>())
|
||||
.getOwnWrapperData("/config/someValue")
|
||||
;(await utils<WrapperType>(todo<Effects>())
|
||||
.store.getOwn("/config/someValue")
|
||||
// @ts-expect-error Const should normally not be callable
|
||||
.const()) satisfies string
|
||||
;(await utils(wrapperDataContract, todo<Effects>())
|
||||
.getOwnWrapperData("/config")
|
||||
;(await utils<WrapperType>(todo<Effects>())
|
||||
.store.getOwn("/config")
|
||||
// @ts-expect-error Const should normally not be callable
|
||||
.const()) satisfies WrapperType["config"]
|
||||
await utils(wrapperDataContract, todo<Effects>())
|
||||
await utils<WrapperType>(todo<Effects>())
|
||||
// @ts-expect-error Path is wrong
|
||||
.getOwnWrapperData("/config/somdsfeValue")
|
||||
.store.getOwn("/config/somdsfeValue")
|
||||
// @ts-expect-error Const should normally not be callable
|
||||
.const()
|
||||
|
||||
///
|
||||
;(await utils(wrapperDataContract, todo<Effects>())
|
||||
.getOwnWrapperData("/config/someValue")
|
||||
;(await utils<WrapperType>(todo<Effects>())
|
||||
.store.getOwn("/config/someValue")
|
||||
// @ts-expect-error satisfies type is wrong
|
||||
.const()) satisfies number
|
||||
;(await createMainUtils(wrapperDataContract, todo<Effects>())
|
||||
;(await createMainUtils(todo<Effects>())
|
||||
// @ts-expect-error Path is wrong
|
||||
.getOwnWrapperData("/config/")
|
||||
.store.getOwn("/config/")
|
||||
.const()) satisfies WrapperType["config"]
|
||||
;(await todo<Effects>().getWrapperData<WrapperType, "/config/someValue">({
|
||||
;(await todo<Effects>().store.get<WrapperType, "/config/someValue">({
|
||||
path: "/config/someValue",
|
||||
callback: noop,
|
||||
})) satisfies string
|
||||
await todo<Effects>().getWrapperData<WrapperType, "/config/someValue">({
|
||||
await todo<Effects>().store.get<WrapperType, "/config/someValue">({
|
||||
// @ts-expect-error Path is wrong as in it doesn't match above
|
||||
path: "/config/someV2alue",
|
||||
callback: noop,
|
||||
})
|
||||
await todo<Effects>().getWrapperData<WrapperType, "/config/someV2alue">({
|
||||
await todo<Effects>().store.get<WrapperType, "/config/someV2alue">({
|
||||
// @ts-expect-error Path is wrong as in it doesn't exists in wrapper type
|
||||
path: "/config/someV2alue",
|
||||
callback: noop,
|
||||
@@ -1,4 +1,4 @@
|
||||
import { HealthStatus } from "../../types"
|
||||
import { HealthStatus } from "../types"
|
||||
|
||||
export type TriggerInput = {
|
||||
lastResult?: HealthStatus
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { TriggerInput } from "./TriggerInput"
|
||||
import { Trigger } from "./index"
|
||||
|
||||
export function changeOnFirstSuccess(o: {
|
||||
|
||||
47
lib/types.ts
47
lib/types.ts
@@ -251,26 +251,27 @@ export type Effects = {
|
||||
progress: () => Promise<number>
|
||||
}
|
||||
|
||||
/** Get a value in a json like data, can be observed and subscribed */
|
||||
getWrapperData<WrapperData = never, Path extends string = never>(options: {
|
||||
/** If there is no packageId it is assumed the current package */
|
||||
packageId?: string
|
||||
/** The path defaults to root level, using the [JsonPath](https://jsonpath.com/) */
|
||||
path: Path & EnsureWrapperDataPath<WrapperData, Path>
|
||||
callback: (config: unknown, previousConfig: unknown) => void
|
||||
}): Promise<ExtractWrapperData<WrapperData, Path>>
|
||||
store: {
|
||||
/** Get a value in a json like data, can be observed and subscribed */
|
||||
get<Store = never, Path extends string = never>(options: {
|
||||
/** If there is no packageId it is assumed the current package */
|
||||
packageId?: string
|
||||
/** The path defaults to root level, using the [JsonPath](https://jsonpath.com/) */
|
||||
path: Path & EnsureStorePath<Store, Path>
|
||||
callback: (config: unknown, previousConfig: unknown) => void
|
||||
}): Promise<ExtractStore<Store, Path>>
|
||||
/** Used to store values that can be accessed and subscribed to */
|
||||
set<Store = never, Path extends string = never>(options: {
|
||||
/** Sets the value for the wrapper at the path, it will override, using the [JsonPath](https://jsonpath.com/) */
|
||||
path: Path & EnsureStorePath<Store, Path>
|
||||
value: ExtractStore<Store, Path>
|
||||
}): Promise<void>
|
||||
}
|
||||
|
||||
getSystemSmtp(input: {
|
||||
callback: (config: unknown, previousConfig: unknown) => void
|
||||
}): Promise<SmtpValue>
|
||||
|
||||
/** Used to store values that can be accessed and subscribed to */
|
||||
setWrapperData<WrapperData = never, Path extends string = never>(options: {
|
||||
/** Sets the value for the wrapper at the path, it will override, using the [JsonPath](https://jsonpath.com/) */
|
||||
path: Path & EnsureWrapperDataPath<WrapperData, Path>
|
||||
value: ExtractWrapperData<WrapperData, Path>
|
||||
}): Promise<void>
|
||||
|
||||
getLocalHostname(): Promise<string>
|
||||
getIPHostname(): Promise<string[]>
|
||||
/** Get the address for another service for tor interfaces */
|
||||
@@ -400,20 +401,20 @@ export type Effects = {
|
||||
}
|
||||
|
||||
// prettier-ignore
|
||||
export type ExtractWrapperData<WrapperData, Path extends string> =
|
||||
Path extends `/${infer A }/${infer Rest }` ? (A extends keyof WrapperData ? ExtractWrapperData<WrapperData[A], `/${Rest}`> : never) :
|
||||
Path extends `/${infer A }` ? (A extends keyof WrapperData ? WrapperData[A] : never) :
|
||||
Path extends '' ? WrapperData :
|
||||
export type ExtractStore<Store, Path extends string> =
|
||||
Path extends `/${infer A }/${infer Rest }` ? (A extends keyof Store ? ExtractStore<Store[A], `/${Rest}`> : never) :
|
||||
Path extends `/${infer A }` ? (A extends keyof Store ? Store[A] : never) :
|
||||
Path extends '' ? Store :
|
||||
never
|
||||
|
||||
// prettier-ignore
|
||||
type _EnsureWrapperDataPath<WrapperData, Path extends string, Origin extends string> =
|
||||
Path extends`/${infer A }/${infer Rest}` ? (WrapperData extends {[K in A & string]: infer NextWrapperData} ? _EnsureWrapperDataPath<NextWrapperData, `/${Rest}`, Origin> : never) :
|
||||
Path extends `/${infer A }` ? (WrapperData extends {[K in A]: infer B} ? Origin : never) :
|
||||
type _EnsureStorePath<Store, Path extends string, Origin extends string> =
|
||||
Path extends`/${infer A }/${infer Rest}` ? (Store extends {[K in A & string]: infer NextStore} ? _EnsureStorePath<NextStore, `/${Rest}`, Origin> : never) :
|
||||
Path extends `/${infer A }` ? (Store extends {[K in A]: infer B} ? Origin : never) :
|
||||
Path extends '' ? Origin :
|
||||
never
|
||||
// prettier-ignore
|
||||
export type EnsureWrapperDataPath<WrapperData, Path extends string> = _EnsureWrapperDataPath<WrapperData, Path, Path>
|
||||
export type EnsureStorePath<Store, Path extends string> = _EnsureStorePath<Store, Path, Path>
|
||||
|
||||
/** rsync options: https://linux.die.net/man/1/rsync
|
||||
*/
|
||||
|
||||
@@ -1,29 +1,12 @@
|
||||
import { Parser, string } from "ts-matches"
|
||||
import * as T from "../types"
|
||||
import FileHelper from "./fileHelper"
|
||||
import nullIfEmpty from "./nullIfEmpty"
|
||||
import { GetWrapperData, getWrapperData } from "../wrapperData/getWrapperData"
|
||||
import {
|
||||
CheckResult,
|
||||
checkPortListening,
|
||||
checkWebUrl,
|
||||
} from "../health/checkFns"
|
||||
import { ExtractWrapperData } from "../types"
|
||||
import { GetSystemSmtp } from "./GetSystemSmtp"
|
||||
|
||||
import "./nullIfEmpty"
|
||||
import "./fileHelper"
|
||||
import "../wrapperData/getWrapperData"
|
||||
import "../store/getStore"
|
||||
import "./deepEqual"
|
||||
import "./deepMerge"
|
||||
import "./once"
|
||||
import { LocalBinding } from "../mainFn/LocalBinding"
|
||||
import { LocalPort } from "../mainFn/LocalPort"
|
||||
import { NetworkBuilder } from "../mainFn/NetworkBuilder"
|
||||
import { TorHostname } from "../mainFn/TorHostname"
|
||||
import { DefaultString } from "../config/configTypes"
|
||||
import { getDefaultString } from "./getDefaultString"
|
||||
import { WrapperDataContract } from "../wrapperData/wrapperDataContract"
|
||||
import { utils } from "./utils"
|
||||
|
||||
// prettier-ignore
|
||||
export type FlattenIntersection<T> =
|
||||
@@ -38,106 +21,9 @@ export const isKnownError = (e: unknown): e is T.KnownError =>
|
||||
|
||||
declare const affine: unique symbol
|
||||
|
||||
export type Utils<WD, WrapperOverWrite = { const: never }> = {
|
||||
createOrUpdateVault: (opts: {
|
||||
key: string
|
||||
value: string | null | undefined
|
||||
generator: DefaultString
|
||||
}) => Promise<null | string>
|
||||
readFile: <A>(fileHelper: FileHelper<A>) => ReturnType<FileHelper<A>["read"]>
|
||||
writeFile: <A>(
|
||||
fileHelper: FileHelper<A>,
|
||||
data: A,
|
||||
) => ReturnType<FileHelper<A>["write"]>
|
||||
getSystemSmtp: () => GetSystemSmtp & WrapperOverWrite
|
||||
getWrapperData: <Path extends string>(
|
||||
packageId: string,
|
||||
path: T.EnsureWrapperDataPath<WD, Path>,
|
||||
) => GetWrapperData<WD, Path> & WrapperOverWrite
|
||||
getOwnWrapperData: <Path extends string>(
|
||||
path: T.EnsureWrapperDataPath<WD, Path>,
|
||||
) => GetWrapperData<WD, Path> & WrapperOverWrite
|
||||
setOwnWrapperData: <Path extends string | never>(
|
||||
path: T.EnsureWrapperDataPath<WD, Path>,
|
||||
value: ExtractWrapperData<WD, Path>,
|
||||
) => Promise<void>
|
||||
checkPortListening(
|
||||
port: number,
|
||||
options: {
|
||||
errorMessage: string
|
||||
successMessage: string
|
||||
timeoutMessage?: string
|
||||
timeout?: number
|
||||
},
|
||||
): Promise<CheckResult>
|
||||
checkWebUrl(
|
||||
url: string,
|
||||
options?: {
|
||||
timeout?: number
|
||||
successMessage?: string
|
||||
errorMessage?: string
|
||||
},
|
||||
): Promise<CheckResult>
|
||||
bindLan: (port: number) => Promise<LocalBinding>
|
||||
networkBuilder: () => NetworkBuilder
|
||||
torHostName: (id: string) => TorHostname
|
||||
nullIfEmpty: typeof nullIfEmpty
|
||||
}
|
||||
export const utils = <WD = never, WrapperOverWrite = { const: never }>(
|
||||
effects: T.Effects,
|
||||
): Utils<WD, WrapperOverWrite> => ({
|
||||
createOrUpdateVault: async ({
|
||||
key,
|
||||
value,
|
||||
generator,
|
||||
}: {
|
||||
key: string
|
||||
value: string | null | undefined
|
||||
generator: DefaultString
|
||||
}) => {
|
||||
if (value) {
|
||||
await effects.vault.set({ key, value })
|
||||
return value
|
||||
}
|
||||
if (await effects.vault.get({ key })) {
|
||||
return null
|
||||
}
|
||||
const newValue = getDefaultString(generator)
|
||||
await effects.vault.set({ key, value: newValue })
|
||||
return newValue
|
||||
},
|
||||
getSystemSmtp: () =>
|
||||
new GetSystemSmtp(effects) as GetSystemSmtp & WrapperOverWrite,
|
||||
readFile: <A>(fileHelper: FileHelper<A>) => fileHelper.read(effects),
|
||||
writeFile: <A>(fileHelper: FileHelper<A>, data: A) =>
|
||||
fileHelper.write(data, effects),
|
||||
nullIfEmpty,
|
||||
getWrapperData: <WrapperData = never, Path extends string = never>(
|
||||
packageId: string,
|
||||
path: T.EnsureWrapperDataPath<WrapperData, Path>,
|
||||
) =>
|
||||
getWrapperData<WrapperData, Path>(effects, path as any, {
|
||||
packageId,
|
||||
}) as any,
|
||||
getOwnWrapperData: <Path extends string>(
|
||||
path: T.EnsureWrapperDataPath<WD, Path>,
|
||||
) => getWrapperData<WD, Path>(effects, path as any) as any,
|
||||
setOwnWrapperData: <Path extends string | never>(
|
||||
path: T.EnsureWrapperDataPath<WD, Path>,
|
||||
value: ExtractWrapperData<WD, Path>,
|
||||
) => effects.setWrapperData<WD, Path>({ value, path: path as any }),
|
||||
checkPortListening: checkPortListening.bind(null, effects),
|
||||
checkWebUrl: checkWebUrl.bind(null, effects),
|
||||
bindLan: async (port: number) => LocalPort.bindLan(effects, port),
|
||||
networkBuilder: () => NetworkBuilder.of(effects),
|
||||
torHostName: (id: string) => TorHostname.of(effects, id),
|
||||
})
|
||||
|
||||
export const createUtils = utils
|
||||
export const createMainUtils = <WD>(
|
||||
wrapperDataContract: WrapperDataContract<WD>,
|
||||
effects: T.Effects,
|
||||
) => createUtils<WD, {}>(wrapperDataContract, effects)
|
||||
export const createMainUtils = <Store>(effects: T.Effects) =>
|
||||
createUtils<Store, {}>(effects)
|
||||
|
||||
type NeverPossible = { [affine]: string }
|
||||
export type NoAny<A> = NeverPossible extends A
|
||||
|
||||
115
lib/util/utils.ts
Normal file
115
lib/util/utils.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
import * as T from "../types"
|
||||
import FileHelper from "./fileHelper"
|
||||
import nullIfEmpty from "./nullIfEmpty"
|
||||
import {
|
||||
CheckResult,
|
||||
checkPortListening,
|
||||
checkWebUrl,
|
||||
} from "../health/checkFns"
|
||||
import { ExtractStore } from "../types"
|
||||
import { GetSystemSmtp } from "./GetSystemSmtp"
|
||||
import { LocalBinding } from "../mainFn/LocalBinding"
|
||||
import { LocalPort } from "../mainFn/LocalPort"
|
||||
import { NetworkBuilder } from "../mainFn/NetworkBuilder"
|
||||
import { TorHostname } from "../mainFn/TorHostname"
|
||||
import { DefaultString } from "../config/configTypes"
|
||||
import { getDefaultString } from "./getDefaultString"
|
||||
import { GetStore, getStore } from "../store/getStore"
|
||||
|
||||
export type Utils<Store, WrapperOverWrite = { const: never }> = {
|
||||
createOrUpdateVault: (opts: {
|
||||
key: string
|
||||
value: string | null | undefined
|
||||
generator: DefaultString
|
||||
}) => Promise<null | string>
|
||||
readFile: <A>(fileHelper: FileHelper<A>) => ReturnType<FileHelper<A>["read"]>
|
||||
writeFile: <A>(
|
||||
fileHelper: FileHelper<A>,
|
||||
data: A,
|
||||
) => ReturnType<FileHelper<A>["write"]>
|
||||
getSystemSmtp: () => GetSystemSmtp & WrapperOverWrite
|
||||
store: {
|
||||
get: <Path extends string>(
|
||||
packageId: string,
|
||||
path: T.EnsureStorePath<Store, Path>,
|
||||
) => GetStore<Store, Path> & WrapperOverWrite
|
||||
getOwn: <Path extends string>(
|
||||
path: T.EnsureStorePath<Store, Path>,
|
||||
) => GetStore<Store, Path> & WrapperOverWrite
|
||||
setOwn: <Path extends string | never>(
|
||||
path: T.EnsureStorePath<Store, Path>,
|
||||
value: ExtractStore<Store, Path>,
|
||||
) => Promise<void>
|
||||
}
|
||||
checkPortListening(
|
||||
port: number,
|
||||
options: {
|
||||
errorMessage: string
|
||||
successMessage: string
|
||||
timeoutMessage?: string
|
||||
timeout?: number
|
||||
},
|
||||
): Promise<CheckResult>
|
||||
checkWebUrl(
|
||||
url: string,
|
||||
options?: {
|
||||
timeout?: number
|
||||
successMessage?: string
|
||||
errorMessage?: string
|
||||
},
|
||||
): Promise<CheckResult>
|
||||
bindLan: (port: number) => Promise<LocalBinding>
|
||||
networkBuilder: () => NetworkBuilder
|
||||
torHostName: (id: string) => TorHostname
|
||||
nullIfEmpty: typeof nullIfEmpty
|
||||
}
|
||||
export const utils = <Store = never, WrapperOverWrite = { const: never }>(
|
||||
effects: T.Effects,
|
||||
): Utils<Store, WrapperOverWrite> => ({
|
||||
createOrUpdateVault: async ({
|
||||
key,
|
||||
value,
|
||||
generator,
|
||||
}: {
|
||||
key: string
|
||||
value: string | null | undefined
|
||||
generator: DefaultString
|
||||
}) => {
|
||||
if (value) {
|
||||
await effects.vault.set({ key, value })
|
||||
return value
|
||||
}
|
||||
if (await effects.vault.get({ key })) {
|
||||
return null
|
||||
}
|
||||
const newValue = getDefaultString(generator)
|
||||
await effects.vault.set({ key, value: newValue })
|
||||
return newValue
|
||||
},
|
||||
getSystemSmtp: () =>
|
||||
new GetSystemSmtp(effects) as GetSystemSmtp & WrapperOverWrite,
|
||||
readFile: <A>(fileHelper: FileHelper<A>) => fileHelper.read(effects),
|
||||
writeFile: <A>(fileHelper: FileHelper<A>, data: A) =>
|
||||
fileHelper.write(data, effects),
|
||||
nullIfEmpty,
|
||||
store: {
|
||||
get: <Store = never, Path extends string = never>(
|
||||
packageId: string,
|
||||
path: T.EnsureStorePath<Store, Path>,
|
||||
) =>
|
||||
getStore<Store, Path>(effects, path as any, {
|
||||
packageId,
|
||||
}) as any,
|
||||
getOwn: <Path extends string>(path: T.EnsureStorePath<Store, Path>) =>
|
||||
getStore<Store, Path>(effects, path as any) as any,
|
||||
setOwn: <Path extends string | never>(
|
||||
path: T.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),
|
||||
bindLan: async (port: number) => LocalPort.bindLan(effects, port),
|
||||
networkBuilder: () => NetworkBuilder.of(effects),
|
||||
torHostName: (id: string) => TorHostname.of(effects, id),
|
||||
})
|
||||
@@ -28,19 +28,12 @@ function isString(x: unknown): x is string {
|
||||
|
||||
export default async function makeFileContentFromOld(
|
||||
inputData: Promise<any> | any,
|
||||
{
|
||||
startSdk = "start-sdk",
|
||||
nested = true,
|
||||
wrapperData = "../../wrapperData",
|
||||
} = {},
|
||||
{ startSdk = "start-sdk", nested = true } = {},
|
||||
) {
|
||||
const outputLines: string[] = []
|
||||
outputLines.push(`
|
||||
import { Config } from "${startSdk}/lib/config/builder/config"
|
||||
import { List } from "${startSdk}/lib/config/builder/list"
|
||||
import { Value } from "${startSdk}/lib/config/builder/value"
|
||||
import { Variants } from "${startSdk}/lib/config/builder/variants"
|
||||
import {WrapperData} from '${wrapperData}'
|
||||
import { sdk } from "${startSdk}"
|
||||
const {Config, List, Value, Variants} = sdk
|
||||
`)
|
||||
const data = await inputData
|
||||
|
||||
|
||||
Reference in New Issue
Block a user