@sealcode/sealgen 0.15.59 → 0.15.61

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,6 @@
2
2
  import Router from "@koa/router";
3
3
  import { BaseContext, Context } from "koa";
4
4
  import { Templatable } from "tempstream";
5
- import { ExtractTail } from "../utils/utils.js";
6
5
  import { Mountable } from "./mountable.js";
7
6
  export type StatefulPageActionDescription<ActionName> = {
8
7
  action: ActionName;
@@ -22,7 +21,16 @@ export type StateAndMetadata<State, Actions> = {
22
21
  action_args: null;
23
22
  $: Record<string, unknown>;
24
23
  };
25
- export declare abstract class StatefulPage<State extends Record<string, unknown>, Actions extends Record<string, (ctx: BaseContext, state: State, inputs: Record<string, string>, ...args: unknown[]) => State | Promise<State>>> extends Mountable {
24
+ export type StatefulPageActionArgument<State extends Record<string, unknown>, Args extends unknown[] = unknown[]> = {
25
+ ctx: BaseContext;
26
+ state: State;
27
+ inputs: Record<string, string>;
28
+ args: Args;
29
+ page: StatefulPage<any, any>;
30
+ };
31
+ export type StatefulPageAction<State extends Record<string, unknown>, Args extends unknown[] = unknown[]> = (obj: StatefulPageActionArgument<State, Args>) => State | Promise<State>;
32
+ export type ExtractStatefulPageActionArgs<X> = X extends StatefulPageAction<any, infer Args> ? Args : never;
33
+ export declare abstract class StatefulPage<State extends Record<string, unknown>, Actions extends Record<string, StatefulPageAction<State>>> extends Mountable {
26
34
  abstract actions: Actions;
27
35
  abstract getInitialState(ctx: BaseContext): State | Promise<State>;
28
36
  abstract render(ctx: BaseContext, state: State, inputs: Record<string, string>): Templatable | Promise<Templatable>;
@@ -39,12 +47,12 @@ export declare abstract class StatefulPage<State extends Record<string, unknown>
39
47
  content: string;
40
48
  disabled: boolean;
41
49
  };
42
- makeActionURL<ActionName extends keyof Actions>(action_description: StatefulPageActionDescription<ActionName>, ...args: ExtractTail<ExtractTail<ExtractTail<Parameters<Actions[ActionName]>>>>): string;
43
- makeActionButton<ActionName extends keyof Actions>(_state: State, action_description: StatefulPageActionDescription<ActionName>, ...args: ExtractTail<ExtractTail<ExtractTail<Parameters<Actions[ActionName]>>>>): string;
50
+ makeActionURL<ActionName extends keyof Actions>(action_description: StatefulPageActionDescription<ActionName>, ...args: ExtractStatefulPageActionArgs<Actions[ActionName]>): string;
51
+ makeActionButton<ActionName extends keyof Actions>(_state: State, action_description: StatefulPageActionDescription<ActionName>, ...args: ExtractStatefulPageActionArgs<Actions[ActionName]>): string;
44
52
  makeActionCallback<ActionName extends keyof Actions>(action_description: {
45
53
  action: ActionName;
46
54
  label?: string;
47
- } | ActionName, ...args: ExtractTail<ExtractTail<ExtractTail<Parameters<Actions[ActionName]>>>>): string;
55
+ } | ActionName, ...args: ExtractStatefulPageActionArgs<Actions[ActionName]>): string;
48
56
  rerender(): string;
49
57
  preprocessState(values: State): Promise<State>;
50
58
  preprocessOverrides(_context: BaseContext, _state: State, values: Record<string, unknown>): Promise<Record<string, unknown>>;
@@ -176,14 +176,15 @@ class StatefulPage extends Mountable {
176
176
  router.post(path, async (ctx) => {
177
177
  const { action, state, inputs, action_args } = await this.extractState(ctx);
178
178
  if (action) {
179
- const new_state = await this.actions[action](
179
+ const new_state = await this.actions[action]({
180
180
  ctx,
181
181
  state,
182
182
  inputs,
183
- ...JSON.parse(
183
+ args: JSON.parse(
184
184
  from_base64(action_args)
185
- )
186
- );
185
+ ),
186
+ page: this
187
+ });
187
188
  ctx.body = this.render(ctx, new_state, inputs);
188
189
  } else {
189
190
  ctx.body = this.render(ctx, state, inputs);
@@ -1,9 +1,16 @@
1
1
  import { tempstream } from "tempstream";
2
- import { StatefulPage } from "./stateful-page.js";
2
+ import {
3
+ StatefulPage
4
+ } from "./stateful-page.js";
3
5
  describe("stateful page", () => {
6
+ it("has types that allow for extracting action argument types", () => {
7
+ const action = async ({}) => {
8
+ };
9
+ const a = [2];
10
+ });
4
11
  it("handles a basic case with action buttons", () => {
5
12
  const actions = {
6
- some_action: async (_ctx, _state, _inputs, _arg1) => {
13
+ some_action: async ({}) => {
7
14
  }
8
15
  };
9
16
  new class extends StatefulPage {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sealcode/sealgen",
3
- "version": "0.15.59",
3
+ "version": "0.15.61",
4
4
  "description": "Module to automate adding routes and collections to a sealious application",
5
5
  "main": "lib/index.js",
6
6
  "type": "module",
@@ -1,17 +1,23 @@
1
1
  import { BaseContext } from "koa";
2
2
  import { Templatable, tempstream } from "tempstream";
3
- import { StatefulPage } from "./stateful-page.js";
3
+ import {
4
+ ExtractStatefulPageActionArgs,
5
+ StatefulPage,
6
+ StatefulPageActionArgument,
7
+ } from "./stateful-page.js";
4
8
 
5
9
  describe("stateful page", () => {
10
+ it("has types that allow for extracting action argument types", () => {
11
+ type TestState = {};
12
+ const action = async ({}: StatefulPageActionArgument<TestState, [number]>) => {};
13
+ type Args = ExtractStatefulPageActionArgs<typeof action>;
14
+ const a = [2] as Args; // should not throw a typescript error;
15
+ });
16
+
6
17
  it("handles a basic case with action buttons", () => {
7
18
  type TestState = {};
8
19
  const actions = <const>{
9
- some_action: async (
10
- _ctx: BaseContext,
11
- _state: TestState,
12
- _inputs: Record<string, unknown>,
13
- _arg1: number
14
- ) => {},
20
+ some_action: async ({}: StatefulPageActionArgument<TestState, [number]>) => {},
15
21
  };
16
22
  new (class extends StatefulPage<TestState, typeof actions> {
17
23
  actions = actions;
@@ -5,7 +5,6 @@ import deepmerge, { ArrayMergeOptions } from "deepmerge";
5
5
  import { BaseContext, Context } from "koa";
6
6
  import { Templatable, tempstream } from "tempstream";
7
7
  import { from_base64, to_base64 } from "../utils/base64.js";
8
- import { ExtractTail } from "../utils/utils.js";
9
8
  import { Mountable } from "./mountable.js";
10
9
  import { isPlainObject } from "is-what";
11
10
 
@@ -33,17 +32,32 @@ export type StateAndMetadata<State, Actions> =
33
32
  $: Record<string, unknown>;
34
33
  };
35
34
 
35
+ export type StatefulPageActionArgument<
36
+ State extends Record<string, unknown>,
37
+ Args extends unknown[] = unknown[]
38
+ > = {
39
+ ctx: BaseContext;
40
+ state: State;
41
+ inputs: Record<string, string>;
42
+ args: Args;
43
+ page: StatefulPage<any, any>;
44
+ };
45
+
46
+ export type StatefulPageAction<
47
+ State extends Record<string, unknown>,
48
+ Args extends unknown[] = unknown[]
49
+ > = (obj: StatefulPageActionArgument<State, Args>) => State | Promise<State>;
50
+
51
+ export type ExtractStatefulPageActionArgs<X> = X extends StatefulPageAction<
52
+ any,
53
+ infer Args
54
+ >
55
+ ? Args
56
+ : never;
57
+
36
58
  export abstract class StatefulPage<
37
59
  State extends Record<string, unknown>,
38
- Actions extends Record<
39
- string,
40
- (
41
- ctx: BaseContext,
42
- state: State,
43
- inputs: Record<string, string>,
44
- ...args: unknown[]
45
- ) => State | Promise<State>
46
- >
60
+ Actions extends Record<string, StatefulPageAction<State>>
47
61
  > extends Mountable {
48
62
  abstract actions: Actions;
49
63
  abstract getInitialState(ctx: BaseContext): State | Promise<State>;
@@ -123,9 +137,7 @@ export abstract class StatefulPage<
123
137
 
124
138
  makeActionURL<ActionName extends keyof Actions>(
125
139
  action_description: StatefulPageActionDescription<ActionName>,
126
- ...args: ExtractTail<
127
- ExtractTail<ExtractTail<Parameters<Actions[ActionName]>>>
128
- >
140
+ ...args: ExtractStatefulPageActionArgs<Actions[ActionName]>
129
141
  ) {
130
142
  const { action } = this.extractActionAndLabel(action_description);
131
143
  return `./?action=${action}&action_args=${encodeURIComponent(
@@ -137,9 +149,7 @@ export abstract class StatefulPage<
137
149
  makeActionButton<ActionName extends keyof Actions>(
138
150
  _state: State,
139
151
  action_description: StatefulPageActionDescription<ActionName>,
140
- ...args: ExtractTail<
141
- ExtractTail<ExtractTail<Parameters<Actions[ActionName]>>>
142
- >
152
+ ...args: ExtractStatefulPageActionArgs<Actions[ActionName]>
143
153
  ) {
144
154
  const { label, content, disabled } =
145
155
  this.extractActionAndLabel(action_description);
@@ -162,9 +172,7 @@ export abstract class StatefulPage<
162
172
  label?: string;
163
173
  }
164
174
  | ActionName,
165
- ...args: ExtractTail<
166
- ExtractTail<ExtractTail<Parameters<Actions[ActionName]>>>
167
- >
175
+ ...args: ExtractStatefulPageActionArgs<Actions[ActionName]>
168
176
  ) {
169
177
  return `(()=>{const form = this.closest('form'); form.action='${this.makeActionURL(
170
178
  action_description,
@@ -301,14 +309,15 @@ export abstract class StatefulPage<
301
309
  const { action, state, inputs, action_args } =
302
310
  await this.extractState(ctx);
303
311
  if (action) {
304
- const new_state = await this.actions[action](
312
+ const new_state = await this.actions[action]({
305
313
  ctx,
306
314
  state,
307
315
  inputs,
308
- ...(JSON.parse(
316
+ args: JSON.parse(
309
317
  from_base64(action_args as string)
310
- ) as unknown[])
311
- );
318
+ ) as unknown[],
319
+ page: this,
320
+ });
312
321
  ctx.body = this.render(ctx, new_state, inputs);
313
322
  } else {
314
323
  ctx.body = this.render(ctx, state, inputs);