feat: creating the rest of the sdk

This commit is contained in:
BluJ
2023-05-09 11:42:26 -06:00
parent 72df4cb502
commit 07493551b1
30 changed files with 568 additions and 504 deletions

View File

@@ -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>
}
}

View File

@@ -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>
}
}

View File

@@ -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>
}
}

View File

@@ -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>
}
}

View File

@@ -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: {

View File

@@ -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,
)