@sealcode/sealgen 0.16.1-beta3 → 0.16.2

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.
@@ -1,6 +1,6 @@
1
1
  /// <reference types="koa__router" />
2
2
  import Router from "@koa/router";
3
- import { BaseContext, Context } from "koa";
3
+ import { Context } from "koa";
4
4
  import { Templatable } from "tempstream";
5
5
  import { Mountable } from "./mountable.js";
6
6
  export type StatefulPageActionDescription<ActionName> = {
@@ -21,25 +21,25 @@ export type StateAndMetadata<State, Actions> = {
21
21
  action_args: null;
22
22
  $: Record<string, unknown>;
23
23
  };
24
- export type StatefulPageActionArgument<State extends Record<string, unknown>, Args extends unknown[] = unknown[]> = {
25
- ctx: BaseContext;
24
+ export type StatefulPageActionArgument<State extends Record<string, unknown>, Args extends unknown[] = unknown[], Page extends StatefulPage<Record<string, unknown>, any> = StatefulPage<any, any>> = {
25
+ ctx: Context;
26
26
  state: State;
27
27
  inputs: Record<string, string>;
28
28
  args: Args;
29
- page: StatefulPage<any, any>;
29
+ page: Page;
30
30
  };
31
31
  export type StatefulPageAction<State extends Record<string, unknown>, Args extends unknown[] = unknown[]> = (obj: StatefulPageActionArgument<State, Args>) => State | Promise<State>;
32
32
  export type ExtractStatefulPageActionArgs<X> = X extends StatefulPageAction<any, infer Args> ? Args : never;
33
33
  export declare abstract class StatefulPage<State extends Record<string, unknown>, Actions extends Record<string, StatefulPageAction<State>>> extends Mountable {
34
34
  abstract actions: Actions;
35
- abstract getInitialState(ctx: BaseContext): State | Promise<State>;
36
- abstract render(ctx: BaseContext, state: State, inputs: Record<string, string>): Templatable | Promise<Templatable>;
35
+ abstract getInitialState(ctx: Context): State | Promise<State>;
36
+ abstract render(ctx: Context, state: State, inputs: Record<string, string>): Templatable | Promise<Templatable>;
37
37
  canAccess(): Promise<{
38
38
  readonly canAccess: true;
39
39
  readonly message: "";
40
40
  }>;
41
41
  constructor();
42
- abstract wrapInLayout(ctx: BaseContext, content: Templatable, state: State): Templatable;
42
+ abstract wrapInLayout(ctx: Context, content: Templatable, state: State): Templatable;
43
43
  wrapInForm(context: Context, state: State, content: Templatable): Promise<Templatable>;
44
44
  extractActionAndLabel<ActionName extends keyof Actions>(action_description: StatefulPageActionDescription<ActionName>): {
45
45
  action: string;
@@ -55,9 +55,9 @@ export declare abstract class StatefulPage<State extends Record<string, unknown>
55
55
  } | ActionName, ...args: ExtractStatefulPageActionArgs<Actions[ActionName]>): string;
56
56
  rerender(): string;
57
57
  preprocessState(values: State): Promise<State>;
58
- preprocessOverrides(_context: BaseContext, _state: State, values: Record<string, unknown>): Promise<Record<string, unknown>>;
59
- serializeState(_context: BaseContext, state: State): Promise<string>;
60
- deserializeState(_context: BaseContext, s: string): Promise<State>;
61
- extractState(ctx: BaseContext): Promise<StateAndMetadata<State, Actions>>;
58
+ preprocessOverrides(_context: Context, _state: State, values: Record<string, unknown>): Promise<Record<string, unknown>>;
59
+ serializeState(_context: Context, state: State): Promise<string>;
60
+ deserializeState(_context: Context, s: string): Promise<State>;
61
+ extractState(ctx: Context): Promise<StateAndMetadata<State, Actions>>;
62
62
  mount(router: Router, path: string): void;
63
63
  }
package/lib/builder.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { build } from "esbuild";
2
2
  import glob from "tiny-glob";
3
+ import { promises as fs } from "fs";
3
4
  import { embeddable_file_extensions } from "./embeddable-file-extensions.js";
4
5
  import { load_assets_plugin } from "./esbuild-plugins/load-assets.js";
5
6
  import { rewrite_asset_imports_plugin } from "./esbuild-plugins/rewrite-asset-imports.js";
@@ -8,6 +9,7 @@ import { generateComponents } from "./generate-components.js";
8
9
  import { generateRoutes } from "./generate-routes.js";
9
10
  import { generateStimulusControllers } from "./generate-stimulus.js";
10
11
  import { FONTS_CONFIG_PATH, getFonts } from "./get-fonts.js";
12
+ import { relative } from "node:path";
11
13
  class Builder {
12
14
  constructor(project_dir) {
13
15
  this.project_dir = project_dir;
@@ -61,7 +63,7 @@ class BackendTSBuilder extends Builder {
61
63
  ","
62
64
  )}}`
63
65
  )).filter((path) => !path.includes(".#"));
64
- await build({
66
+ const { metafile } = await build({
65
67
  entryPoints,
66
68
  sourcemap: true,
67
69
  bundle: false,
@@ -75,8 +77,13 @@ class BackendTSBuilder extends Builder {
75
77
  loader: Object.fromEntries(
76
78
  embeddable_file_extensions.map((ext) => ["." + ext, "js"])
77
79
  ),
78
- plugins: [rewrite_asset_imports_plugin, load_assets_plugin]
80
+ plugins: [rewrite_asset_imports_plugin, load_assets_plugin],
81
+ metafile: true
79
82
  });
83
+ await fs.writeFile(
84
+ relative(this.project_dir, "dist") + "/back.meta.json",
85
+ JSON.stringify(metafile)
86
+ );
80
87
  }
81
88
  }
82
89
  class FrontendTSBuilder extends Builder {
@@ -91,14 +98,20 @@ class FrontendTSBuilder extends Builder {
91
98
  }
92
99
  async _build() {
93
100
  await generateStimulusControllers();
94
- await build({
101
+ const { metafile } = await build({
95
102
  entryPoints: ["./src/front/index.ts"],
96
103
  sourcemap: true,
97
104
  outfile: "./public/dist/bundle.js",
98
105
  logLevel: "info",
99
106
  bundle: true,
100
- minify: true
107
+ minify: true,
108
+ metafile: true,
109
+ treeShaking: true
101
110
  });
111
+ await fs.writeFile(
112
+ relative(this.project_dir, "dist") + "/front.meta.json",
113
+ JSON.stringify(metafile)
114
+ );
102
115
  }
103
116
  }
104
117
  export {
package/lib/get-fonts.js CHANGED
@@ -1,5 +1,6 @@
1
- import { readFile } from "fs/promises";
1
+ import { readFile, writeFile } from "fs/promises";
2
2
  import { constructURL, download } from "google-fonts-helper";
3
+ import { resolve } from "node:path";
3
4
  import { target_locreq } from "./target-locreq.js";
4
5
  const FONTS_CONFIG_PATH = "src/fonts.json";
5
6
  async function getFonts(_ = {}) {
@@ -18,6 +19,15 @@ async function getFonts(_ = {}) {
18
19
  fontsPath: "/dist/fonts"
19
20
  });
20
21
  await downloader.execute();
22
+ const fonts_css_file_path = resolve(
23
+ target_locreq.resolve("public/dist/fonts"),
24
+ "fonts.css"
25
+ );
26
+ const content = await readFile(fonts_css_file_path, "utf-8");
27
+ await writeFile(
28
+ fonts_css_file_path,
29
+ content.replace(/@font-face {/g, "@font-face {\nfont-display: swap;")
30
+ );
21
31
  console.log("Downloaded new fonts pack");
22
32
  }
23
33
  export {
@@ -2,7 +2,7 @@ import { curryImportPath } from "../utils/import-path.js";
2
2
  async function statefulPageTemplate(action_name, newfilefullpath) {
3
3
  const rel = curryImportPath(newfilefullpath);
4
4
  return `import { TempstreamJSX, Templatable } from "tempstream";
5
- import { BaseContext } from "koa";
5
+ import { Context } from "koa";
6
6
  import { StatefulPage } from "@sealcode/sealgen";
7
7
  import html from "${rel("src/back/html.js")}";
8
8
 
@@ -34,11 +34,11 @@ export default new (class ${action_name}Page extends StatefulPage<State, typeof
34
34
  return { elements: ["one", "two", "three"] };
35
35
  }
36
36
 
37
- wrapInLayout(ctx: BaseContext, content: Templatable): Templatable {
37
+ wrapInLayout(ctx: Context, content: Templatable): Templatable {
38
38
  return html(ctx, "${action_name}", content);
39
39
  }
40
40
 
41
- render(ctx: BaseContext, state: State, inputs: Record<string, string>) {
41
+ render(ctx: Context, state: State, inputs: Record<string, string>) {
42
42
  return (
43
43
  <div>
44
44
  <ul>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sealcode/sealgen",
3
- "version": "0.16.1-beta3",
3
+ "version": "0.16.2",
4
4
  "description": "Module to automate adding routes and collections to a sealious application",
5
5
  "main": "lib/index.js",
6
6
  "type": "module",
package/src/builder.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { build } from "esbuild";
2
2
  import glob from "tiny-glob";
3
+ import { promises as fs } from "fs";
3
4
  import { embeddable_file_extensions } from "./embeddable-file-extensions.js";
4
5
  import { load_assets_plugin } from "./esbuild-plugins/load-assets.js";
5
6
  import { rewrite_asset_imports_plugin } from "./esbuild-plugins/rewrite-asset-imports.js";
@@ -8,6 +9,7 @@ import { generateComponents } from "./generate-components.js";
8
9
  import { generateRoutes } from "./generate-routes.js";
9
10
  import { generateStimulusControllers } from "./generate-stimulus.js";
10
11
  import { FONTS_CONFIG_PATH, getFonts } from "./get-fonts.js";
12
+ import { relative } from "node:path";
11
13
 
12
14
  export abstract class Builder {
13
15
  abstract ownsFile(file_path: string): boolean;
@@ -84,7 +86,7 @@ export class BackendTSBuilder extends Builder {
84
86
  )}}`
85
87
  )
86
88
  ).filter((path) => !path.includes(".#"));
87
- await build({
89
+ const { metafile } = await build({
88
90
  entryPoints,
89
91
  sourcemap: true,
90
92
  bundle: false,
@@ -99,7 +101,13 @@ export class BackendTSBuilder extends Builder {
99
101
  embeddable_file_extensions.map((ext) => ["." + ext, "js"])
100
102
  ),
101
103
  plugins: [rewrite_asset_imports_plugin, load_assets_plugin],
104
+ metafile: true,
102
105
  });
106
+
107
+ await fs.writeFile(
108
+ relative(this.project_dir, "dist") + "/" + "back" + ".meta.json",
109
+ JSON.stringify(metafile)
110
+ );
103
111
  }
104
112
  }
105
113
 
@@ -120,13 +128,19 @@ export class FrontendTSBuilder extends Builder {
120
128
 
121
129
  async _build(): Promise<void> {
122
130
  await generateStimulusControllers();
123
- await build({
131
+ const { metafile } = await build({
124
132
  entryPoints: ["./src/front/index.ts"],
125
133
  sourcemap: true,
126
134
  outfile: "./public/dist/bundle.js",
127
135
  logLevel: "info",
128
136
  bundle: true,
129
137
  minify: true,
138
+ metafile: true,
139
+ treeShaking: true,
130
140
  });
141
+ await fs.writeFile(
142
+ relative(this.project_dir, "dist") + "/" + "front" + ".meta.json",
143
+ JSON.stringify(metafile)
144
+ );
131
145
  }
132
146
  }
@@ -1,6 +1,6 @@
1
1
  import Router from "@koa/router";
2
2
  import axios from "axios";
3
- import Koa, { BaseContext } from "koa";
3
+ import Koa, { Context } from "koa";
4
4
  import { Page } from "playwright";
5
5
  import { Controls, Fields, Form, Mountable } from "../index.js";
6
6
  import { mount } from "../mount.js";
@@ -205,7 +205,7 @@ describe("form test", () => {
205
205
  const app = new Koa();
206
206
  const router = new Router();
207
207
 
208
- router.use(async (ctx: BaseContext, next: any) => {
208
+ router.use(async (ctx: Context, next: any) => {
209
209
  ctx.$context = {
210
210
  user_id: "miguel",
211
211
  } as any;
package/src/get-fonts.ts CHANGED
@@ -1,5 +1,6 @@
1
- import { readFile } from "fs/promises";
1
+ import { readFile, writeFile } from "fs/promises";
2
2
  import { constructURL, download } from "google-fonts-helper";
3
+ import { resolve } from "node:path";
3
4
  import { target_locreq } from "./target-locreq.js";
4
5
 
5
6
  export const FONTS_CONFIG_PATH = "src/fonts.json";
@@ -23,5 +24,15 @@ export async function getFonts(_: Record<string, string | boolean> = {}) {
23
24
  fontsPath: "/dist/fonts",
24
25
  });
25
26
  await downloader.execute();
27
+ const fonts_css_file_path = resolve(
28
+ target_locreq.resolve("public/dist/fonts"),
29
+ "fonts.css"
30
+ );
31
+ const content = await readFile(fonts_css_file_path, "utf-8");
32
+ await writeFile(
33
+ fonts_css_file_path,
34
+ content.replace(/@font-face {/g, "@font-face {\nfont-display: swap;")
35
+ );
36
+
26
37
  console.log("Downloaded new fonts pack");
27
38
  }
package/src/mount.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
  import Router from "@koa/router";
3
3
  import { FileManager } from "@sealcode/file-manager";
4
- import Koa, { BaseContext, Context } from "koa";
4
+ import Koa, { Context } from "koa";
5
5
  import { Middlewares as SealiousMiddlewares } from "sealious";
6
6
  import { Mountable } from "./page/mountable.js";
7
7
 
@@ -26,7 +26,7 @@ export function mount(
26
26
  const raw_url = typeof url === "string" ? url : url.rawURL;
27
27
  const args = use_dummy_app
28
28
  ? [
29
- async (ctx: BaseContext, next: any) => {
29
+ async (ctx: Context, next: any) => {
30
30
  // this dummy is a temporary solution it's ilustrating the ways that
31
31
  // sealgen is coupled with sealious. Definitely room for improvement in this
32
32
  // regard
@@ -1,4 +1,4 @@
1
- import { BaseContext } from "koa";
1
+ import { Context } from "koa";
2
2
  import { Templatable, tempstream } from "tempstream";
3
3
  import {
4
4
  ExtractStatefulPageActionArgs,
@@ -22,15 +22,15 @@ describe("stateful page", () => {
22
22
  new (class extends StatefulPage<TestState, typeof actions> {
23
23
  actions = actions;
24
24
 
25
- getInitialState(_ctx: BaseContext) {
25
+ getInitialState(_ctx: Context) {
26
26
  return {};
27
27
  }
28
28
 
29
- wrapInLayout(_ctx: BaseContext, content: Templatable, _state: TestState): Templatable {
29
+ wrapInLayout(_ctx: Context, content: Templatable, _state: TestState): Templatable {
30
30
  return content;
31
31
  }
32
32
 
33
- render(_ctx: BaseContext, state: TestState) {
33
+ render(_ctx: Context, state: TestState) {
34
34
  return tempstream`<div>${this.makeActionButton(state, "some_action", 2)}</div>`;
35
35
  }
36
36
  })();
@@ -2,7 +2,7 @@
2
2
  import Router from "@koa/router";
3
3
  import { predicates, hasShape, is } from "@sealcode/ts-predicates";
4
4
  import deepmerge, { ArrayMergeOptions } from "deepmerge";
5
- import { BaseContext, Context } from "koa";
5
+ import { Context } from "koa";
6
6
  import { Templatable, tempstream } from "tempstream";
7
7
  import { from_base64, to_base64 } from "../utils/base64.js";
8
8
  import { Mountable } from "./mountable.js";
@@ -34,13 +34,17 @@ export type StateAndMetadata<State, Actions> =
34
34
 
35
35
  export type StatefulPageActionArgument<
36
36
  State extends Record<string, unknown>,
37
- Args extends unknown[] = unknown[]
37
+ Args extends unknown[] = unknown[],
38
+ Page extends StatefulPage<Record<string, unknown>, any> = StatefulPage<
39
+ any,
40
+ any
41
+ >
38
42
  > = {
39
- ctx: BaseContext;
43
+ ctx: Context;
40
44
  state: State;
41
45
  inputs: Record<string, string>;
42
46
  args: Args;
43
- page: StatefulPage<any, any>;
47
+ page: Page;
44
48
  };
45
49
 
46
50
  export type StatefulPageAction<
@@ -60,9 +64,9 @@ export abstract class StatefulPage<
60
64
  Actions extends Record<string, StatefulPageAction<State>>
61
65
  > extends Mountable {
62
66
  abstract actions: Actions;
63
- abstract getInitialState(ctx: BaseContext): State | Promise<State>;
67
+ abstract getInitialState(ctx: Context): State | Promise<State>;
64
68
  abstract render(
65
- ctx: BaseContext,
69
+ ctx: Context,
66
70
  state: State,
67
71
  inputs: Record<string, string>
68
72
  ): Templatable | Promise<Templatable>;
@@ -75,14 +79,14 @@ export abstract class StatefulPage<
75
79
  super();
76
80
  const original_render = this.render.bind(this) as typeof this.render;
77
81
  this.render = async (
78
- ctx: BaseContext,
82
+ ctx: Context,
79
83
  state: State,
80
84
  inputs: Record<string, string>
81
85
  ) => {
82
86
  return this.wrapInLayout(
83
87
  ctx,
84
88
  await this.wrapInForm(
85
- ctx as Context,
89
+ ctx,
86
90
  state,
87
91
  await original_render(ctx, state, inputs)
88
92
  ),
@@ -92,7 +96,7 @@ export abstract class StatefulPage<
92
96
  }
93
97
 
94
98
  abstract wrapInLayout(
95
- ctx: BaseContext,
99
+ ctx: Context,
96
100
  content: Templatable,
97
101
  state: State
98
102
  ): Templatable;
@@ -189,24 +193,24 @@ export abstract class StatefulPage<
189
193
  }
190
194
 
191
195
  async preprocessOverrides(
192
- _context: BaseContext,
196
+ _context: Context,
193
197
  _state: State,
194
198
  values: Record<string, unknown>
195
199
  ): Promise<Record<string, unknown>> {
196
200
  return values;
197
201
  }
198
202
 
199
- async serializeState(_context: BaseContext, state: State): Promise<string> {
203
+ async serializeState(_context: Context, state: State): Promise<string> {
200
204
  return JSON.stringify(state);
201
205
  }
202
206
 
203
- async deserializeState(_context: BaseContext, s: string): Promise<State> {
207
+ async deserializeState(_context: Context, s: string): Promise<State> {
204
208
  const deserialized = JSON.parse(s) as unknown;
205
209
  return deserialized as State;
206
210
  }
207
211
 
208
212
  async extractState(
209
- ctx: BaseContext
213
+ ctx: Context
210
214
  ): Promise<StateAndMetadata<State, Actions>> {
211
215
  if (
212
216
  !hasShape(
@@ -6,7 +6,7 @@ export async function statefulPageTemplate(
6
6
  ): Promise<string> {
7
7
  const rel = curryImportPath(newfilefullpath);
8
8
  return `import { TempstreamJSX, Templatable } from "tempstream";
9
- import { BaseContext } from "koa";
9
+ import { Context } from "koa";
10
10
  import { StatefulPage } from "@sealcode/sealgen";
11
11
  import html from "${rel("src/back/html.js")}";
12
12
 
@@ -38,11 +38,11 @@ export default new (class ${action_name}Page extends StatefulPage<State, typeof
38
38
  return { elements: ["one", "two", "three"] };
39
39
  }
40
40
 
41
- wrapInLayout(ctx: BaseContext, content: Templatable): Templatable {
41
+ wrapInLayout(ctx: Context, content: Templatable): Templatable {
42
42
  return html(ctx, "${action_name}", content);
43
43
  }
44
44
 
45
- render(ctx: BaseContext, state: State, inputs: Record<string, string>) {
45
+ render(ctx: Context, state: State, inputs: Record<string, string>) {
46
46
  return (
47
47
  <div>
48
48
  <ul>