@primate/go 0.1.6 → 0.2.0

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,180 +0,0 @@
1
- import route_error from "#error/route-error";
2
- import pkgname from "#pkgname";
3
- import verbs from "@primate/core/http/verbs";
4
- import log from "@primate/core/log";
5
- import dim from "@rcompat/cli/color/dim";
6
- import { user } from "@rcompat/env";
7
- import file from "@rcompat/fs/file";
8
- import runtime from "@rcompat/runtime";
9
- import execute from "@rcompat/stdio/execute";
10
- import which from "@rcompat/stdio/which";
11
- import upperfirst from "@rcompat/string/upperfirst";
12
-
13
- const command = await which("go");
14
- const env = {
15
- GOOS: "js",
16
- GOARCH: "wasm",
17
- GOCACHE: (await execute(`${command} env GOCACHE`)).replaceAll("\n", ""),
18
- };
19
-
20
- const run = (wasm, go, includes = "request.go") =>
21
- `${command} build -o ${wasm} ${go} ${includes}`;
22
- const verbs_string = verbs.map(upperfirst).join("|");
23
- const routes_re = new RegExp(`func (?<route>${verbs_string})`, "gu");
24
- const add_setter = route => `
25
- var cb${route} js.Func;
26
- cb${route} = js.FuncOf(func(this js.Value, args[]js.Value) any {
27
- cb${route}.Release();
28
- return make_request(${route}, args[0]);
29
- });
30
- js.Global().Set("${route}", cb${route});
31
- `;
32
-
33
- const make_route = route =>
34
- ` ${route.toLowerCase()}(request) {
35
- const go = new globalThis.Go();
36
- return WebAssembly.instantiate(route, {...go.importObject}).then(result => {
37
- go.run(result.instance);
38
- return to_response(globalThis.${route}(to_request(request)));
39
- });
40
- }`;
41
-
42
- const js_wrapper = (path, routes) => `
43
- import env from "@primate/go/env";
44
- import to_request from "@primate/go/to-request";
45
- import to_response from "@primate/go/to-response";
46
- ${
47
- runtime === "bun" ? `
48
- import route_path from "${path}" with { type: "file" };
49
- const route = await Bun.file(route_path).arrayBuffer();
50
- ` : `
51
- import file from "primate/runtime/file";
52
- const route = new Uint8Array(await file(import.meta.url+"/../${path}")
53
- .arrayBuffer());
54
- `
55
- }
56
- env();
57
-
58
- export default {
59
- ${routes.map(route => make_route(route)).join(",\n")}
60
- };`;
61
-
62
- const go_wrapper = (code, routes) =>
63
- `// {{{ wrapper prefix
64
- package main
65
- import "syscall/js"
66
- // }}} end
67
- ${code}
68
- // {{{ wrapper postfix
69
- func main() {
70
- ${routes.map(route => add_setter(route)).join("\n ")}
71
- select{};
72
- }
73
- // }}} end`;
74
-
75
- const get_routes = code => [...code.matchAll(routes_re)]
76
- .map(({ groups: { route } }) => route);
77
-
78
- const type_map = {
79
- boolean: { transfer: "Bool", type: "bool" },
80
- i8: { transfer: "Int", type: "int8" },
81
- i16: { transfer: "Int", type: "int16" },
82
- i32: { transfer: "Int", type: "int32" },
83
- i64: { transfer: "Int", type: "int64" },
84
- f32: { transfer: "Float", type: "float32" },
85
- f64: { transfer: "Float", type: "float64" },
86
- u8: { transfer: "Int", type: "uint8" },
87
- u16: { transfer: "Int", type: "uint16" },
88
- u32: { transfer: "Int", type: "uint32", nullval: "0" },
89
- u64: { transfer: "Int", type: "uint64" },
90
- string: { transfer: "String", type: "string" },
91
- uuid: { transfer: "String", type: "string" },
92
- };
93
- const error_default = {
94
- Bool: false,
95
- Int: 0,
96
- Float: 0,
97
- String: "\"\"",
98
- };
99
- const root = file(import.meta.url).up(1);
100
-
101
- const create_meta_files = async (directory, app) => {
102
- const meta = {
103
- mod: "go.mod",
104
- sum: "go.sum",
105
- request: "request.go",
106
- session: "session.go",
107
- };
108
- const has_session = app.modules.names.includes("@primate/session");
109
-
110
- if (!await directory.join(meta.mod).exists()) {
111
- const request_struct_items = [];
112
- const request_make_items = [];
113
-
114
- if (has_session) {
115
- request_struct_items.push(
116
- "Session Session",
117
- );
118
- request_make_items.push(
119
- "make_session(request),",
120
- );
121
- }
122
-
123
- const request_struct = request_struct_items.join("\n");
124
- const request_make = request_make_items.join("\n");
125
-
126
- // copy go.mod file
127
- await directory.join(meta.mod).write(await root.join(meta.mod).text());
128
- // copy go.sum file
129
- await directory.join(meta.sum).write(await root.join(meta.sum).text());
130
-
131
- // copy transformed request.go file
132
- await directory.join(meta.request).write((await root.join(meta.request)
133
- .text())
134
- .replace("%%REQUEST_STRUCT%%", _ => request_struct)
135
- .replace("%%REQUEST_MAKE%%", _ => request_make),
136
- );
137
-
138
- if (has_session) {
139
- // copy session.go file
140
- directory.join(meta.session).write(await root.join(meta.session).text());
141
- }
142
- }
143
-
144
- return ["request.go"]
145
- .concat(has_session ? ["session.go"] : [])
146
- ;
147
- };
148
-
149
- export default ({ extension }) => (app, next) => {
150
- app.bind(extension, async (directory, file) => {
151
- const path = directory.join(file);
152
- const base = path.directory;
153
- const go = path.base.concat(".go");
154
- const wasm = path.base.concat(".wasm");
155
- const js = path.base.concat(".js");
156
-
157
- // create meta files
158
- const includes = await create_meta_files(base, app);
159
-
160
- const code = await path.text();
161
- const routes = get_routes(code);
162
- // write .go file
163
- await path.write(go_wrapper(code, routes));
164
- // write .js wrapper
165
- const wasm_route_path = `./${file.name.slice(0, -extension.length)}.wasm`;
166
- await base.join(js).write(js_wrapper(wasm_route_path, routes));
167
-
168
- try {
169
- log.info(`compiling ${dim(file)} to WebAssembly`, { module: pkgname });
170
- const cwd = `${base}`;
171
- // compile .go to .wasm
172
- await execute(run(wasm, go, includes.join(" ")),
173
- { cwd, env: { HOME: user.HOME, ...env } });
174
- } catch (error) {
175
- route_error(file, error);
176
- }
177
- });
178
-
179
- return next(app);
180
- };
@@ -1,11 +0,0 @@
1
- import pkgname from "#pkgname";
2
- import log from "@primate/core/log";
3
- import file from "@rcompat/fs/file";
4
-
5
- export default (...params) => log.error({
6
- params,
7
- name: file(import.meta.url).base,
8
- module: pkgname,
9
- message: "error in Go route {0}",
10
- fix: "fix route error:\n{1}",
11
- });
@@ -1 +0,0 @@
1
- export default ".go";
@@ -1,5 +0,0 @@
1
- module primate-binding
2
-
3
- go 1.21
4
-
5
- require github.com/primatejs/go/primate v0.0.0-20240512124018-39bdcae05e1c // indirect
@@ -1,2 +0,0 @@
1
- github.com/primatejs/go/primate v0.0.0-20240512124018-39bdcae05e1c h1:JK/EVNq60uV83eFATziKvZW42+fuJnQ0RHIPwcWXTwI=
2
- github.com/primatejs/go/primate v0.0.0-20240512124018-39bdcae05e1c/go.mod h1:56jgK3iIMJtYGYqlQVvHi5lfSfPQ3Yrex0/6Jtpq4X8=
@@ -1 +0,0 @@
1
- export default "@primate/go";
@@ -1,117 +0,0 @@
1
- package main
2
-
3
- import "syscall/js"
4
- import "encoding/json"
5
-
6
- type t_request func(Request) any
7
- type t_response func(js.Value, []js.Value) any
8
- type Object map[string]any
9
- type Array []any
10
-
11
- type Dispatcher struct {
12
- Get func(string) any
13
- Json func() map[string]any
14
- }
15
-
16
- type URL struct {
17
- Href string
18
- Origin string
19
- Protocol string
20
- Username string
21
- Password string
22
- Host string
23
- Hostname string
24
- Port string
25
- Pathname string
26
- Search string
27
- SearchParams map[string]any
28
- Hash string
29
- }
30
-
31
- type Request struct {
32
- Url URL
33
- Body map[string]any
34
- Path Dispatcher
35
- Query Dispatcher
36
- Cookies Dispatcher
37
- Headers Dispatcher
38
- %%REQUEST_STRUCT%%
39
- }
40
-
41
- func make_url(request js.Value) URL {
42
- url := request.Get("url");
43
- search_params := make(map[string]any);
44
- json.Unmarshal([]byte(request.Get("search_params").String()), &search_params);
45
-
46
- return URL{
47
- url.Get("href").String(),
48
- url.Get("origin").String(),
49
- url.Get("protocol").String(),
50
- url.Get("username").String(),
51
- url.Get("password").String(),
52
- url.Get("host").String(),
53
- url.Get("hostname").String(),
54
- url.Get("port").String(),
55
- url.Get("pathname").String(),
56
- url.Get("search").String(),
57
- search_params,
58
- url.Get("hash").String(),
59
- };
60
- }
61
-
62
- func make_dispatcher(key string, request js.Value) Dispatcher {
63
- properties := make(map[string]any);
64
- value := request.Get(key)
65
- json.Unmarshal([]byte(value.Get("stringified").String()), &properties);
66
-
67
- return Dispatcher{
68
- // Get
69
- func(property string) any {
70
- switch properties[property].(type) {
71
- case string:
72
- return properties[property].(string);
73
- default:
74
- return nil;
75
- }
76
- },
77
- // Json
78
- func() map[string]any {
79
- return properties;
80
- },
81
- };
82
- }
83
-
84
- func make_request(route t_request, request js.Value) any {
85
- body := make(map[string]any);
86
- json.Unmarshal([]byte(request.Get("body").String()), &body);
87
-
88
- go_request := Request{
89
- make_url(request),
90
- body,
91
- make_dispatcher("path", request),
92
- make_dispatcher("query", request),
93
- make_dispatcher("cookies", request),
94
- make_dispatcher("headers", request),
95
- %%REQUEST_MAKE%%
96
- };
97
-
98
- response := route(go_request);
99
- switch response.(type) {
100
- case js.Func:
101
- return response;
102
- default:
103
- marshalled, _ := json.Marshal(response);
104
- return string(marshalled);
105
- }
106
- }
107
-
108
- func make_empty(route func() any) any {
109
- response := route();
110
- switch response.(type) {
111
- case js.Func:
112
- return response;
113
- default:
114
- marshalled, _ := json.Marshal(response);
115
- return string(marshalled);
116
- }
117
- }
@@ -1,70 +0,0 @@
1
- package main
2
-
3
- import "syscall/js"
4
- import "encoding/json"
5
- import "errors"
6
-
7
- type Session struct {
8
- Exists func() bool
9
- Get func(string) any
10
- Json func() map[string]any
11
- Set func(string, any) error
12
- Create func(map[string]any)
13
- Destroy func()
14
- }
15
-
16
- func make_session(request js.Value) Session {
17
- session := request.Get("session");
18
- properties := make(map[string]any);
19
- json.Unmarshal([]byte(session.Get("stringified").String()), &properties);
20
-
21
- return Session{
22
- // Exists
23
- func() bool {
24
- return session.Get("exists").Invoke().Bool();
25
- },
26
- // Get
27
- func(key string) any {
28
- invoked := session.Get("get").Invoke(key);
29
- jstype := invoked.Type()
30
- switch jstype {
31
- case 0:
32
- case 1:
33
- return nil;
34
- case 2:
35
- return invoked.Bool();
36
- case 3:
37
- return invoked.Float();
38
- case 4:
39
- return invoked.String();
40
- // currently unsupported
41
- case 5:
42
- case 6:
43
- case 7:
44
- return nil;
45
- }
46
-
47
- return nil;
48
- },
49
- // Json
50
- func() map[string]any {
51
- return properties;
52
- },
53
- // Set
54
- func(key string, value any) error {
55
- r := session.Get("set").Invoke(key, value);
56
- if (r.Type() == 7) {
57
- return errors.New(r.Invoke().String());
58
- }
59
- return nil
60
- },
61
- // Create
62
- func(data map[string]any) {
63
- session.Get("create").Invoke(data);
64
- },
65
- // Destroy
66
- func() {
67
- session.Get("destroy").Invoke();
68
- },
69
- };
70
- }
package/src/runtime.js DELETED
@@ -1,3 +0,0 @@
1
- import pkgname from "#pkgname";
2
-
3
- export default () => ({ name: pkgname });
package/src/to-request.js DELETED
@@ -1,54 +0,0 @@
1
- import exclude from "@rcompat/object/exclude";
2
- import stringify from "@rcompat/object/stringify";
3
- import valmap from "@rcompat/object/valmap";
4
-
5
- const to_search_params = url =>
6
- stringify(Object.fromEntries(url.searchParams.entries()));
7
- const dispatchers = ["path", "query", "cookies", "headers"];
8
-
9
- const to_dispatcher = dispatcher =>
10
- valmap(exclude(dispatcher, ["get", "raw"]), getter => {
11
- try {
12
- return getter();
13
- } catch ({ message }) {
14
- return () => message;
15
- }
16
- });
17
-
18
- const make_session = session => {
19
- if (session === undefined) {
20
- return {};
21
- }
22
-
23
- return {
24
- session: {
25
- ...session,
26
- set: (key, value) => {
27
- try {
28
- return session.set(key, value);
29
- } catch ({ message }) {
30
- return () => message;
31
- }
32
- },
33
- get: session.get,
34
- stringified: session.toString(),
35
- },
36
- };
37
- };
38
-
39
- export default request => {
40
- dispatchers.map(property => to_dispatcher(request[property]));
41
-
42
- return {
43
- url: request.url,
44
- search_params: to_search_params(request.url),
45
- body: JSON.stringify(request.body),
46
- ...Object.fromEntries(dispatchers.map(property => [
47
- property, {
48
- stringified: request[property].toString(),
49
- ...to_dispatcher(request[property]),
50
- },
51
- ])),
52
- ...make_session(request.session),
53
- };
54
- };
@@ -1,23 +0,0 @@
1
- import error from "@primate/core/handler/error";
2
- import redirect from "@primate/core/handler/redirect";
3
- import view from "@primate/core/handler/view";
4
-
5
- const handlers = {
6
- view({ component, props = "{}", options = "{}" }) {
7
- return view(component, JSON.parse(props), JSON.parse(options));
8
- },
9
- redirect({ location, options = "{}" }) {
10
- return redirect(location, JSON.parse(options));
11
- },
12
- };
13
-
14
- const handle_function = response => {
15
- const { handler, ...args } = response;
16
- return handlers[handler]?.(args) ?? error();
17
- };
18
-
19
- const handle_other = response => JSON.parse(response);
20
-
21
- export default response => typeof response === "function"
22
- ? handle_function(response())
23
- : handle_other(response);