feat: Create a dynamic action

This commit is contained in:
Blu-J
2023-05-31 10:21:53 -06:00
parent a98ccb4590
commit 7454f9a42a
4 changed files with 63 additions and 18 deletions

View File

@@ -18,6 +18,7 @@ import {
ActionResult,
BackupOptions,
DeepPartial,
MaybePromise,
} from "./types"
import * as patterns from "./util/patterns"
import { Utils } from "./util/utils"
@@ -91,7 +92,31 @@ export class StartSdk<Manifest extends SDKManifest, Store> {
utils: Utils<Store>
input: Type
}) => Promise<ActionResult>,
) => createAction<Store, ConfigType, Type>(metaData, fn),
) => {
const { input, ...rest } = metaData
return createAction<Store, ConfigType, Type>(rest, fn, input)
},
createDynamicAction: <
ConfigType extends
| Record<string, any>
| Config<any, any>
| Config<any, never>,
Type extends Record<string, any> = ExtractConfigType<ConfigType>,
>(
metaData: (options: {
effects: Effects
utils: Utils<Store>
}) => MaybePromise<Omit<ActionMetadata, "input">>,
fn: (options: {
effects: Effects
utils: Utils<Store>
input: Type
}) => Promise<ActionResult>,
input: Config<Type, Store> | Config<Type, never>,
) => {
return createAction<Store, ConfigType, Type>(metaData, fn, input)
},
HealthCheck: {
of: healthCheck,
},

View File

@@ -3,6 +3,12 @@ import { ActionMetadata, ActionResult, Effects, ExportedAction } from "../types"
import { createUtils } from "../util"
import { Utils } from "../util/utils"
export type MaybeFn<Store, Value> =
| Value
| ((options: {
effects: Effects
utils: Utils<Store>
}) => Promise<Value> | Value)
export class CreatedAction<
Store,
ConfigType extends
@@ -12,7 +18,7 @@ export class CreatedAction<
Type extends Record<string, any> = ExtractConfigType<ConfigType>,
> {
private constructor(
public readonly myMetaData: Omit<ActionMetadata, "input">,
public readonly myMetaData: MaybeFn<Store, Omit<ActionMetadata, "input">>,
readonly fn: (options: {
effects: Effects
utils: Utils<Store>
@@ -30,20 +36,18 @@ export class CreatedAction<
| Config<any, never>,
Type extends Record<string, any> = ExtractConfigType<ConfigType>,
>(
metaData: Omit<ActionMetadata, "input"> & {
input: Config<Type, Store> | Config<Type, never>
},
metaData: MaybeFn<Store, Omit<ActionMetadata, "input">>,
fn: (options: {
effects: Effects
utils: Utils<Store>
input: Type
}) => Promise<ActionResult>,
inputConfig: Config<Type, Store> | Config<Type, never>,
) {
const { input, ...rest } = metaData
return new CreatedAction<Store, ConfigType, Type>(
rest,
metaData,
fn,
input as Config<Type, Store>,
inputConfig as Config<Type, Store>,
)
}
@@ -63,12 +67,18 @@ export class CreatedAction<
})
}
async metaData(options: { effects: Effects; utils: Utils<Store> }) {
if (this.myMetaData instanceof Function)
return await this.myMetaData(options)
return this.myMetaData
}
async ActionMetadata(options: {
effects: Effects
utils: Utils<Store>
}): Promise<ActionMetadata> {
return {
...this.myMetaData,
...(await this.metaData(options)),
input: await this.input.build(options),
}
}

View File

@@ -1,24 +1,34 @@
import { Effects, ExpectedExports } from "../types"
import { createUtils } from "../util"
import { once } from "../util/once"
import { Utils } from "../util/utils"
import { CreatedAction } from "./createAction"
export function setupActions<Store>(
...createdActions: CreatedAction<Store, any>[]
) {
const myActions = once(() => {
const myActions = async (options: {
effects: Effects
utils: Utils<Store>
}) => {
const actions: Record<string, CreatedAction<Store, any>> = {}
for (const action of createdActions) {
actions[action.myMetaData.id] = action
const actionMetadata = await action.metaData(options)
actions[actionMetadata.id] = action
}
return actions
})
}
const answer: {
actions: ExpectedExports.actions
actionsMetadata: ExpectedExports.actionsMetadata
} = {
get actions() {
return myActions()
actions(options: { effects: Effects }) {
const utils = createUtils<Store>(options.effects)
return myActions({
...options,
utils,
})
},
async actionsMetadata({ effects }: { effects: Effects }) {
const utils = createUtils<Store>(effects)

View File

@@ -7,7 +7,7 @@ export type ExportedAction = (options: {
effects: Effects
input?: Record<string, unknown>
}) => Promise<ActionResult>
export type MaybePromise<A> = A | Promise<A>
export namespace ExpectedExports {
version: 1
/** Set configuration is called after we have modified and saved the configuration in the start9 ui. Use this to make a file for the docker to read from for configuration. */
@@ -39,12 +39,12 @@ export namespace ExpectedExports {
* One old use case is to add a action where we add a file, that will then be run during the
* service starting, and that file would indicate that it would rescan all the data.
*/
export type actions = {
export type actions = (options: { effects: Effects }) => MaybePromise<{
[id: string]: {
run: ExportedAction
getConfig: (options: { effects: Effects }) => Promise<InputSpec>
}
}
}>
export type actionsMetadata = (options: {
effects: Effects
@@ -160,7 +160,7 @@ export type ActionMetadata = {
description: string
id: string
input: InputSpec
allowedStatuses: "only-running" | "only-stopped" | "any"
allowedStatuses: "only-running" | "only-stopped" | "any" | "disabled"
/**
* So the ordering of the actions is by alphabetical order of the group, then followed by the alphabetical of the actions
*/