@anaemia/core 0.0.1

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.
Files changed (59) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +3 -0
  3. package/dist/config.d.ts +63 -0
  4. package/dist/config.d.ts.map +1 -0
  5. package/dist/config.js +3 -0
  6. package/dist/index.d.ts +11 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +5 -0
  9. package/dist/plugins/index.d.ts +2 -0
  10. package/dist/plugins/index.d.ts.map +1 -0
  11. package/dist/plugins/index.js +1 -0
  12. package/dist/plugins/lightningcss.d.ts +5 -0
  13. package/dist/plugins/lightningcss.d.ts.map +1 -0
  14. package/dist/plugins/lightningcss.js +69 -0
  15. package/dist/runtime/context.browser.d.ts +4 -0
  16. package/dist/runtime/context.browser.d.ts.map +1 -0
  17. package/dist/runtime/context.browser.js +4 -0
  18. package/dist/runtime/context.d.ts +8 -0
  19. package/dist/runtime/context.d.ts.map +1 -0
  20. package/dist/runtime/context.js +25 -0
  21. package/dist/runtime/entry-client.d.ts +2 -0
  22. package/dist/runtime/entry-client.d.ts.map +1 -0
  23. package/dist/runtime/entry-client.jsx +19 -0
  24. package/dist/runtime/entry-server.d.ts +4 -0
  25. package/dist/runtime/entry-server.d.ts.map +1 -0
  26. package/dist/runtime/entry-server.jsx +346 -0
  27. package/dist/runtime/resources.d.ts +6 -0
  28. package/dist/runtime/resources.d.ts.map +1 -0
  29. package/dist/runtime/resources.js +36 -0
  30. package/dist/runtime/route-data.d.ts +15 -0
  31. package/dist/runtime/route-data.d.ts.map +1 -0
  32. package/dist/runtime/route-data.js +57 -0
  33. package/dist/runtime/route-request.d.ts +2 -0
  34. package/dist/runtime/route-request.d.ts.map +1 -0
  35. package/dist/runtime/route-request.js +11 -0
  36. package/dist/runtime/rpc-client.d.ts +6 -0
  37. package/dist/runtime/rpc-client.d.ts.map +1 -0
  38. package/dist/runtime/rpc-client.js +78 -0
  39. package/dist/types.d.ts +49 -0
  40. package/dist/types.d.ts.map +1 -0
  41. package/dist/types.js +1 -0
  42. package/package.json +61 -0
  43. package/src/config.ts +74 -0
  44. package/src/index.ts +13 -0
  45. package/src/plugins/index.ts +1 -0
  46. package/src/plugins/lightningcss.ts +82 -0
  47. package/src/runtime/context.browser.ts +5 -0
  48. package/src/runtime/context.ts +34 -0
  49. package/src/runtime/entry-client.tsx +34 -0
  50. package/src/runtime/entry-server.tsx +393 -0
  51. package/src/runtime/resources.ts +49 -0
  52. package/src/runtime/route-data.ts +93 -0
  53. package/src/runtime/route-request.ts +12 -0
  54. package/src/runtime/rpc-client.ts +87 -0
  55. package/src/runtime/webpack.d.ts +6 -0
  56. package/src/types.ts +32 -0
  57. package/test/integration/hmr.test.mjs +152 -0
  58. package/test/run-on-server.test.mjs +48 -0
  59. package/tsconfig.json +12 -0
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@anaemia/core",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js",
11
+ "default": "./dist/index.js"
12
+ },
13
+ "./config": {
14
+ "types": "./dist/config.d.ts",
15
+ "default": "./dist/config.js"
16
+ },
17
+ "./runtime/context": {
18
+ "types": "./dist/runtime/context.d.ts",
19
+ "import": "./dist/runtime/context.js",
20
+ "default": "./dist/runtime/context.js"
21
+ },
22
+ "./runtime/route-data": {
23
+ "types": "./dist/runtime/route-data.d.ts",
24
+ "import": "./dist/runtime/route-data.js",
25
+ "default": "./dist/runtime/route-data.js"
26
+ },
27
+ "./plugins": {
28
+ "types": "./dist/plugins/index.d.ts",
29
+ "import": "./dist/plugins/index.js"
30
+ },
31
+ "./package.json": "./package.json"
32
+ },
33
+ "dependencies": {
34
+ "@hono/node-server": "^2.0.4",
35
+ "@solidjs/router": "^0.16.1",
36
+ "hono": "^4.12.23"
37
+ },
38
+ "peerDependencies": {
39
+ "@rspack/core": "*",
40
+ "lightningcss": "^1.32.0",
41
+ "solid-js": "^1.9.13"
42
+ },
43
+ "peerDependenciesMeta": {
44
+ "@rspack/core": {
45
+ "optional": true
46
+ },
47
+ "lightningcss": {
48
+ "optional": true
49
+ }
50
+ },
51
+ "devDependencies": {
52
+ "@types/node": "^25.9.1",
53
+ "jiti": "^2.7.0",
54
+ "playwright": "^1.60.0"
55
+ },
56
+ "scripts": {
57
+ "build": "tsc",
58
+ "test": "pnpm run build && node --test test/*.test.mjs",
59
+ "test:integration": "pnpm run build && node --test test/integration/*.test.mjs"
60
+ }
61
+ }
package/src/config.ts ADDED
@@ -0,0 +1,74 @@
1
+ import { Hono } from "hono";
2
+ import type { Configuration } from "@rspack/core";
3
+
4
+ export interface AnaemiaPlugin {
5
+ /**
6
+ * unique identifier for the plugin.
7
+ */
8
+ name: string;
9
+
10
+ /**
11
+ * extend or modify the rspack config for the client bundle.
12
+ */
13
+ clientRspackConfig?: (config: Configuration) => Configuration;
14
+
15
+ /**
16
+ * extend or modify the rspack config for the server bundle.
17
+ */
18
+ serverRspackConfig?: (config: Configuration) => Configuration;
19
+
20
+ /**
21
+ * add additional babel plugins to the client transform pipeline.
22
+ */
23
+ babelPlugins?: {
24
+ client?: any[];
25
+ server?: any[];
26
+ };
27
+
28
+ /**
29
+ * hook into the Hono app instance to register additional routes or middleware.
30
+ */
31
+ configureServer?: (app: Hono) => void;
32
+
33
+ /**
34
+ * transform the final HTML string before it is sent to the client.
35
+ */
36
+ transformHtml?: (html: string) => string | Promise<string>;
37
+ }
38
+
39
+ export interface AnaemiaConfig {
40
+ port?: number;
41
+ assets?: {
42
+ publicPath?: string;
43
+ };
44
+ styles?: {
45
+ sass?: boolean;
46
+ modules?: boolean;
47
+ };
48
+ experimental?: {
49
+ outputModule?: boolean;
50
+ };
51
+
52
+ /**
53
+ * list of anaemia plugins to apply to the build and runtime.
54
+ */
55
+ plugins?: AnaemiaPlugin[];
56
+
57
+ /**
58
+ * inject global constants into the client and/or server bundles at build time.
59
+ * values must be JSON-serializable expressions — wrap strings in JSON.stringify.
60
+ * @example
61
+ * define: {
62
+ * client: { __APP_VERSION__: JSON.stringify("1.0.0") },
63
+ * server: { __DB_POOL_SIZE__: "10" }
64
+ * }
65
+ */
66
+ define?: {
67
+ client?: Record<string, string>;
68
+ server?: Record<string, string>;
69
+ };
70
+ }
71
+
72
+ export function defineConfig(config: AnaemiaConfig): AnaemiaConfig {
73
+ return config;
74
+ }
package/src/index.ts ADDED
@@ -0,0 +1,13 @@
1
+ export * from "./config.js";
2
+
3
+ export { runOnServer } from "./runtime/context.js";
4
+ export { RouteDataController, useRouteData } from "./runtime/route-data.js";
5
+ export { $$executeClientRpc } from "./runtime/rpc-client.js";
6
+ export { createServerResource } from "./runtime/resources.js";
7
+
8
+ export type ServerFunction<Args extends any[], Return> = ((...args: Args) => Promise<Return>) & {
9
+ id?: string;
10
+ urlId?: string;
11
+ };
12
+
13
+ export type { LoaderArgs, LoaderFunction, InferServerData, GuardContext, GuardResult, GuardFn } from "./types.js";
@@ -0,0 +1 @@
1
+ export { anaemiaLightningCssPlugin } from "./lightningcss.js";
@@ -0,0 +1,82 @@
1
+ import { createRequire } from "node:module";
2
+ import type { AnaemiaPlugin } from "../config.js";
3
+
4
+ export function anaemiaLightningCssPlugin(options: { browserslist?: string[] } = {}): AnaemiaPlugin {
5
+ const targets = options.browserslist ?? ["defaults", "not IE 11"];
6
+
7
+ const localRequire = createRequire(import.meta.url);
8
+ let rspackModule: any;
9
+
10
+ try {
11
+ rspackModule = localRequire("@rspack/core");
12
+ } catch (err) {
13
+ throw new Error(
14
+ "[anaemia] The LightningCSS plugin requires '@rspack/core' to be available in the execution workspace."
15
+ );
16
+ }
17
+
18
+ return {
19
+ name: "anaemia-lightningcss-plugin",
20
+
21
+ clientRspackConfig(config) {
22
+ const isProd = process.env.NODE_ENV === "production";
23
+
24
+ if (config.module?.rules) {
25
+ config.module.rules.forEach((rule) => {
26
+ if (rule && typeof rule === "object" && rule.test && rule.test.toString().includes("ss")) {
27
+ const currentUse = Array.isArray(rule.use) ? rule.use : [];
28
+
29
+ rule.use = [
30
+ ...currentUse,
31
+ {
32
+ loader: "builtin:lightningcss-loader",
33
+ options: {
34
+ targets,
35
+ modules: rule.type === "css/auto",
36
+ },
37
+ },
38
+ ];
39
+ }
40
+ });
41
+ }
42
+
43
+ if (isProd) {
44
+ config.optimization = {
45
+ ...config.optimization,
46
+ minimize: true,
47
+ minimizer: [
48
+ ...(config.optimization?.minimizer ?? []),
49
+ // Native Rust CSS minification engine
50
+ new rspackModule.LightningCssMinimizerRspackPlugin({
51
+ minimizerOptions: { targets },
52
+ }),
53
+ ],
54
+ };
55
+ }
56
+
57
+ return config;
58
+ },
59
+
60
+ serverRspackConfig(config) {
61
+ if (config.module?.rules) {
62
+ config.module.rules.forEach((rule) => {
63
+ if (rule && typeof rule === "object" && rule.test && rule.test.toString().includes("ss")) {
64
+ const currentUse = Array.isArray(rule.use) ? rule.use : [];
65
+
66
+ rule.use = [
67
+ ...currentUse,
68
+ {
69
+ loader: "builtin:lightningcss-loader",
70
+ options: {
71
+ targets,
72
+ modules: rule.type === "css/auto",
73
+ },
74
+ },
75
+ ];
76
+ }
77
+ });
78
+ }
79
+ return config;
80
+ },
81
+ };
82
+ }
@@ -0,0 +1,5 @@
1
+ export const ssrStorage = null as any;
2
+ export const serverFunctionsRegistry = new Map<string, Function>();
3
+
4
+ // runOnServer calls are compiled away by babel-transform-server
5
+ export const runOnServer = null as any;
@@ -0,0 +1,34 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+
3
+ export const serverFunctionsRegistry = new Map<string, Function>();
4
+ export const ssrStorage = new AsyncLocalStorage<Map<string, any>>();
5
+
6
+ (globalThis as any).__ANAEMIA_SERVER_STORAGE__ = ssrStorage;
7
+
8
+ export function runOnServer(backendFn: Function, id?: string) {
9
+ const hashId = id || "";
10
+
11
+ const rpcProxy = async function (...args: any[]) {
12
+ const result = await backendFn(...args);
13
+
14
+ const store = ssrStorage.getStore();
15
+ if (store && hashId) {
16
+ if (!store.has("__SERVER_FUNCTION_DATA__")) {
17
+ store.set("__SERVER_FUNCTION_DATA__", {});
18
+ }
19
+
20
+ const functionCache = store.get("__SERVER_FUNCTION_DATA__");
21
+ if (!functionCache[hashId]) {
22
+ functionCache[hashId] = {};
23
+ }
24
+
25
+ const paramKey = JSON.stringify(args);
26
+ functionCache[hashId][paramKey] = result;
27
+ }
28
+
29
+ return result;
30
+ };
31
+
32
+ rpcProxy.id = hashId;
33
+ return rpcProxy;
34
+ }
@@ -0,0 +1,34 @@
1
+ import { hydrate, render } from "solid-js/web";
2
+ import { Router } from "@solidjs/router";
3
+
4
+ // @ts-ignore
5
+ import App, { preloadActiveClientRoute } from "anaemia-user-app";
6
+
7
+ const mountTarget = document.querySelector(
8
+ "[anaemia-entry]"
9
+ ) as HTMLElement | null;
10
+
11
+ if (!mountTarget) {
12
+ throw new Error("[anaemia] missing mount target");
13
+ }
14
+
15
+ const root = mountTarget;
16
+
17
+ async function start() {
18
+ await preloadActiveClientRoute(window.location.pathname);
19
+
20
+ const mount = root.hasChildNodes()
21
+ ? hydrate
22
+ : render;
23
+
24
+ mount(
25
+ () => (
26
+ <Router>
27
+ <App />
28
+ </Router>
29
+ ),
30
+ root
31
+ );
32
+ }
33
+
34
+ start();