@sealcode/sealgen 0.14.4 → 0.14.5
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.
- package/@types/src/builder.d.ts +36 -0
- package/@types/src/embeddable-file-extensions.d.ts +1 -0
- package/@types/src/esbuild-plugins/load-assets.d.ts +4 -0
- package/@types/src/esbuild-plugins/rewrite-asset-imports.d.ts +4 -0
- package/@types/src/generate-stimulus.d.ts +1 -0
- package/@types/src/page/stateful-page.d.ts +1 -1
- package/@types/src/templates/stimulus-controller.d.ts +1 -0
- package/dist/build.js +29 -213
- package/dist/builder.js +145 -0
- package/dist/cli.js +3 -1
- package/dist/embeddable-file-extensions.js +5 -0
- package/dist/esbuild-plugins/load-assets.js +67 -0
- package/dist/esbuild-plugins/rewrite-asset-imports.js +30 -0
- package/dist/generate-stimulus.js +41 -0
- package/dist/page/stateful-page.js +3 -2
- package/dist/templates/stimulus-controller.js +21 -0
- package/package.json +1 -1
- package/src/build.ts +30 -234
- package/src/builder.ts +176 -0
- package/src/cli.ts +3 -1
- package/src/embeddable-file-extensions.ts +1 -0
- package/src/esbuild-plugins/load-assets.ts +68 -0
- package/src/esbuild-plugins/rewrite-asset-imports.ts +29 -0
- package/src/generate-stimulus.ts +52 -0
- package/src/page/stateful-page.ts +8 -3
- package/src/templates/stimulus-controller.ts +18 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { BuildContext } from "esbuild";
|
|
2
|
+
export declare abstract class Builder {
|
|
3
|
+
abstract ownsFile(file_path: string): boolean;
|
|
4
|
+
abstract getName(): string;
|
|
5
|
+
abstract _build(): Promise<void>;
|
|
6
|
+
abstract dispose(): Promise<void>;
|
|
7
|
+
constructor();
|
|
8
|
+
ongoing_build: Promise<void> | null;
|
|
9
|
+
build(notifier?: (message: string) => void): Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
export declare class CSSBuilder extends Builder {
|
|
12
|
+
getName(): string;
|
|
13
|
+
private context_promise;
|
|
14
|
+
ownsFile(file_path: string): boolean;
|
|
15
|
+
dispose(): Promise<void>;
|
|
16
|
+
getBuildContext(): Promise<BuildContext>;
|
|
17
|
+
_build(): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
export declare class FontsBuilder extends Builder {
|
|
20
|
+
getName(): string;
|
|
21
|
+
ownsFile(file_path: string): boolean;
|
|
22
|
+
dispose(): Promise<void>;
|
|
23
|
+
_build(): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
export declare class BackendTSBuilder extends Builder {
|
|
26
|
+
getName(): string;
|
|
27
|
+
ownsFile(file_path: string): boolean;
|
|
28
|
+
dispose(): Promise<void>;
|
|
29
|
+
_build(): Promise<void>;
|
|
30
|
+
}
|
|
31
|
+
export declare class FrontendTSBuilder extends Builder {
|
|
32
|
+
getName(): string;
|
|
33
|
+
ownsFile(file_path: string): boolean;
|
|
34
|
+
dispose(): Promise<void>;
|
|
35
|
+
_build(): Promise<void>;
|
|
36
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const embeddable_file_extensions: string[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function generateStimulusControllers(): Promise<void>;
|
|
@@ -30,7 +30,7 @@ export declare abstract class StatefulPage<State extends Record<string, unknown>
|
|
|
30
30
|
readonly message: "";
|
|
31
31
|
}>;
|
|
32
32
|
constructor();
|
|
33
|
-
abstract wrapInLayout(ctx: BaseContext, content: Templatable): Templatable;
|
|
33
|
+
abstract wrapInLayout(ctx: BaseContext, content: Templatable, state: State): Templatable;
|
|
34
34
|
wrapInForm(state: State, content: Templatable): Templatable;
|
|
35
35
|
extractActionAndLabel<ActionName extends keyof Actions>(action_description: StatefulPageActionDescription<ActionName>): {
|
|
36
36
|
action: string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function jddComponentTemplate(controller_name: string): string;
|
package/dist/build.js
CHANGED
|
@@ -1,20 +1,14 @@
|
|
|
1
|
-
import { build, context } from "esbuild";
|
|
2
1
|
import { promises as fs } from "fs";
|
|
3
2
|
import * as chokidar from "chokidar";
|
|
4
|
-
import { default as glob } from "tiny-glob";
|
|
5
|
-
import { generate_css_includes } from "./find-css-includes.js";
|
|
6
|
-
import { sleep } from "./utils/sleep.js";
|
|
7
|
-
import { generateCollections } from "./generate-collections.js";
|
|
8
|
-
import { generateRoutes } from "./generate-routes.js";
|
|
9
|
-
import { generateComponents } from "./generate-components.js";
|
|
10
3
|
import { make_notifier } from "./notifier.js";
|
|
11
4
|
import getPort from "get-port";
|
|
12
|
-
import { removeNamedImports } from "../remove-named-imports.js";
|
|
13
|
-
import md5 from "md5";
|
|
14
5
|
import _locreq from "locreq";
|
|
15
|
-
import
|
|
16
|
-
|
|
17
|
-
|
|
6
|
+
import {
|
|
7
|
+
BackendTSBuilder,
|
|
8
|
+
CSSBuilder,
|
|
9
|
+
FontsBuilder,
|
|
10
|
+
FrontendTSBuilder
|
|
11
|
+
} from "./builder.js";
|
|
18
12
|
const target_locreq = _locreq(process.cwd());
|
|
19
13
|
async function get_notifier_port() {
|
|
20
14
|
return getPort({ port: 4e3 });
|
|
@@ -29,222 +23,44 @@ async function write_notifier_config(watch, port) {
|
|
|
29
23
|
JSON.stringify(config)
|
|
30
24
|
);
|
|
31
25
|
}
|
|
32
|
-
function
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
);
|
|
44
|
-
return "/" + public_url;
|
|
45
|
-
}
|
|
46
|
-
async function build_ts() {
|
|
47
|
-
await Promise.all([
|
|
48
|
-
generateCollections(),
|
|
49
|
-
generateRoutes(),
|
|
50
|
-
generateComponents()
|
|
51
|
-
]);
|
|
52
|
-
const embeddable_file_extensions = ["svg", "png", "jpg", "jpeg", "webp"];
|
|
53
|
-
const entryPoints = (await glob(
|
|
54
|
-
`./src/back/**/*.{ts,tsx,${embeddable_file_extensions.join(",")}}`
|
|
55
|
-
)).filter((path2) => !path2.includes(".#"));
|
|
56
|
-
try {
|
|
57
|
-
await build({
|
|
58
|
-
entryPoints,
|
|
59
|
-
sourcemap: true,
|
|
60
|
-
bundle: false,
|
|
61
|
-
jsxFactory: "TempstreamJSX.createElement",
|
|
62
|
-
outdir: "./dist/back",
|
|
63
|
-
logLevel: "info",
|
|
64
|
-
platform: "node",
|
|
65
|
-
target: "es2022",
|
|
66
|
-
format: "esm",
|
|
67
|
-
loader: Object.fromEntries(
|
|
68
|
-
embeddable_file_extensions.map((ext) => ["." + ext, "js"])
|
|
69
|
-
),
|
|
70
|
-
plugins: [
|
|
71
|
-
{
|
|
72
|
-
name: "sealgen-rewrite-asset-imports",
|
|
73
|
-
setup(build2) {
|
|
74
|
-
build2.onLoad(
|
|
75
|
-
{ filter: /\.tsx?$/ },
|
|
76
|
-
async (args) => {
|
|
77
|
-
let contents = await fs.readFile(
|
|
78
|
-
args.path,
|
|
79
|
-
"utf8"
|
|
80
|
-
);
|
|
81
|
-
for (const ext of embeddable_file_extensions) {
|
|
82
|
-
const regex = new RegExp(
|
|
83
|
-
`^import (\\w+|{[^}]+}) from "([^"]+.${ext})";`,
|
|
84
|
-
"gm"
|
|
85
|
-
);
|
|
86
|
-
contents = contents.replaceAll(
|
|
87
|
-
regex,
|
|
88
|
-
(line) => {
|
|
89
|
-
return line.replace(
|
|
90
|
-
`.${ext}"`,
|
|
91
|
-
'.js"'
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
contents = removeNamedImports(contents);
|
|
97
|
-
return {
|
|
98
|
-
contents,
|
|
99
|
-
loader: extname(args.path) === ".tsx" ? "tsx" : "ts"
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
},
|
|
105
|
-
{
|
|
106
|
-
name: "sealgen-load-assets",
|
|
107
|
-
setup(build2) {
|
|
108
|
-
build2.onLoad(
|
|
109
|
-
{
|
|
110
|
-
filter: new RegExp(
|
|
111
|
-
`\\.(${embeddable_file_extensions.join(
|
|
112
|
-
"|"
|
|
113
|
-
)})$`
|
|
114
|
-
)
|
|
115
|
-
},
|
|
116
|
-
async (args) => {
|
|
117
|
-
let contents = `export const url = "${await makeResourceURL(
|
|
118
|
-
args.path
|
|
119
|
-
)}";
|
|
120
|
-
|
|
121
|
-
import fs from "fs";
|
|
122
|
-
let buffer_promise = null;
|
|
123
|
-
|
|
124
|
-
export const getBuffer = function(){
|
|
125
|
-
if(buffer_promise) return buffer_promise;
|
|
126
|
-
buffer_promise = fs.promises.readFile("${args.path}");
|
|
127
|
-
return buffer_promise;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export const getContent = async function(){
|
|
131
|
-
const buffer = await getBuffer();
|
|
132
|
-
return buffer.toString("utf-8");
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
export const getBase64 = async function(){
|
|
136
|
-
const buffer = await getBuffer();
|
|
137
|
-
return buffer.toString("base64");
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
export default { getContent, url, getBase64, getBuffer };
|
|
141
|
-
`;
|
|
142
|
-
return {
|
|
143
|
-
contents
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
]
|
|
150
|
-
});
|
|
151
|
-
} catch (e) {
|
|
152
|
-
console.error(e.message);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
async function complex_build(watch) {
|
|
156
|
-
const loader = Object.fromEntries(
|
|
157
|
-
["png", "svg", "jpg", "gif", "jpeg", "otf", "ttf"].map(
|
|
158
|
-
(ext) => ["." + ext, "file"]
|
|
159
|
-
)
|
|
160
|
-
);
|
|
161
|
-
let css_build = await context({
|
|
162
|
-
entryPoints: ["./src/main.css"],
|
|
163
|
-
sourcemap: true,
|
|
164
|
-
bundle: true,
|
|
165
|
-
outdir: "./public/dist",
|
|
166
|
-
logLevel: "info",
|
|
167
|
-
// plugins: [sassPlugin()],
|
|
168
|
-
loader
|
|
169
|
-
});
|
|
170
|
-
let ongoing_fonts = false;
|
|
171
|
-
let ongoing_ts = false;
|
|
172
|
-
let ongoing_css = false;
|
|
173
|
-
let ongoing_ts_promise = null;
|
|
26
|
+
async function build(watch) {
|
|
27
|
+
const fonts_builder = new FontsBuilder();
|
|
28
|
+
const backend_ts_builder = new BackendTSBuilder();
|
|
29
|
+
const frontend_ts_builder = new FrontendTSBuilder();
|
|
30
|
+
const css_builder = new CSSBuilder();
|
|
31
|
+
const builders = [
|
|
32
|
+
fonts_builder,
|
|
33
|
+
backend_ts_builder,
|
|
34
|
+
css_builder,
|
|
35
|
+
frontend_ts_builder
|
|
36
|
+
];
|
|
37
|
+
await Promise.all(builders.map((b) => b.build()));
|
|
174
38
|
if (watch) {
|
|
175
39
|
const watcher = chokidar.watch("src", { ignoreInitial: true });
|
|
176
40
|
const port = await get_notifier_port();
|
|
177
41
|
const notifier = make_notifier(port);
|
|
178
42
|
await write_notifier_config(watch, port);
|
|
179
|
-
watcher.on("all", async (_,
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
if (!ongoing_fonts) {
|
|
186
|
-
ongoing_fonts = true;
|
|
187
|
-
await getFonts();
|
|
188
|
-
ongoing_fonts = false;
|
|
189
|
-
}
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
|
-
if (path2.endsWith(".css") && !path2.endsWith("/includes.css")) {
|
|
193
|
-
if (ongoing_css) {
|
|
194
|
-
return;
|
|
195
|
-
}
|
|
196
|
-
ongoing_css = true;
|
|
197
|
-
await generate_css_includes();
|
|
198
|
-
try {
|
|
199
|
-
await css_build?.rebuild?.();
|
|
200
|
-
console.log(`Built main.css [on ${path2}]`);
|
|
201
|
-
} catch (e) {
|
|
202
|
-
console.error(e.message);
|
|
203
|
-
await sleep(200);
|
|
204
|
-
css_build?.rebuild?.().catch((e2) => console.error(e2?.message));
|
|
205
|
-
}
|
|
206
|
-
if (ongoing_ts_promise) {
|
|
207
|
-
await ongoing_ts_promise;
|
|
208
|
-
}
|
|
209
|
-
notifier("css");
|
|
210
|
-
ongoing_css = false;
|
|
211
|
-
}
|
|
212
|
-
if ((path2.endsWith(".ts") || path2.endsWith(".tsx")) && !path2.endsWith("src/back/collections/collections.ts") && !path2.endsWith("src/back/routes/routes.ts") && !path2.endsWith("src/back/routes/urls.ts")) {
|
|
213
|
-
if (ongoing_ts) {
|
|
214
|
-
return;
|
|
43
|
+
watcher.on("all", async (_, file_path) => {
|
|
44
|
+
console.log("Detected a change!", file_path);
|
|
45
|
+
builders.forEach((builder) => {
|
|
46
|
+
const owns_a_file = builder.ownsFile(file_path);
|
|
47
|
+
if (owns_a_file) {
|
|
48
|
+
builder.build(notifier);
|
|
215
49
|
}
|
|
216
|
-
|
|
217
|
-
ongoing_ts_promise = build_ts();
|
|
218
|
-
await ongoing_ts_promise;
|
|
219
|
-
notifier("ts");
|
|
220
|
-
ongoing_ts_promise = null;
|
|
221
|
-
console.log(`Finished TS build [on ${path2}]`);
|
|
222
|
-
ongoing_ts = false;
|
|
223
|
-
}
|
|
50
|
+
});
|
|
224
51
|
});
|
|
225
52
|
} else {
|
|
226
53
|
await write_notifier_config(watch);
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
if (watch) {
|
|
231
|
-
css_build?.rebuild?.();
|
|
232
|
-
} else {
|
|
233
|
-
css_build.dispose();
|
|
54
|
+
builders.forEach((builder) => {
|
|
55
|
+
builder.dispose();
|
|
56
|
+
});
|
|
234
57
|
}
|
|
235
58
|
}
|
|
236
59
|
async function buildProject({
|
|
237
60
|
watch
|
|
238
61
|
}) {
|
|
239
62
|
try {
|
|
240
|
-
await build(
|
|
241
|
-
entryPoints: ["./src/front/index.ts"],
|
|
242
|
-
sourcemap: true,
|
|
243
|
-
outfile: "./public/dist/bundle.js",
|
|
244
|
-
logLevel: "info",
|
|
245
|
-
bundle: true
|
|
246
|
-
});
|
|
247
|
-
await complex_build(watch);
|
|
63
|
+
await build(watch);
|
|
248
64
|
} catch (e) {
|
|
249
65
|
console.log("CAUGHT!");
|
|
250
66
|
console.error(e.message);
|
package/dist/builder.js
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { build, context } from "esbuild";
|
|
2
|
+
import glob from "tiny-glob";
|
|
3
|
+
import { embeddable_file_extensions } from "./embeddable-file-extensions.js";
|
|
4
|
+
import { load_assets_plugin } from "./esbuild-plugins/load-assets.js";
|
|
5
|
+
import { rewrite_asset_imports_plugin } from "./esbuild-plugins/rewrite-asset-imports.js";
|
|
6
|
+
import { generate_css_includes } from "./find-css-includes.js";
|
|
7
|
+
import { generateCollections } from "./generate-collections.js";
|
|
8
|
+
import { generateComponents } from "./generate-components.js";
|
|
9
|
+
import { generateRoutes } from "./generate-routes.js";
|
|
10
|
+
import { generateStimulusControllers } from "./generate-stimulus.js";
|
|
11
|
+
import { FONTS_CONFIG_PATH, getFonts } from "./get-fonts.js";
|
|
12
|
+
class Builder {
|
|
13
|
+
constructor() {
|
|
14
|
+
this.ongoing_build = null;
|
|
15
|
+
}
|
|
16
|
+
build(notifier) {
|
|
17
|
+
if (!this.ongoing_build) {
|
|
18
|
+
const build2 = this._build().catch((err) => {
|
|
19
|
+
console.error(err);
|
|
20
|
+
}).then(() => {
|
|
21
|
+
notifier?.(this.getName());
|
|
22
|
+
this.ongoing_build = null;
|
|
23
|
+
});
|
|
24
|
+
this.ongoing_build = build2;
|
|
25
|
+
}
|
|
26
|
+
return this.ongoing_build;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
class CSSBuilder extends Builder {
|
|
30
|
+
getName() {
|
|
31
|
+
return "css";
|
|
32
|
+
}
|
|
33
|
+
ownsFile(file_path) {
|
|
34
|
+
return file_path.endsWith(".css") && !file_path.endsWith("/includes.css");
|
|
35
|
+
}
|
|
36
|
+
async dispose() {
|
|
37
|
+
return (await this.getBuildContext()).dispose();
|
|
38
|
+
}
|
|
39
|
+
async getBuildContext() {
|
|
40
|
+
if (!this.context_promise) {
|
|
41
|
+
const loader = Object.fromEntries(
|
|
42
|
+
["png", "svg", "jpg", "gif", "jpeg", "otf", "ttf"].map(
|
|
43
|
+
(ext) => ["." + ext, "file"]
|
|
44
|
+
)
|
|
45
|
+
);
|
|
46
|
+
const context_promise = context({
|
|
47
|
+
entryPoints: ["./src/main.css"],
|
|
48
|
+
sourcemap: true,
|
|
49
|
+
bundle: true,
|
|
50
|
+
outdir: "./public/dist",
|
|
51
|
+
logLevel: "info",
|
|
52
|
+
// plugins: [sassPlugin()],
|
|
53
|
+
loader
|
|
54
|
+
});
|
|
55
|
+
this.context_promise = context_promise;
|
|
56
|
+
return context_promise;
|
|
57
|
+
} else {
|
|
58
|
+
return this.context_promise;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
async _build() {
|
|
62
|
+
const context2 = await this.getBuildContext();
|
|
63
|
+
await generate_css_includes();
|
|
64
|
+
await context2.rebuild();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
class FontsBuilder extends Builder {
|
|
68
|
+
getName() {
|
|
69
|
+
return "fonts";
|
|
70
|
+
}
|
|
71
|
+
ownsFile(file_path) {
|
|
72
|
+
return file_path == FONTS_CONFIG_PATH;
|
|
73
|
+
}
|
|
74
|
+
async dispose() {
|
|
75
|
+
}
|
|
76
|
+
async _build() {
|
|
77
|
+
return getFonts();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
class BackendTSBuilder extends Builder {
|
|
81
|
+
getName() {
|
|
82
|
+
return "backend-ts";
|
|
83
|
+
}
|
|
84
|
+
ownsFile(file_path) {
|
|
85
|
+
return (file_path.endsWith(".ts") || file_path.endsWith(".tsx")) && !file_path.endsWith("src/back/collections/collections.ts") && !file_path.endsWith("src/back/routes/routes.ts") && !file_path.endsWith("src/back/routes/urls.ts") && !file_path.endsWith("stimulus.ts") && !file_path.startsWith("src/front");
|
|
86
|
+
}
|
|
87
|
+
async dispose() {
|
|
88
|
+
}
|
|
89
|
+
async _build() {
|
|
90
|
+
await Promise.all([
|
|
91
|
+
generateCollections(),
|
|
92
|
+
generateRoutes(),
|
|
93
|
+
generateComponents()
|
|
94
|
+
]);
|
|
95
|
+
const entryPoints = (await glob(
|
|
96
|
+
`./src/back/**/*.{ts,tsx,${embeddable_file_extensions.join(
|
|
97
|
+
","
|
|
98
|
+
)}}`
|
|
99
|
+
)).filter((path) => !path.includes(".#"));
|
|
100
|
+
await build({
|
|
101
|
+
entryPoints,
|
|
102
|
+
sourcemap: true,
|
|
103
|
+
bundle: false,
|
|
104
|
+
jsxFactory: "TempstreamJSX.createElement",
|
|
105
|
+
outdir: "./dist/back",
|
|
106
|
+
logLevel: "info",
|
|
107
|
+
platform: "node",
|
|
108
|
+
target: "es2022",
|
|
109
|
+
format: "esm",
|
|
110
|
+
loader: Object.fromEntries(
|
|
111
|
+
embeddable_file_extensions.map((ext) => ["." + ext, "js"])
|
|
112
|
+
),
|
|
113
|
+
plugins: [rewrite_asset_imports_plugin, load_assets_plugin]
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
class FrontendTSBuilder extends Builder {
|
|
118
|
+
getName() {
|
|
119
|
+
return "frontend-ts";
|
|
120
|
+
}
|
|
121
|
+
ownsFile(file_path) {
|
|
122
|
+
return file_path.startsWith("src/front") || file_path.endsWith(".stimulus.ts");
|
|
123
|
+
}
|
|
124
|
+
async dispose() {
|
|
125
|
+
}
|
|
126
|
+
async _build() {
|
|
127
|
+
await generateStimulusControllers();
|
|
128
|
+
await build({
|
|
129
|
+
entryPoints: ["./src/front/index.ts"],
|
|
130
|
+
sourcemap: true,
|
|
131
|
+
outfile: "./public/dist/bundle.js",
|
|
132
|
+
logLevel: "info",
|
|
133
|
+
bundle: true,
|
|
134
|
+
minify: true
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
export {
|
|
139
|
+
BackendTSBuilder,
|
|
140
|
+
Builder,
|
|
141
|
+
CSSBuilder,
|
|
142
|
+
FontsBuilder,
|
|
143
|
+
FrontendTSBuilder
|
|
144
|
+
};
|
|
145
|
+
//# sourceMappingURL=builder.js.map
|
package/dist/cli.js
CHANGED
|
@@ -10,6 +10,7 @@ import { generateRoutes } from "./generate-routes.js";
|
|
|
10
10
|
import { makeEnv } from "./make-env.js";
|
|
11
11
|
import yargs from "yargs/yargs";
|
|
12
12
|
import { getFonts } from "./get-fonts.js";
|
|
13
|
+
import { generateStimulusControllers } from "./generate-stimulus.js";
|
|
13
14
|
const actions = {
|
|
14
15
|
"add-collection": addCollection,
|
|
15
16
|
"add-route": addRoute,
|
|
@@ -26,7 +27,8 @@ const actions = {
|
|
|
26
27
|
},
|
|
27
28
|
"make-env": makeEnv,
|
|
28
29
|
"add-component": addJDDComponent,
|
|
29
|
-
"get-fonts": getFonts
|
|
30
|
+
"get-fonts": getFonts,
|
|
31
|
+
"generate-stimulus": generateStimulusControllers
|
|
30
32
|
};
|
|
31
33
|
void async function() {
|
|
32
34
|
const action = process.argv.at(2);
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { copyFile } from "fs/promises";
|
|
2
|
+
import { promises as fs } from "fs";
|
|
3
|
+
import md5 from "md5";
|
|
4
|
+
import path, { basename } from "node:path";
|
|
5
|
+
import _locreq from "locreq";
|
|
6
|
+
import { embeddable_file_extensions } from "../embeddable-file-extensions.js";
|
|
7
|
+
const target_locreq = _locreq(process.cwd());
|
|
8
|
+
function addSuffix(filename, suffix) {
|
|
9
|
+
return filename.replace(/(\.[a-zA-Z0-9]+)?$/, suffix + "$1");
|
|
10
|
+
}
|
|
11
|
+
async function makeResourceURL(file_path) {
|
|
12
|
+
const hash_base = file_path + (await fs.stat(file_path)).mtimeMs;
|
|
13
|
+
const hash = md5(hash_base);
|
|
14
|
+
const public_url = "dist/" + addSuffix(basename(file_path), "-" + hash.slice(0, 8));
|
|
15
|
+
const public_dir = "public";
|
|
16
|
+
await copyFile(
|
|
17
|
+
file_path,
|
|
18
|
+
target_locreq.resolve(path.resolve(public_dir, public_url))
|
|
19
|
+
);
|
|
20
|
+
return "/" + public_url;
|
|
21
|
+
}
|
|
22
|
+
const load_assets_plugin = {
|
|
23
|
+
name: "sealgen-load-assets",
|
|
24
|
+
setup(build) {
|
|
25
|
+
build.onLoad(
|
|
26
|
+
{
|
|
27
|
+
filter: new RegExp(
|
|
28
|
+
`\\.(${embeddable_file_extensions.join("|")})$`
|
|
29
|
+
)
|
|
30
|
+
},
|
|
31
|
+
async (args) => {
|
|
32
|
+
let contents = `export const url = "${await makeResourceURL(
|
|
33
|
+
args.path
|
|
34
|
+
)}";
|
|
35
|
+
|
|
36
|
+
import fs from "fs";
|
|
37
|
+
let buffer_promise = null;
|
|
38
|
+
|
|
39
|
+
export const getBuffer = function(){
|
|
40
|
+
if(buffer_promise) return buffer_promise;
|
|
41
|
+
buffer_promise = fs.promises.readFile("${args.path}");
|
|
42
|
+
return buffer_promise;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const getContent = async function(){
|
|
46
|
+
const buffer = await getBuffer();
|
|
47
|
+
return buffer.toString("utf-8");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export const getBase64 = async function(){
|
|
51
|
+
const buffer = await getBuffer();
|
|
52
|
+
return buffer.toString("base64");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export default { getContent, url, getBase64, getBuffer };
|
|
56
|
+
`;
|
|
57
|
+
return {
|
|
58
|
+
contents
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
export {
|
|
65
|
+
load_assets_plugin
|
|
66
|
+
};
|
|
67
|
+
//# sourceMappingURL=load-assets.js.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { promises as fs } from "fs";
|
|
2
|
+
import { extname } from "node:path";
|
|
3
|
+
import { embeddable_file_extensions } from "../embeddable-file-extensions.js";
|
|
4
|
+
import { removeNamedImports } from "../../remove-named-imports.js";
|
|
5
|
+
const rewrite_asset_imports_plugin = {
|
|
6
|
+
name: "sealgen-rewrite-asset-imports",
|
|
7
|
+
setup(build) {
|
|
8
|
+
build.onLoad({ filter: /\.tsx?$/ }, async (args) => {
|
|
9
|
+
let contents = await fs.readFile(args.path, "utf8");
|
|
10
|
+
for (const ext of embeddable_file_extensions) {
|
|
11
|
+
const regex_assets = new RegExp(
|
|
12
|
+
`^import (\\w+|{[^}]+}) from "([^"]+.${ext})";`,
|
|
13
|
+
"gm"
|
|
14
|
+
);
|
|
15
|
+
contents = contents.replaceAll(regex_assets, (line) => {
|
|
16
|
+
return line.replace(`.${ext}"`, '.js"');
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
contents = removeNamedImports(contents);
|
|
20
|
+
return {
|
|
21
|
+
contents,
|
|
22
|
+
loader: extname(args.path) === ".tsx" ? "tsx" : "ts"
|
|
23
|
+
};
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
export {
|
|
28
|
+
rewrite_asset_imports_plugin
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=rewrite-asset-imports.js.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import _locreq from "locreq";
|
|
2
|
+
import * as prettier from "prettier";
|
|
3
|
+
import { promises as fs } from "fs";
|
|
4
|
+
import { getPrettierConfig } from "./utils/prettier.js";
|
|
5
|
+
import recursive from "recursive-readdir";
|
|
6
|
+
import path, { dirname } from "path";
|
|
7
|
+
import { toKebabCase, toPascalCase } from "js-convert-case";
|
|
8
|
+
const target_locreq = _locreq(process.cwd());
|
|
9
|
+
async function generateStimulusControllers() {
|
|
10
|
+
const output_file = "src/front/controllers.ts";
|
|
11
|
+
const stimulus_search_dir = target_locreq.resolve("src/");
|
|
12
|
+
const controller_names = (await recursive(stimulus_search_dir)).filter((c) => c.endsWith(".stimulus.ts")).sort();
|
|
13
|
+
const controller_data = controller_names.map(
|
|
14
|
+
(p) => "./" + path.relative(target_locreq.resolve(dirname(output_file)), p).replace(/\.[tj]sx?$/, ".js")
|
|
15
|
+
).map((relative_path) => {
|
|
16
|
+
const name = relative_path.match(/\/([^\/]+).stimulus/)?.[1];
|
|
17
|
+
return { name, relative_path };
|
|
18
|
+
});
|
|
19
|
+
const content = `// DO NOT EDIT! This file is generated automaticaly with 'npm run generate-stimulus'
|
|
20
|
+
|
|
21
|
+
import * as Turbo from "@hotwired/turbo";
|
|
22
|
+
import { Application } from "stimulus";
|
|
23
|
+
const application = Application.start();
|
|
24
|
+
${controller_data.map(
|
|
25
|
+
(c) => `
|
|
26
|
+
import { default as ${toPascalCase(c.name)} } from "${c.relative_path}";
|
|
27
|
+
application.register("${toKebabCase(c.name)}", ${toPascalCase(c.name)});`
|
|
28
|
+
).join("\n")}
|
|
29
|
+
|
|
30
|
+
export { Turbo };
|
|
31
|
+
`;
|
|
32
|
+
await fs.writeFile(
|
|
33
|
+
target_locreq.resolve(output_file),
|
|
34
|
+
prettier.format(content, await getPrettierConfig())
|
|
35
|
+
);
|
|
36
|
+
console.log(`Successfuly generated new ${output_file} file`);
|
|
37
|
+
}
|
|
38
|
+
export {
|
|
39
|
+
generateStimulusControllers
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=generate-stimulus.js.map
|
|
@@ -16,7 +16,8 @@ class StatefulPage extends Mountable {
|
|
|
16
16
|
this.wrapInForm(
|
|
17
17
|
state,
|
|
18
18
|
await original_render(ctx, state, inputs)
|
|
19
|
-
)
|
|
19
|
+
),
|
|
20
|
+
state
|
|
20
21
|
);
|
|
21
22
|
};
|
|
22
23
|
}
|
|
@@ -123,7 +124,7 @@ class StatefulPage extends Mountable {
|
|
|
123
124
|
options
|
|
124
125
|
);
|
|
125
126
|
} else if (target.indexOf(item) === -1) {
|
|
126
|
-
destination
|
|
127
|
+
destination[index] = item;
|
|
127
128
|
}
|
|
128
129
|
});
|
|
129
130
|
return destination;
|