@primate/solid 0.4.3 → 0.5.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.
Files changed (72) hide show
  1. package/lib/private/Default.d.ts +13 -0
  2. package/lib/private/Default.js +30 -0
  3. package/lib/private/Head/ClientChild.d.ts +3 -0
  4. package/lib/private/Head/ClientChild.js +2 -0
  5. package/lib/private/Head/ServerChild.d.ts +8 -0
  6. package/lib/private/Head/ServerChild.js +2 -0
  7. package/lib/private/Head/browser.d.ts +9 -0
  8. package/lib/private/Head/browser.js +36 -0
  9. package/lib/private/Head/default.d.ts +9 -0
  10. package/lib/private/Head/default.js +44 -0
  11. package/lib/private/Head.d.ts +8 -0
  12. package/lib/private/Head.js +8 -0
  13. package/lib/private/Runtime.d.ts +11 -0
  14. package/lib/private/Runtime.js +22 -0
  15. package/lib/private/client/Validated.d.ts +10 -0
  16. package/lib/private/client/Validated.js +2 -0
  17. package/lib/private/client/index.d.ts +11 -0
  18. package/lib/private/client/index.js +31 -0
  19. package/lib/private/client/validate.d.ts +25 -0
  20. package/lib/private/client/validate.js +29 -0
  21. package/lib/private/context/app.d.ts +13 -0
  22. package/lib/private/context/app.js +10 -0
  23. package/lib/private/context/head.d.ts +3 -0
  24. package/{src → lib}/private/context/head.js +1 -1
  25. package/lib/private/create-root.d.ts +3 -0
  26. package/lib/private/create-root.js +40 -0
  27. package/lib/private/i18n/Bridge.browser.d.ts +8 -0
  28. package/lib/private/i18n/Bridge.browser.js +25 -0
  29. package/lib/private/i18n/Bridge.default.d.ts +8 -0
  30. package/lib/private/i18n/Bridge.default.js +12 -0
  31. package/lib/public/Head.d.ts +2 -0
  32. package/lib/public/Head.js +2 -0
  33. package/lib/public/Validated.d.ts +2 -0
  34. package/lib/public/Validated.js +2 -0
  35. package/lib/public/browser.d.ts +2 -0
  36. package/lib/public/browser.js +2 -0
  37. package/lib/public/context/app.d.ts +2 -0
  38. package/{src → lib}/public/context/app.js +1 -0
  39. package/lib/public/context/head.d.ts +2 -0
  40. package/{src → lib}/public/context/head.js +1 -0
  41. package/lib/public/default.d.ts +4 -0
  42. package/lib/public/default.js +3 -0
  43. package/lib/public/i18n/Bridge/browser.d.ts +2 -0
  44. package/lib/public/i18n/Bridge/browser.js +2 -0
  45. package/lib/public/i18n/Bridge/default.d.ts +2 -0
  46. package/lib/public/i18n/Bridge/default.js +2 -0
  47. package/lib/public/runtime.d.ts +4 -0
  48. package/lib/public/runtime.js +3 -0
  49. package/lib/public/validate.d.ts +2 -0
  50. package/lib/public/validate.js +2 -0
  51. package/package.json +38 -48
  52. package/src/private/build/client.js +0 -7
  53. package/src/private/build/index.js +0 -14
  54. package/src/private/build/publish.js +0 -26
  55. package/src/private/build/server.js +0 -8
  56. package/src/private/client/create-root.js +0 -33
  57. package/src/private/client/expose.js +0 -7
  58. package/src/private/client/index.js +0 -25
  59. package/src/private/client/spa.js +0 -14
  60. package/src/private/context/app.js +0 -3
  61. package/src/private/extension.js +0 -1
  62. package/src/private/i18n/index.js +0 -10
  63. package/src/private/i18n/locale.js +0 -37
  64. package/src/private/name.js +0 -1
  65. package/src/private/pkgname.js +0 -1
  66. package/src/private/serve/index.js +0 -16
  67. package/src/private/serve/render.js +0 -17
  68. package/src/public/default.js +0 -14
  69. package/src/public/head.js +0 -92
  70. package/src/public/i18n.js +0 -1
  71. package/src/public/locale.js +0 -1
  72. package/src/public/runtime.js +0 -12
@@ -0,0 +1,13 @@
1
+ import Runtime from "#Runtime";
2
+ export default class Default extends Runtime {
3
+ root: {
4
+ create: (length: number, i18n_active: boolean) => string;
5
+ };
6
+ compile: {
7
+ client: (text: string) => {
8
+ js: string;
9
+ };
10
+ server: (text: string) => string;
11
+ };
12
+ }
13
+ //# sourceMappingURL=Default.d.ts.map
@@ -0,0 +1,30 @@
1
+ import create_root from "#create-root";
2
+ import Runtime from "#Runtime";
3
+ import { transformSync } from "@babel/core";
4
+ import transform from "@rcompat/build/sync/transform";
5
+ // @ts-expect-error no declaration file
6
+ import solid from "babel-preset-solid";
7
+ function compile(text, presets) {
8
+ return transformSync(transform(text, {
9
+ format: "esm",
10
+ jsx: "preserve",
11
+ loader: "tsx",
12
+ target: "esnext",
13
+ }).code, { presets })?.code ?? "";
14
+ }
15
+ export default class Default extends Runtime {
16
+ root = {
17
+ create: create_root,
18
+ };
19
+ compile = {
20
+ client: (text) => {
21
+ const presets = [[solid, { generate: "dom", hydratable: true }]];
22
+ return { js: compile(text, presets) };
23
+ },
24
+ server: (text) => {
25
+ const presets = [[solid, { generate: "ssr", hydratable: true }]];
26
+ return compile(text, presets);
27
+ },
28
+ };
29
+ }
30
+ //# sourceMappingURL=Default.js.map
@@ -0,0 +1,3 @@
1
+ type ClientChild = HTMLElement;
2
+ export type { ClientChild as default };
3
+ //# sourceMappingURL=ClientChild.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ClientChild.js.map
@@ -0,0 +1,8 @@
1
+ import type Dict from "@rcompat/type/Dict";
2
+ type Child = {
3
+ props: Dict;
4
+ t: string;
5
+ tagName: string;
6
+ };
7
+ export type { Child as default };
8
+ //# sourceMappingURL=ServerChild.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ServerChild.js.map
@@ -0,0 +1,9 @@
1
+ import type Child from "#Head/ClientChild";
2
+ declare const Head: {
3
+ (props: {
4
+ children: Child[];
5
+ }): null;
6
+ clear(data_value?: string): void;
7
+ };
8
+ export default Head;
9
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1,36 @@
1
+ import { onCleanup, onMount } from "solid-js";
2
+ const data_attribute = "data-sh";
3
+ const data_ssr = "ssr";
4
+ const render = (children, id) => {
5
+ // DOM elements
6
+ const titles = children.filter(({ tagName }) => tagName === "TITLE");
7
+ const others = children.filter(({ tagName }) => tagName !== "TITLE");
8
+ titles.forEach(title => {
9
+ globalThis.document.title = title.innerText;
10
+ });
11
+ others.forEach(other => {
12
+ other.dataset.sh = id;
13
+ globalThis.document.head.prepend(other);
14
+ });
15
+ };
16
+ const clear = (data_value) => {
17
+ const selector = `[${data_attribute}="${data_value}"]`;
18
+ globalThis.document.querySelectorAll(selector).forEach(element => {
19
+ element.remove();
20
+ });
21
+ };
22
+ const Head = function Head(props) {
23
+ let id;
24
+ onMount(() => {
25
+ id = crypto.randomUUID();
26
+ render(props.children, id);
27
+ });
28
+ onCleanup(() => {
29
+ // remove managed tags
30
+ clear(id);
31
+ });
32
+ return null;
33
+ };
34
+ Head.clear = (data_value = data_ssr) => clear(data_value);
35
+ export default Head;
36
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1,9 @@
1
+ import type Child from "#Head/ServerChild";
2
+ declare const Head: {
3
+ (props: {
4
+ children: Child[];
5
+ }): null;
6
+ clear(data_value?: string): void;
7
+ };
8
+ export default Head;
9
+ //# sourceMappingURL=default.d.ts.map
@@ -0,0 +1,44 @@
1
+ import HeadContext from "#context/head";
2
+ import { useContext } from "solid-js";
3
+ const data_attribute = "data-sh";
4
+ const data_ssr = "ssr";
5
+ const allowed = ["title", "meta", "style", "meta", "link", "script", "base"];
6
+ const make_tag = (tag, id) => {
7
+ const parts = tag.split(" ");
8
+ return [
9
+ parts[0],
10
+ `${data_attribute}="${id}"`,
11
+ ...parts.slice(1),
12
+ ].join(" ");
13
+ };
14
+ const get_tag = (child) => child.match(/^<(?<tag>[a-z]*) .*$/u)?.groups?.tag ?? "";
15
+ const render = (children, id) => {
16
+ const tags = children.map(({ t: tag }) => tag);
17
+ const all_good = tags.every(tag => allowed.includes(get_tag(tag)));
18
+ if (!all_good) {
19
+ const bad = get_tag(tags.find(tag => !allowed.includes(get_tag(tag))) ?? "");
20
+ const alloweds = `${allowed.map(tag => `<${tag}>`).join(", ")}`;
21
+ const error = `Head may only contain ${alloweds}, found <${bad}>`;
22
+ throw new Error(error);
23
+ }
24
+ const titles = tags.filter(tag => get_tag(tag) === "title");
25
+ const others = tags.filter(tag => get_tag(tag) !== "title");
26
+ return [
27
+ ...titles,
28
+ ...others.map(other => make_tag(other, id)),
29
+ ];
30
+ };
31
+ const clear = (data_value) => {
32
+ const selector = `[${data_attribute}="${data_value}"]`;
33
+ globalThis.document.querySelectorAll(selector).forEach(element => {
34
+ element.remove();
35
+ });
36
+ };
37
+ const Head = function Head(props) {
38
+ const context = useContext(HeadContext);
39
+ context(render(props.children, data_ssr));
40
+ return null;
41
+ };
42
+ Head.clear = (data_value = data_ssr) => clear(data_value);
43
+ export default Head;
44
+ //# sourceMappingURL=default.js.map
@@ -0,0 +1,8 @@
1
+ declare const Head: {
2
+ (props: {
3
+ children: any[];
4
+ }): null;
5
+ clear: (data_value?: string) => void;
6
+ };
7
+ export default Head;
8
+ //# sourceMappingURL=Head.d.ts.map
@@ -0,0 +1,8 @@
1
+ import impl from "#HeadImpl";
2
+ const Head = function Head(props) {
3
+ impl(props);
4
+ return null;
5
+ };
6
+ Head.clear = impl.clear;
7
+ export default Head;
8
+ //# sourceMappingURL=Head.js.map
@@ -0,0 +1,11 @@
1
+ import FrontendModule from "@primate/core/frontend/Module";
2
+ import type Render from "@primate/core/frontend/Render";
3
+ import type { Component } from "solid-js";
4
+ export default class Runtime extends FrontendModule<Component> {
5
+ name: string;
6
+ defaultExtensions: string[];
7
+ client: boolean;
8
+ layouts: boolean;
9
+ render: Render<Component>;
10
+ }
11
+ //# sourceMappingURL=Runtime.d.ts.map
@@ -0,0 +1,22 @@
1
+ import FrontendModule from "@primate/core/frontend/Module";
2
+ import { renderToString } from "solid-js/web";
3
+ export default class Runtime extends FrontendModule {
4
+ name = "solid";
5
+ defaultExtensions = [".jsx", ".tsx"];
6
+ client = true;
7
+ layouts = true;
8
+ render = (component, props) => {
9
+ const heads = [];
10
+ const push_heads = (sub_heads) => {
11
+ heads.push(...sub_heads);
12
+ };
13
+ const body = renderToString(() => component({ ...props, push_heads }));
14
+ if (heads.filter(head => head.startsWith("<title")).length > 1) {
15
+ const error = "May only contain one <title> across component hierarchy";
16
+ throw new Error(error);
17
+ }
18
+ const head = heads.join("\n");
19
+ return { body, head };
20
+ };
21
+ }
22
+ //# sourceMappingURL=Runtime.js.map
@@ -0,0 +1,10 @@
1
+ import type ValidateUpdater from "@primate/core/client/ValidateUpdater";
2
+ import type ValidationError from "@primate/core/client/ValidationError";
3
+ type Validated<T> = {
4
+ error: () => null | ValidationError;
5
+ loading: () => boolean;
6
+ update: (updater: ValidateUpdater<T>) => Promise<void>;
7
+ value: () => T;
8
+ };
9
+ export type { Validated as default };
10
+ //# sourceMappingURL=Validated.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=Validated.js.map
@@ -0,0 +1,11 @@
1
+ import type ClientData from "@primate/core/client/Data";
2
+ import type Dict from "@rcompat/type/Dict";
3
+ type Data = ClientData<{
4
+ components: string[];
5
+ props: Dict[];
6
+ }>;
7
+ export default class Solid {
8
+ static mount(component: string, data: ClientData<Data>): void;
9
+ }
10
+ export {};
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,31 @@
1
+ import spa from "@primate/core/client/spa";
2
+ import SolidHead from "@primate/solid/Head";
3
+ import { hydrate, render } from "solid-js/web";
4
+ // @ts-expect-error esbuild vfs
5
+ import * as components from "solid:components";
6
+ // @ts-expect-error esbuild vfs
7
+ import root_component from "solid:root";
8
+ // @ts-expect-error solid hydration
9
+ globalThis._$HY = { completed: new WeakSet(), events: [], r: {} };
10
+ const { body } = globalThis.window.document;
11
+ SolidHead.clear();
12
+ const make_props = (data) => ({
13
+ components: data.components.map(name => components[name]),
14
+ props: data.props,
15
+ request: {
16
+ ...data.request,
17
+ url: new URL(location.href),
18
+ },
19
+ });
20
+ export default class Solid {
21
+ static mount(component, data) {
22
+ let dispose = hydrate(() => root_component(make_props(data)), body);
23
+ if (data.spa) {
24
+ window.addEventListener("DOMContentLoaded", _ => spa(_data => {
25
+ dispose();
26
+ dispose = render(() => root_component(make_props(_data)), body);
27
+ }));
28
+ }
29
+ }
30
+ }
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,25 @@
1
+ import type Validated from "#client/Validated";
2
+ declare const _default: <T>(initial: T) => {
3
+ delete: (url: string, options?: {
4
+ headers?: import("@rcompat/type/Dict").default<string>;
5
+ map?: ((v: T) => import("@rcompat/type/JSONValue").default) | undefined;
6
+ path?: import("@rcompat/type/JSONPointer").default;
7
+ } | undefined) => Validated<T>;
8
+ patch: (url: string, options?: {
9
+ headers?: import("@rcompat/type/Dict").default<string>;
10
+ map?: ((v: T) => import("@rcompat/type/JSONValue").default) | undefined;
11
+ path?: import("@rcompat/type/JSONPointer").default;
12
+ } | undefined) => Validated<T>;
13
+ post: (url: string, options?: {
14
+ headers?: import("@rcompat/type/Dict").default<string>;
15
+ map?: ((v: T) => import("@rcompat/type/JSONValue").default) | undefined;
16
+ path?: import("@rcompat/type/JSONPointer").default;
17
+ } | undefined) => Validated<T>;
18
+ put: (url: string, options?: {
19
+ headers?: import("@rcompat/type/Dict").default<string>;
20
+ map?: ((v: T) => import("@rcompat/type/JSONValue").default) | undefined;
21
+ path?: import("@rcompat/type/JSONPointer").default;
22
+ } | undefined) => Validated<T>;
23
+ };
24
+ export default _default;
25
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1,29 @@
1
+ import toValidated from "@primate/core/client/toValidated";
2
+ import validate from "@primate/core/client/validate";
3
+ import { createSignal } from "solid-js";
4
+ function useValidate(init) {
5
+ const [value, setValue] = createSignal(init.initial);
6
+ const [loading, setLoading] = createSignal(false);
7
+ const [error, setError] = createSignal(null);
8
+ async function update(updater) {
9
+ const previous = value();
10
+ const next = updater(previous);
11
+ setValue(() => next);
12
+ setLoading(true);
13
+ setError(null);
14
+ try {
15
+ await validate(init, next);
16
+ }
17
+ catch (e) {
18
+ // rollback
19
+ setValue(() => previous);
20
+ setError(() => e);
21
+ }
22
+ finally {
23
+ setLoading(false);
24
+ }
25
+ }
26
+ return { error, loading, update, value };
27
+ }
28
+ export default toValidated(useValidate);
29
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1,13 @@
1
+ import type ContextData from "@primate/core/i18n/ContextData";
2
+ import type Dict from "@rcompat/type/Dict";
3
+ import { type Accessor, type Setter } from "solid-js";
4
+ type Context = {
5
+ i18n: ContextData;
6
+ } & Dict;
7
+ export type AppContextValue = {
8
+ context: Accessor<Context>;
9
+ setContext: Setter<Context>;
10
+ };
11
+ declare const _default: import("solid-js").Context<AppContextValue>;
12
+ export default _default;
13
+ //# sourceMappingURL=app.d.ts.map
@@ -0,0 +1,10 @@
1
+ import { createContext } from "solid-js";
2
+ export default createContext({
3
+ context: () => ({
4
+ i18n: {
5
+ locale: "en-US",
6
+ },
7
+ }),
8
+ setContext: (() => { }),
9
+ });
10
+ //# sourceMappingURL=app.js.map
@@ -0,0 +1,3 @@
1
+ declare const _default: import("solid-js").Context<unknown>;
2
+ export default _default;
3
+ //# sourceMappingURL=head.d.ts.map
@@ -1,3 +1,3 @@
1
1
  import { createContext } from "solid-js";
2
-
3
2
  export default createContext();
3
+ //# sourceMappingURL=head.js.map
@@ -0,0 +1,3 @@
1
+ declare const _default: (length: number, i18n_active: boolean) => string;
2
+ export default _default;
3
+ //# sourceMappingURL=create-root.d.ts.map
@@ -0,0 +1,40 @@
1
+ export default (length, i18n_active) => {
2
+ const n = length - 1;
3
+ const body = Array.from({ length: n }, (_, i) => i - 1)
4
+ .reduceRight((child, _, i) => `components[${i + 1}] !== undefined
5
+ ? createComponent(components[${i}], {request, ...props[${i}],
6
+ children: ${child}})
7
+ : createComponent(components[${i}], {request, ...props[${i}]})
8
+ `, `createComponent(components[${n}], {request, ...props[${n}]})`);
9
+ const i18n_imports = i18n_active
10
+ ? `
11
+ import I18nBridge from "@primate/solid/i18n/Bridge";
12
+ import t from "#i18n";`
13
+ : "";
14
+ const tree = i18n_active
15
+ ? `<I18nBridge t={t}>{${body}}</I18nBridge>`
16
+ : `{${body}}`;
17
+ return `
18
+ import { createSignal } from "solid-js";
19
+ import { createComponent } from "solid-js/web";
20
+ import AppContext from "@primate/solid/context/app";
21
+ import HeadContext from "@primate/solid/context/head";${i18n_imports}
22
+
23
+ export default ({
24
+ components,
25
+ props,
26
+ request,
27
+ push_heads: value,
28
+ }) => {
29
+ const [context, setContext] = createSignal(request.context);
30
+ const $value = { context, setContext };
31
+
32
+ return <AppContext.Provider value={$value}>
33
+ <HeadContext.Provider value={value}>
34
+ ${tree}
35
+ </HeadContext.Provider>
36
+ </AppContext.Provider>
37
+ }
38
+ `;
39
+ };
40
+ //# sourceMappingURL=create-root.js.map
@@ -0,0 +1,8 @@
1
+ import type API from "@primate/core/i18n/API";
2
+ import type Catalogs from "@primate/core/i18n/Catalogs";
3
+ import { type JSX } from "solid-js";
4
+ export default function I18nBridge<C extends Catalogs>(props: {
5
+ t: API<C>;
6
+ children?: JSX.Element;
7
+ }): import("react").JSX.Element;
8
+ //# sourceMappingURL=Bridge.browser.d.ts.map
@@ -0,0 +1,25 @@
1
+ import { memo as _$memo } from "solid-js/web";
2
+ import AppContext from "#context/app";
3
+ import sInternal from "@primate/core/i18n/sInternal";
4
+ import { createSignal, onCleanup, onMount, useContext } from "solid-js";
5
+ function I18nBridge(props) {
6
+ const {
7
+ context
8
+ } = useContext(AppContext);
9
+ const server = context().i18n.locale;
10
+ if (server !== void 0 && server !== props.t.locale.get()) {
11
+ props.t[sInternal].init(server);
12
+ }
13
+ const [version, setVersion] = createSignal(props.t[sInternal].version);
14
+ const removeDepend = props.t[sInternal].depend(() => {
15
+ version();
16
+ });
17
+ const off = props.t.subscribe(() => setVersion(v => v + 1));
18
+ onMount(() => props.t[sInternal].restore());
19
+ onCleanup(() => {
20
+ off();
21
+ removeDepend();
22
+ });
23
+ return _$memo(() => props.children);
24
+ }
25
+ export { I18nBridge as default };
@@ -0,0 +1,8 @@
1
+ import type API from "@primate/core/i18n/API";
2
+ import type Catalogs from "@primate/core/i18n/Catalogs";
3
+ import { type JSX } from "solid-js";
4
+ export default function I18nBridge<C extends Catalogs>(props: {
5
+ t: API<C>;
6
+ children?: JSX.Element;
7
+ }): import("react").JSX.Element;
8
+ //# sourceMappingURL=Bridge.default.d.ts.map
@@ -0,0 +1,12 @@
1
+ import { memo as _$memo } from "solid-js/web";
2
+ import AppContext from "#context/app";
3
+ import sInternal from "@primate/core/i18n/sInternal";
4
+ import { useContext } from "solid-js";
5
+ function I18nBridge(props) {
6
+ const {
7
+ context
8
+ } = useContext(AppContext);
9
+ props.t[sInternal].init(context().i18n.locale);
10
+ return _$memo(() => props.children);
11
+ }
12
+ export { I18nBridge as default };
@@ -0,0 +1,2 @@
1
+ export { default } from "#Head";
2
+ //# sourceMappingURL=Head.d.ts.map
@@ -0,0 +1,2 @@
1
+ export { default } from "#Head";
2
+ //# sourceMappingURL=Head.js.map
@@ -0,0 +1,2 @@
1
+ export { default } from "#client/Validated";
2
+ //# sourceMappingURL=Validated.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=Validated.js.map
@@ -0,0 +1,2 @@
1
+ export { default } from "#client/index";
2
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1,2 @@
1
+ export { default } from "#client/index";
2
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1,2 @@
1
+ export { default } from "#context/app";
2
+ //# sourceMappingURL=app.d.ts.map
@@ -1 +1,2 @@
1
1
  export { default } from "#context/app";
2
+ //# sourceMappingURL=app.js.map
@@ -0,0 +1,2 @@
1
+ export { default } from "#context/head";
2
+ //# sourceMappingURL=head.d.ts.map
@@ -1 +1,2 @@
1
1
  export { default } from "#context/head";
2
+ //# sourceMappingURL=head.js.map
@@ -0,0 +1,4 @@
1
+ import Default from "#Default";
2
+ declare const _default: (options?: typeof Default.input) => Default;
3
+ export default _default;
4
+ //# sourceMappingURL=default.d.ts.map
@@ -0,0 +1,3 @@
1
+ import Default from "#Default";
2
+ export default (options) => new Default(options);
3
+ //# sourceMappingURL=default.js.map
@@ -0,0 +1,2 @@
1
+ export { default } from "#i18n/Bridge.browser";
2
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1,2 @@
1
+ export { default } from "#i18n/Bridge.browser";
2
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1,2 @@
1
+ export { default } from "#i18n/Bridge.default";
2
+ //# sourceMappingURL=default.d.ts.map
@@ -0,0 +1,2 @@
1
+ export { default } from "#i18n/Bridge.default";
2
+ //# sourceMappingURL=default.js.map
@@ -0,0 +1,4 @@
1
+ import Runtime from "#Runtime";
2
+ declare const _default: (options?: typeof Runtime.input) => Runtime;
3
+ export default _default;
4
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1,3 @@
1
+ import Runtime from "#Runtime";
2
+ export default (options) => new Runtime(options);
3
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1,2 @@
1
+ export { default } from "#client/validate";
2
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1,2 @@
1
+ export { default } from "#client/validate";
2
+ //# sourceMappingURL=validate.js.map
package/package.json CHANGED
@@ -1,74 +1,64 @@
1
1
  {
2
2
  "name": "@primate/solid",
3
- "version": "0.4.3",
3
+ "version": "0.5.0",
4
4
  "description": "Primate Solid frontend",
5
- "homepage": "https://primatejs.com/modules/solid",
6
- "bugs": "https://github.com/primatejs/primate/issues",
5
+ "homepage": "https://primate.run/docs/frontend/solid",
6
+ "bugs": "https://github.com/primate-run/primate/issues",
7
7
  "license": "MIT",
8
8
  "files": [
9
- "src/**/*.js",
10
- "!src/**/*.spec.js"
9
+ "/lib/**/*.js",
10
+ "/lib/**/*.d.ts",
11
+ "!/**/*.spec.*"
11
12
  ],
12
13
  "repository": {
13
14
  "type": "git",
14
- "url": "https://github.com/primatejs/primate",
15
+ "url": "https://github.com/primate-run/primate",
15
16
  "directory": "packages/solid"
16
17
  },
18
+ "devDependencies": {
19
+ "@types/babel__core": "^7.20.5"
20
+ },
17
21
  "dependencies": {
18
- "@babel/core": "^7.52.2",
19
- "@rcompat/build": "^0.5.0",
20
- "@rcompat/fs": "^0.7.0",
21
- "@rcompat/runtime": "^0.1.0",
22
- "babel-preset-solid": "^1.8.19",
23
- "@primate/frontend": "^0.16.4"
22
+ "@babel/core": "^7.28.4",
23
+ "@rcompat/build": "^0.14.0",
24
+ "@rcompat/fs": "^0.21.1",
25
+ "@rcompat/runtime": "^0.6.0",
26
+ "babel-preset-solid": "^1.9.9",
27
+ "fast-glob": "^3.3.3",
28
+ "@primate/core": "^0.2.0"
24
29
  },
25
30
  "peerDependencies": {
26
31
  "solid-js": "1",
27
- "@primate/i18n": "^0.8.3",
28
- "primate": "^0.32.6"
29
- },
30
- "peerDependenciesMeta": {
31
- "@primate/i18n": {
32
- "optional": true
33
- }
32
+ "primate": "^0.33.0"
34
33
  },
35
34
  "type": "module",
36
35
  "imports": {
37
36
  "#*": {
38
- "livetypes": "./src/private/*.js",
39
- "default": "./src/private/*.js"
40
- },
41
- "#build": {
42
- "livetypes": "./src/private/build/index.js",
43
- "default": "./src/private/build/index.js"
44
- },
45
- "#serve": {
46
- "livetypes": "./src/private/serve/index.js",
47
- "default": "./src/private/serve/index.js"
37
+ "apekit": "./src/private/*.ts",
38
+ "default": "./lib/private/*.js"
48
39
  },
49
- "#context/*": {
50
- "livetypes": "./src/private/context/*.js",
51
- "default": "./src/private/context/*.js"
52
- },
53
- "#client": {
54
- "livetypes": "./src/private/client/index.js",
55
- "default": "./src/private/client/index.js"
56
- },
57
- "#client/*": {
58
- "livetypes": "./src/private/client/*.js",
59
- "default": "./src/private/client/*.js"
60
- },
61
- "#i18n/*": {
62
- "livetypes": "./src/private/i18n/*.js",
63
- "default": "./src/private/i18n/*.js"
40
+ "#HeadImpl": {
41
+ "apekit": "./src/private/Head/default.ts",
42
+ "browser": "./lib/private/Head/browser.js",
43
+ "default": "./lib/private/Head/default.js"
64
44
  }
65
45
  },
66
46
  "exports": {
67
47
  ".": {
68
- "runtime": "./src/public/runtime.js",
69
- "default": "./src/public/default.js"
48
+ "browser": "./lib/public/browser.js",
49
+ "runtime": "./lib/public/runtime.js",
50
+ "default": "./lib/public/default.js"
70
51
  },
71
- "./*": "./src/public/*.js",
72
- "./context/*": "./src/public/context/*.js"
52
+ "./*": "./lib/public/*.js",
53
+ "./i18n/Bridge": {
54
+ "browser": "./lib/public/i18n/Bridge/browser.js",
55
+ "default": "./lib/public/i18n/Bridge/default.js"
56
+ }
57
+ },
58
+ "scripts": {
59
+ "build": "npm run clean && tsc",
60
+ "postbuild": "node scripts/compile-jsx.js",
61
+ "clean": "rm -rf ./lib",
62
+ "lint": "eslint ."
73
63
  }
74
64
  }
@@ -1,7 +0,0 @@
1
- import { transformAsync } from "@babel/core";
2
- import solid from "babel-preset-solid";
3
-
4
- export default async text => {
5
- const presets = [[solid, { generate: "dom", hydratable: true }]];
6
- return { js: (await transformAsync(text, { presets })).code };
7
- };
@@ -1,14 +0,0 @@
1
- import create_root from "#client/create-root";
2
- import expose from "#client/expose";
3
- import name from "#name";
4
- import build from "@primate/frontend/core/build";
5
- import client from "./client.js";
6
- import publish from "./publish.js";
7
- import server from "./server.js";
8
-
9
- export default extension => build({
10
- create_root,
11
- extension,
12
- name,
13
- actions: { compile: { client, server }, expose, publish },
14
- });
@@ -1,26 +0,0 @@
1
- import file from "@rcompat/fs/file";
2
- import client from "./client.js";
3
-
4
- const root_filter = /^root:solid/u;
5
-
6
- export default (app, extension) => ({
7
- name: "solid",
8
- setup(build) {
9
- build.onResolve({ filter: root_filter }, ({ path }) => {
10
- return { path, namespace: "solidroot" };
11
- });
12
- build.onLoad({ filter: root_filter }, ({ path }) => {
13
- const contents = app.build.load(path);
14
- return contents
15
- ? { contents, loader: "js", resolveDir: app.root.path }
16
- : null;
17
- });
18
- build.onLoad({ filter: new RegExp(`${extension}$`, "u") }, async args => {
19
- // Load the file from the file system
20
- const source = await file(args.path).text();
21
-
22
- // Convert JSX syntax to JavaScript
23
- return { contents: (await client(source)).js };
24
- });
25
- },
26
- });
@@ -1,8 +0,0 @@
1
- import { transformAsync } from "@babel/core";
2
- import solid from "babel-preset-solid";
3
-
4
- export default async text => {
5
- const presets = [[solid, { generate: "ssr", hydratable: true }]];
6
- return (await transformAsync(text, { presets })).code;
7
- };
8
-
@@ -1,33 +0,0 @@
1
- export default length => {
2
- const n = length - 1;
3
- const body = Array.from({ length: n }, (_, i) => i - 1)
4
- .reduceRight((child, _, i) => `components[${i + 1}] !== undefined
5
- ? createComponent(components[${i}], {request, ...data[${i}],
6
- children: ${child}})
7
- : createComponent(components[${i}], {request, ...data[${i}]})
8
- `, `createComponent(components[${n}], {request, ...data[${n}]})`);
9
-
10
- return `
11
- import { createSignal } from "solid-js";
12
- import { createComponent } from "solid-js/web";
13
- import AppContext from "@primate/solid/context/app";
14
- import HeadContext from "@primate/solid/context/head";
15
-
16
- export default ({
17
- components,
18
- data,
19
- request,
20
- context: c,
21
- push_heads: value,
22
- }) => {
23
- const [context, setContext] = createSignal(c);
24
- const $value = { context, setContext };
25
-
26
- return <AppContext.Provider value={$value}>
27
- <HeadContext.Provider value={value}>
28
- {${body}}
29
- </HeadContext.Provider>
30
- </AppContext.Provider>
31
- }
32
- `;
33
- };
@@ -1,7 +0,0 @@
1
- export default `
2
- export {
3
- hydrate as hydrate_solid,
4
- render as render_solid,
5
- } from "solid-js/web";
6
- export { default as SolidHead } from "@primate/solid/head";
7
- `;
@@ -1,25 +0,0 @@
1
- import { generateHydrationScript } from "solid-js/web";
2
- import spa from "./spa.js";
3
-
4
- const { groups: { code: hydration_script } } = generateHydrationScript()
5
- .match(/^<script>(?<code>.*?)<\/script>/u);
6
-
7
- export default ({ names, data, context, request }, options) => `
8
- import * as components from "app";
9
- import { hydrate_solid, render_solid, SolidHead } from "app";
10
-
11
- window._$HY = { events: [], completed: new WeakSet(), r: {} };
12
-
13
- ${hydration_script}
14
-
15
- SolidHead.clear();
16
- let dispose = hydrate_solid(() => components.root_solid({
17
- components: [${names.map(name => `components.${name}`).join(", ")}],
18
- data: ${JSON.stringify(data)},
19
- context: ${JSON.stringify(context)},
20
- request: {
21
- ...${JSON.stringify(request)},
22
- url: new URL(location.href),
23
- },
24
- }), globalThis.window.document.body);
25
- ${options.spa ? spa : ""}`;
@@ -1,14 +0,0 @@
1
- export default `
2
- const { spa } = components;
3
- window.addEventListener("DOMContentLoaded", _ => spa((props, update) => {
4
- dispose();
5
- dispose = render_solid(() => components.root_solid({
6
- components: props.names.map(name => components[name]),
7
- data: props.data,
8
- context: props.context,
9
- request: {
10
- ...props.request,
11
- url: new URL(location.href),
12
- },
13
- }), globalThis.window.document.body);
14
- }));`;
@@ -1,3 +0,0 @@
1
- import { createContext } from "solid-js";
2
-
3
- export default createContext({});
@@ -1 +0,0 @@
1
- export default ".jsx";
@@ -1,10 +0,0 @@
1
- import resolve from "@primate/i18n/core/resolve";
2
- import AppContext from "#context/app";
3
- import { useContext } from "solid-js";
4
- import locale_store from "./locale.js";
5
-
6
- export default (key, placeholders) => {
7
- locale_store.init();
8
- const { locales, locale } = useContext(AppContext).context().i18n;
9
- return resolve(locales[locale], key, placeholders);
10
- };
@@ -1,37 +0,0 @@
1
- import AppContext from "#context/app";
2
- import save from "@primate/i18n/core/save";
3
- import { useContext } from "solid-js";
4
-
5
- const $ = {
6
- context: Symbol("context"),
7
- setContext: Symbol("setContext"),
8
- };
9
-
10
- export default {
11
- [$.context]: undefined,
12
- [$.setContext]: undefined,
13
- get() {
14
- this.init();
15
- return this[$.context].i18n.locale;
16
- },
17
- set(locale) {
18
- this.init();
19
- this[$.setContext]({
20
- ...this[$.context],
21
- i18n: {
22
- locale,
23
- locales: this[$.context].i18n.locales,
24
- },
25
- });
26
- save(locale);
27
- },
28
- init() {
29
- if (this[$.context] !== undefined) {
30
- return;
31
- }
32
-
33
- const { context, setContext } = useContext(AppContext);
34
- this[$.context] = context();
35
- this[$.setContext] = setContext;
36
- },
37
- };
@@ -1 +0,0 @@
1
- export default "solid";
@@ -1 +0,0 @@
1
- export default "@primate/solid";
@@ -1,16 +0,0 @@
1
- import handler from "@primate/frontend/core/handler";
2
- import client from "#client";
3
- import name from "#name";
4
- import render from "./render.js";
5
-
6
- export default (extension, spa) => (app, next) => {
7
- app.register(extension, handler({
8
- app,
9
- render,
10
- client,
11
- name,
12
- spa,
13
- }));
14
-
15
- return next(app);
16
- };
@@ -1,17 +0,0 @@
1
- import { renderToString } from "solid-js/web";
2
-
3
- export default (component, props) => {
4
- const heads = [];
5
- const push_heads = sub_heads => {
6
- heads.push(...sub_heads);
7
- };
8
- const body = renderToString(() => component({ ...props, push_heads }));
9
-
10
- if (heads.filter(head => head.startsWith("<title")).length > 1) {
11
- const error = "May only contain one <title> across component hierarchy";
12
- throw new Error(error);
13
- }
14
- const head = heads.join("\n");
15
-
16
- return { body, head };
17
- };
@@ -1,14 +0,0 @@
1
- import build from "#build";
2
- import default_extension from "#extension";
3
- import pkgname from "#pkgname";
4
- import serve from "#serve";
5
-
6
- export default ({
7
- extension = default_extension,
8
- // activate fetch-based browsing
9
- spa = true,
10
- } = {}) => ({
11
- name: pkgname,
12
- build: build(extension),
13
- serve: serve(extension, spa),
14
- });
@@ -1,92 +0,0 @@
1
- import HeadContext from "#context/head";
2
- import runtime from "@rcompat/runtime";
3
- import { onCleanup, onMount, useContext } from "solid-js";
4
-
5
- const is_client = runtime === "browser";
6
-
7
- const to_array = maybe => Array.isArray(maybe) ? maybe : [maybe];
8
-
9
- const data_attribute = "data-sh";
10
- const data_ssr = "ssr";
11
- const allowed = ["title", "meta", "style", "meta", "link", "script", "base"];
12
-
13
- const make_tag = (tag, id) => {
14
- const parts = tag.split(" ");
15
- return [
16
- parts[0],
17
- `${data_attribute}="${id}"`,
18
- ...parts.slice(1),
19
- ].join(" ");
20
- };
21
-
22
- const get_tag = child => child.match(/^<(?<tag>[a-z]*) .*$/u).groups.tag;
23
-
24
- const render = (maybe_children, id) => {
25
- const children = to_array(maybe_children);
26
-
27
- if (is_client) {
28
- // DOM elements
29
- const titles = children.filter(({ tagName }) => tagName === "TITLE");
30
- const others = children.filter(({ tagName }) => tagName !== "TITLE");
31
-
32
- titles.forEach(title => {
33
- globalThis.document.title = title.innerText;
34
- });
35
- others.forEach(other => {
36
- other.dataset.sh = id;
37
- globalThis.document.head.prepend(other);
38
- });
39
- } else {
40
- const tags = children.map(({ t: tag }) => tag);
41
- const all_good = tags.every(tag => allowed.includes(get_tag(tag)));
42
- if (!all_good) {
43
- const bad = get_tag(tags.find(tag => !allowed.includes(get_tag(tag))));
44
- const alloweds = `${allowed.map(tag => `<${tag}>`).join(", ")}`;
45
- const error = `Head may only contain ${alloweds}, found <${bad}>`;
46
- throw new Error(error);
47
- }
48
-
49
- const titles = tags.filter(tag => get_tag(tag) === "title");
50
- const others = tags.filter(tag => get_tag(tag) !== "title");
51
-
52
- return [
53
- ...titles,
54
- ...others.map(other => make_tag(other, id)),
55
- ];
56
- }
57
- };
58
-
59
- const clear = (data_value) => {
60
- const selector = `[${data_attribute}="${data_value}"]`;
61
- globalThis.document.querySelectorAll(selector).forEach(element => {
62
- element.remove();
63
- });
64
- };
65
-
66
- const Head = function Head(props) {
67
- let id;
68
- onMount(() => {
69
- if (is_client) {
70
- id = crypto.randomUUID();
71
- render(props.children, id);
72
- }
73
- });
74
-
75
- onCleanup(() => {
76
- if (is_client) {
77
- // remove managed tags
78
- clear(id);
79
- }
80
- });
81
-
82
- if (!is_client) {
83
- const context = useContext(HeadContext);
84
- context(render(props.children, data_ssr));
85
- }
86
-
87
- // no return, nothing rendered
88
- };
89
-
90
- Head.clear = (data_value = data_ssr) => clear(data_value);
91
-
92
- export default Head;
@@ -1 +0,0 @@
1
- export { default } from "#i18n/index";
@@ -1 +0,0 @@
1
- export { default } from "#i18n/locale";
@@ -1,12 +0,0 @@
1
- import default_extension from "#extension";
2
- import pkgname from "#pkgname";
3
- import serve from "#serve";
4
-
5
- export default ({
6
- extension = default_extension,
7
- // activate fetch-based browsing
8
- spa = true,
9
- } = {}) => ({
10
- name: pkgname,
11
- serve: serve(extension, spa),
12
- });