Refactor/actions (#2733)

* store, properties, manifest

* interfaces

* init and backups

* fix init and backups

* file models

* more versions

* dependencies

* config except dynamic types

* clean up config

* remove disabled from non-dynamic vaues

* actions

* standardize example code block formats

* wip: actions refactor

Co-authored-by: Jade <Blu-J@users.noreply.github.com>

* commit types

* fix types

* update types

* update action request type

* update apis

* add description to actionrequest

* clean up imports

* revert package json

* chore: Remove the recursive to the index

* chore: Remove the other thing I was testing

* flatten action requests

* update container runtime with new config paradigm

* new actions strategy

* seems to be working

* misc backend fixes

* fix fe bugs

* only show breakages if breakages

* only show success modal if result

* don't panic on failed removal

* hide config from actions page

* polyfill autoconfig

* use metadata strategy for actions instead of prev

* misc fixes

* chore: split the sdk into 2 libs (#2736)

* follow sideload progress (#2718)

* follow sideload progress

* small bugfix

* shareReplay with no refcount false

* don't wrap sideload progress in RPCResult

* dont present toast

---------

Co-authored-by: Aiden McClelland <me@drbonez.dev>

* chore: Add the initial of the creation of the two sdk

* chore: Add in the baseDist

* chore: Add in the baseDist

* chore: Get the web and the runtime-container running

* chore: Remove the empty file

* chore: Fix it so the container-runtime works

---------

Co-authored-by: Matt Hill <MattDHill@users.noreply.github.com>
Co-authored-by: Aiden McClelland <me@drbonez.dev>

* misc fixes

* update todos

* minor clean up

* fix link script

* update node version in CI test

* fix node version syntax in ci build

* wip: fixing callbacks

* fix sdk makefile dependencies

* add support for const outside of main

* update apis

* don't panic!

* Chore: Capture weird case on rpc, and log that

* fix procedure id issue

* pass input value for dep auto config

* handle disabled and warning for actions

* chore: Fix for link not having node_modules

* sdk fixes

* fix build

* fix build

* fix build

---------

Co-authored-by: Matt Hill <mattnine@protonmail.com>
Co-authored-by: Jade <Blu-J@users.noreply.github.com>
Co-authored-by: J H <dragondef@gmail.com>
Co-authored-by: Jade <2364004+Blu-J@users.noreply.github.com>
Co-authored-by: Matt Hill <MattDHill@users.noreply.github.com>
This commit is contained in:
Aiden McClelland
2024-09-25 16:12:52 -06:00
committed by GitHub
parent eec5cf6b65
commit db0695126f
469 changed files with 16218 additions and 10485 deletions

View File

@@ -0,0 +1,152 @@
import { InputSpec } from "./input/builder"
import { ExtractInputSpecType } from "./input/builder/inputSpec"
import * as T from "../types"
export type Run<
A extends
| Record<string, any>
| InputSpec<Record<string, any>, any>
| InputSpec<Record<string, never>, never>,
> = (options: {
effects: T.Effects
input: ExtractInputSpecType<A> & Record<string, any>
}) => Promise<T.ActionResult | null>
export type GetInput<
A extends
| Record<string, any>
| InputSpec<Record<string, any>, any>
| InputSpec<Record<string, any>, never>,
> = (options: {
effects: T.Effects
}) => Promise<null | (ExtractInputSpecType<A> & Record<string, any>)>
export type MaybeFn<T> = T | ((options: { effects: T.Effects }) => Promise<T>)
function callMaybeFn<T>(
maybeFn: MaybeFn<T>,
options: { effects: T.Effects },
): Promise<T> {
if (maybeFn instanceof Function) {
return maybeFn(options)
} else {
return Promise.resolve(maybeFn)
}
}
function mapMaybeFn<T, U>(
maybeFn: MaybeFn<T>,
map: (value: T) => U,
): MaybeFn<U> {
if (maybeFn instanceof Function) {
return async (...args) => map(await maybeFn(...args))
} else {
return map(maybeFn)
}
}
export class Action<
Id extends T.ActionId,
Store,
InputSpecType extends
| Record<string, any>
| InputSpec<any, Store>
| InputSpec<any, never>,
Type extends
ExtractInputSpecType<InputSpecType> = ExtractInputSpecType<InputSpecType>,
> {
private constructor(
readonly id: Id,
private readonly metadataFn: MaybeFn<T.ActionMetadata>,
private readonly inputSpec: InputSpecType,
private readonly getInputFn: GetInput<Type>,
private readonly runFn: Run<Type>,
) {}
static withInput<
Id extends T.ActionId,
Store,
InputSpecType extends
| Record<string, any>
| InputSpec<any, Store>
| InputSpec<any, never>,
Type extends
ExtractInputSpecType<InputSpecType> = ExtractInputSpecType<InputSpecType>,
>(
id: Id,
metadata: MaybeFn<Omit<T.ActionMetadata, "hasInput">>,
inputSpec: InputSpecType,
getInput: GetInput<Type>,
run: Run<Type>,
): Action<Id, Store, InputSpecType, Type> {
return new Action(
id,
mapMaybeFn(metadata, (m) => ({ ...m, hasInput: true })),
inputSpec,
getInput,
run,
)
}
static withoutInput<Id extends T.ActionId, Store>(
id: Id,
metadata: MaybeFn<Omit<T.ActionMetadata, "hasInput">>,
run: Run<{}>,
): Action<Id, Store, {}, {}> {
return new Action(
id,
mapMaybeFn(metadata, (m) => ({ ...m, hasInput: true })),
{},
async () => null,
run,
)
}
async exportMetadata(options: {
effects: T.Effects
}): Promise<T.ActionMetadata> {
const metadata = await callMaybeFn(this.metadataFn, options)
await options.effects.action.export({ id: this.id, metadata })
return metadata
}
async getInput(options: { effects: T.Effects }): Promise<T.ActionInput> {
return {
spec: await this.inputSpec.build(options),
value: (await this.getInputFn(options)) || null,
}
}
async run(options: {
effects: T.Effects
input: Type
}): Promise<T.ActionResult | null> {
return this.runFn(options)
}
}
export class Actions<
Store,
AllActions extends Record<T.ActionId, Action<T.ActionId, Store, any, any>>,
> {
private constructor(private readonly actions: AllActions) {}
static of<Store>(): Actions<Store, {}> {
return new Actions({})
}
addAction<A extends Action<T.ActionId, Store, any, any>>(
action: A,
): Actions<Store, AllActions & { [id in A["id"]]: A }> {
return new Actions({ ...this.actions, [action.id]: action })
}
update(options: { effects: T.Effects }): Promise<void> {
const updater = async (options: { effects: T.Effects }) => {
for (let action of Object.values(this.actions)) {
await action.exportMetadata(options)
}
await options.effects.action.clear({ except: Object.keys(this.actions) })
}
const updaterCtx = { options }
updaterCtx.options = {
effects: {
...options.effects,
constRetry: () => updater(updaterCtx.options),
},
}
return updater(updaterCtx.options)
}
get<Id extends T.ActionId>(actionId: Id): AllActions[Id] {
return this.actions[actionId]
}
}