-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
binding: native support for typescript
- Loading branch information
Showing
23 changed files
with
260 additions
and
57 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { dependencies, name } from "@primate/binding/python/common"; | ||
import depend from "@primate/core/depend"; | ||
|
||
const routes_re = /def (?<route>get|post|put|delete)/gu; | ||
const get_routes = code => [...code.matchAll(routes_re)] | ||
.map(({ groups: { route } }) => route); | ||
|
||
const make_route = route => `async ${route.toLowerCase()}(request) { | ||
const ${route}_fn = pyodide.globals.get("${route}"); | ||
return to_request(await ${route}_fn(to_request(pyodide.toPy, request))); | ||
}`; | ||
|
||
const make_package = pkg => `await pyodide.loadPackage("${pkg}", { | ||
messageCallback: _ => _, | ||
});\n`; | ||
|
||
const js_wrapper = async (path, routes, packages) => ` | ||
import { File } from "rcompat/fs"; | ||
import to_request from "@primate/binding/python/to-request"; | ||
import to_response from "@primate/binding/python/to-response"; | ||
import wrap from "@primate/binding/python/wrap"; | ||
import { loadPyodide as load } from "pyodide"; | ||
const pyodide = await load({ indexURL: "./node_modules/pyodide" }); | ||
const file = await File.text(${JSON.stringify(path)}); | ||
${packages.map(make_package)} | ||
pyodide.runPython(wrap(file)); | ||
export default { | ||
${routes.map(route => make_route(route)).join(",\n")} | ||
}; | ||
`; | ||
|
||
export default ({ extension, packages }) => async (app, next) => { | ||
await depend(dependencies, `primate:${name}`); | ||
|
||
app.bind(extension, async (directory, file) => { | ||
const path = directory.join(file); | ||
const base = path.directory; | ||
const js = path.base.concat(".js"); | ||
const code = await path.text(); | ||
const routes = get_routes(code); | ||
// write .js wrapper | ||
await base.join(js) | ||
.write(await js_wrapper(`${path}`, routes, packages)); | ||
}); | ||
|
||
return next(app); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export const name = "python"; | ||
|
||
export const default_extension = ".py"; | ||
|
||
export const dependencies = ["pyodide"]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { default_extension, name } from "@primate/binding/python/common"; | ||
import build from "./build.js"; | ||
|
||
export default ({ extension = default_extension, packages = [] } = {}) => ({ | ||
name: `primate:${name}`, | ||
build: build({ name, extension, packages }), | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import { unwrap, unwrap_async } from "./unwrap.js"; | ||
|
||
const dispatchers = ["path", "query", "headers", "cookies"]; | ||
|
||
const wrap_dispatchers = (toPy, request) => | ||
Object.fromEntries(dispatchers.map(dispatcher => | ||
[dispatcher, { | ||
...request[dispatcher], | ||
json() { | ||
return toPy(request[dispatcher].json()); | ||
}, | ||
}])); | ||
|
||
const wrap_store = (toPy, store) => { | ||
return { | ||
...store, | ||
async validate(input) { | ||
return toPy(await store.validate(unwrap_async(input))); | ||
}, | ||
async get(value) { | ||
return toPy(await store.get(unwrap_async(value))); | ||
}, | ||
async count(criteria) { | ||
return store.count(unwrap_async(criteria)); | ||
}, | ||
async find(criteria) { | ||
return toPy(await store.find(unwrap_async(criteria))); | ||
}, | ||
async exists(criteria) { | ||
return store.exists(unwrap_async(criteria)); | ||
}, | ||
async insert(document) { | ||
return toPy(await store.insert(unwrap_async(document))); | ||
}, | ||
async update(criteria, document) { | ||
const ua = unwrap_async; | ||
return toPy(await store.update(ua(criteria), ua(document))); | ||
}, | ||
async save(document) { | ||
return toPy(await store.save(unwrap_async(document))); | ||
}, | ||
async delete(criteria) { | ||
return store.delete(unwrap_async(criteria)); | ||
}, | ||
schema: { | ||
async create(description) { | ||
return store.schema.create(unwrap_async(description)); | ||
}, | ||
async delete() { | ||
return store.schema.delete(); | ||
}, | ||
}, | ||
}; | ||
}; | ||
|
||
const is_store = value => value.connection !== undefined; | ||
const wrap_stores = (toPy, object) => Object.entries(object) | ||
.reduce((reduced, [key, value]) => ({ | ||
...reduced, | ||
[key]: is_store(value) ? wrap_store(toPy, value) : wrap_stores(toPy, value), | ||
}), {}); | ||
|
||
const wrap_session = (toPy, { session }) => ({ | ||
...session, | ||
create(data) { | ||
session.create(unwrap(data)); | ||
}, | ||
json() { | ||
return toPy(session.json()); | ||
}, | ||
}); | ||
|
||
export default (toPy, request) => ({ | ||
...request, | ||
...wrap_dispatchers(toPy, request), | ||
session: wrap_session(toPy, request), | ||
store: wrap_stores(toPy, request.store), | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import error from "@primate/core/handlers/error"; | ||
import redirect from "@primate/core/handlers/redirect"; | ||
import view from "@primate/core/handlers/view"; | ||
|
||
import { unwrap } from "./unwrap.js"; | ||
|
||
const handlers = { | ||
view({ name, props = {}, options = {} }) { | ||
return view(name, props, options); | ||
}, | ||
redirect({ location, options }) { | ||
return redirect(location, options); | ||
}, | ||
error({ body, options }) { | ||
return error(body, options); | ||
}, | ||
}; | ||
|
||
const handle_handler = response => { | ||
const { __handler__ : handler, ...args } = response; | ||
return handlers[handler]?.(args) ?? error(); | ||
}; | ||
|
||
const handle_other = response => response; | ||
|
||
export default raw_response => { | ||
const response = unwrap(raw_response); | ||
return response.__handler__ === undefined | ||
? handle_other(response) | ||
: handle_handler(response); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import { name } from "@primate/binding/python/common"; | ||
|
||
export default () => ({ name: `primate:${name}` }); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
const dict_converter = value => Object.fromEntries(value); | ||
|
||
const normalize = response => | ||
response instanceof Map ? Object.fromEntries(response.entries()) : response; | ||
const qualify = (response, destroy = true) => { | ||
if (response?.toJs !== undefined) { | ||
const py_proxy = response; | ||
const converted = py_proxy.toJs({ dict_converter }); | ||
destroy && py_proxy.destroy(); | ||
return converted; | ||
} | ||
return response; | ||
}; | ||
|
||
export const unwrap = response => normalize(qualify(response)); | ||
|
||
export const unwrap_async = response => normalize(qualify(response, false)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { File } from "rcompat/fs"; | ||
|
||
const wrap = await new File(import.meta.url).directory.join("wrap.py").text(); | ||
|
||
export default code => `${wrap}\n${code}`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
class Primate(): | ||
@staticmethod | ||
def view(name, props = None, options = None): | ||
return { | ||
"__handler__": "view", | ||
"name": name, | ||
"props": props, | ||
"options": options, | ||
} | ||
@staticmethod | ||
def redirect(location, options = None): | ||
return { | ||
"__handler__": "redirect", | ||
"location": location, | ||
"options": options, | ||
} | ||
@staticmethod | ||
def error(body, options = None): | ||
return { | ||
"__handler__": "error", | ||
"body": body, | ||
"options": options, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { name } from "@primate/binding/typescript/common"; | ||
import { dim } from "rcompat/colors"; | ||
import compile from "./compile.js"; | ||
|
||
const module = `@primate:${name}`; | ||
|
||
export default ({ extension }) => (app, next) => { | ||
app.bind(extension, async (directory, file) => { | ||
app.log.info(`compiling ${dim(file)} to JavaScript`, { module }); | ||
|
||
const path = directory.join(file); | ||
const base = path.directory; | ||
const js = path.base.concat(".js"); | ||
await base.join(js).write(await compile(await path.text())); | ||
}); | ||
|
||
return next(app); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export const name = "typescript"; | ||
|
||
export const default_extension = ".ts"; |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { default_extension, name } from "@primate/binding/typescript/common"; | ||
import build from "./build.js"; | ||
|
||
export default ({ extension = default_extension } = {}) => ({ | ||
name: `@primate:${name}`, | ||
build: build({ extension }), | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import { name } from "@primate/binding/typescript/common"; | ||
|
||
export default () => ({ name: `@primate:${name}` }); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters