Skip to content

Commit

Permalink
export client as npm dep
Browse files Browse the repository at this point in the history
  • Loading branch information
eliknebel committed Sep 8, 2023
1 parent 6d83619 commit b2e9899
Show file tree
Hide file tree
Showing 11 changed files with 144 additions and 53 deletions.
7 changes: 4 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ coverage
.vscode

.DS_Store
priv/static/app.css
priv/static/client.js
priv/static/client.js.map

priv/static
client/dist

yarn-error.log
29 changes: 29 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
.dockerignore
.github
.gitignore
.parcel-cache
.vscode
.DS_Store
Dockerfile
node_modules
build
coverage
src
test
priv

*.beam
*.ez
erl_crash.dump

yarn-error.log

.proxyrc
.tool-versions
fly.toml
gleam.toml
manifest.toml
tailwind.config.js
app.css

!client/src
27 changes: 27 additions & 0 deletions client/src/docs/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { doubleclick } from "./hooks/doubleclick";
import { connect } from "../sprocket";

const hooks = {
DoubleClick: doubleclick,
};

window.addEventListener("DOMContentLoaded", () => {
const preflightId = document
.querySelector("meta[name=spkt-preflight-id]")
?.getAttribute("content");

const csrfToken = document
.querySelector("meta[name=spkt-csrf-token]")
?.getAttribute("content");

if (preflightId && csrfToken) {
connect("/live", {
hooks,
dom: document.documentElement,
preflightId,
csrfToken,
});
} else {
console.error("Missing preflight ID or CSRF token");
}
});
File renamed without changes.
74 changes: 36 additions & 38 deletions client/src/client.ts → client/src/sprocket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,29 @@ import { renderDom } from "./render";
import { applyPatch } from "./patch";
import { initEventHandlers } from "./events";
import { constant } from "./constants";
import { doubleclick } from "./hooks/doubleclick";

const hooks = {
DoubleClick: doubleclick,
type Opts = {
preflightId: string;
csrfToken: string;
dom: Element;
hooks?: Record<string, any>;
};

window.addEventListener("DOMContentLoaded", () => {
export function connect(path: String, opts: Opts) {
const preflightId = opts.preflightId;
const csrfToken = opts.csrfToken;
const hooks = opts.hooks;

let ws_protocol = location.protocol === "https:" ? "wss:" : "ws:";
const socket = new WebSocket(ws_protocol + "//" + location.host + "/live");
const socket = new WebSocket(ws_protocol + "//" + location.host + path);

let dom: Record<string, any>;
const spktPreflightId = document
.querySelector("meta[name=spkt-preflight-id]")
?.getAttribute("content");

const spktCsrfToken = document
.querySelector("meta[name=spkt-csrf-token]")
?.getAttribute("content");

topbar.config({ barColors: { 0: "#29d" }, barThickness: 2 });
topbar.show(500);

socket.addEventListener("open", function (event) {
socket.send(
JSON.stringify(["join", { id: spktPreflightId, csrf: spktCsrfToken }])
);
socket.send(JSON.stringify(["join", { id: preflightId, csrf: csrfToken }]));
});

socket.addEventListener("message", function (event) {
Expand All @@ -41,28 +38,29 @@ window.addEventListener("DOMContentLoaded", () => {
topbar.hide();

// handle hook lifecycle mounted events
Object.keys(hooks).forEach((hook) => {
if (hooks[hook].mounted) {
document
.querySelectorAll(`[${constant.HookAttrPrefix}=${hook}]`)
.forEach((el) => {
const pushEvent = (name: string, payload: any) => {
const hookId = el.getAttribute(
`${constant.HookAttrPrefix}-id`
);

socket.send(
JSON.stringify([
"hook:event",
{ id: hookId, name, payload },
])
);
};

hooks[hook].mounted({ el, pushEvent });
});
}
});
hooks &&
Object.keys(hooks).forEach((hook) => {
if (hooks[hook].mounted) {
document
.querySelectorAll(`[${constant.HookAttrPrefix}=${hook}]`)
.forEach((el) => {
const pushEvent = (name: string, payload: any) => {
const hookId = el.getAttribute(
`${constant.HookAttrPrefix}-id`
);

socket.send(
JSON.stringify([
"hook:event",
{ id: hookId, name, payload },
])
);
};

hooks[hook].mounted({ el, pushEvent });
});
}
});

dom = parsed[1];

Expand Down Expand Up @@ -109,4 +107,4 @@ window.addEventListener("DOMContentLoaded", () => {

// wire up event handlers
initEventHandlers(socket);
});
}
2 changes: 1 addition & 1 deletion gleam.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name = "sprocket"
version = "0.1.2"
version = "0.1.3"
description = "A library for building live views and real-time server components in Gleam"

# Fill out these fields if you intend to generate HTML documentation or publish
Expand Down
16 changes: 12 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
{
"name": "sprocket-js",
"version": "0.1.3",
"source": "client/src/sprocket.ts",
"main": "client/dist/sprocket.js",
"types": "client/dist/types.d.ts",
"devDependencies": {
"@parcel/packager-ts": "2.9.2",
"@parcel/transformer-typescript-types": "2.9.2",
"@tailwindcss/typography": "^0.5.9",
"@types/jest": "^29.5.2",
"@types/node": "^20.4.1",
Expand All @@ -14,18 +21,19 @@
"typescript": "^5.1.3"
},
"scripts": {
"client:build": "parcel build client/src/client.ts --dist-dir priv/static --no-source-maps",
"client:watch": "parcel client/src/client.ts --no-hmr --dist-dir priv/static",
"client:build": "parcel build client/src/sprocket.ts --dist-dir client/dist --no-source-maps",
"client:test": "jest",
"docs:build": "parcel build client/src/docs/app.ts --dist-dir priv/static --no-source-maps",
"docs:watch": "parcel client/src/docs/app.ts --no-hmr --dist-dir priv/static",
"tailwind:build": "npx tailwindcss -i ./app.css -o priv/static/app.css",
"tailwind:watch": "npx tailwindcss -i ./app.css -o priv/static/app.css --watch",
"clean": "rm -rf build dist .parcel-cache",
"watch": "gleam build && concurrently --kill-others \"gleam run -m docs\" \"yarn run client:watch\" \"yarn run tailwind:watch\"",
"watch": "gleam build && concurrently --kill-others \"gleam run -m docs\" \"yarn run docs:watch\" \"yarn run tailwind:watch\"",
"test": "gleam test && yarn run client:test",
"build": "gleam build && yarn run client:build && yarn run tailwind:build"
},
"dependencies": {
"morphdom": "^2.7.0",
"topbar": "^2.0.1"
}
}
}
2 changes: 1 addition & 1 deletion src/docs/controllers/index.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub fn index(req: Request(String), ctx: AppContext) -> Response(String) {
),
)

let body = render(view, html.preflight_renderer(ctx.ca, view))
let body = render(view, html.preflight_renderer(ctx.ca, view, "/app.js"))

response.new(200)
|> response.set_body(body)
Expand Down
2 changes: 0 additions & 2 deletions src/sprocket/internal/constants.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ pub type Const {
EventAttrPrefix
MetaPreflightId
MetaCrsfToken
ClientScript
IgnoreUpdateAttr
ClientHookAttrPrefix
}
Expand All @@ -14,7 +13,6 @@ pub fn constant(c: Const) -> String {
EventAttrPrefix -> "spkt-event"
MetaPreflightId -> "spkt-preflight-id"
MetaCrsfToken -> "spkt-csrf-token"
ClientScript -> "/client.js"
IgnoreUpdateAttr -> "spkt-ignore-update"
ClientHookAttrPrefix -> "spkt-hook"
}
Expand Down
12 changes: 8 additions & 4 deletions src/sprocket/internal/render/html.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import sprocket/render.{
RenderedEventHandler, RenderedText, Renderer, render_element, traverse,
}
import sprocket/internal/constants.{
ClientHookAttrPrefix, ClientScript, EventAttrPrefix, KeyAttr, MetaCrsfToken,
MetaPreflightId, constant,
ClientHookAttrPrefix, EventAttrPrefix, KeyAttr, MetaCrsfToken, MetaPreflightId,
constant,
}
import sprocket/context.{Element}
import sprocket/cassette.{Cassette, Preflight}
Expand All @@ -21,7 +21,11 @@ pub fn renderer() -> Renderer(String) {
Renderer(render: fn(el) { string_builder.to_string(render(el)) })
}

pub fn preflight_renderer(ca: Cassette, view: Element) -> Renderer(String) {
pub fn preflight_renderer(
ca: Cassette,
view: Element,
client_script: String,
) -> Renderer(String) {
let assert Ok(preflight_id) = uuid.v4()
let csrf_token = csrf.generate()

Expand All @@ -44,7 +48,7 @@ pub fn preflight_renderer(ca: Cassette, view: Element) -> Renderer(String) {
|> render_element()

let sprocket_client =
script([src(constant(ClientScript))], None)
script([src(client_script)], None)
|> render_element()

Renderer(render: fn(el) {
Expand Down
26 changes: 26 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1003,6 +1003,13 @@
"@parcel/utils" "2.9.2"
posthtml "^0.16.4"

"@parcel/[email protected]":
version "2.9.2"
resolved "https://registry.yarnpkg.com/@parcel/packager-ts/-/packager-ts-2.9.2.tgz#568b02166255536d5040db3eba114fc4d5fc4084"
integrity sha512-vqVjMTmHA35wEPPXqqkuNykdZh+6g49sT/GZbCJtjJsqmDtVd5AEExgVMpCZ5+ZqPL3VEyjR46uhjrP+1PKvAg==
dependencies:
"@parcel/plugin" "2.9.2"

"@parcel/[email protected]":
version "2.9.2"
resolved "https://registry.yarnpkg.com/@parcel/plugin/-/plugin-2.9.2.tgz#0fe8cee91f5b7d2cc3725073c702fca695b1a639"
Expand Down Expand Up @@ -1233,6 +1240,25 @@
posthtml-render "^3.0.0"
semver "^5.7.1"

"@parcel/[email protected]":
version "2.9.2"
resolved "https://registry.yarnpkg.com/@parcel/transformer-typescript-types/-/transformer-typescript-types-2.9.2.tgz#cf00fa4b72d4c0c502aa41ccc4058e0051c20f17"
integrity sha512-DCWx42Lg2XqwXf90TFCD+uV44GYat69NkTPvilrcr3gws/4y3l978cYu0Q0FShOLWOfteTWWuL+sD0fDIBZDKQ==
dependencies:
"@parcel/diagnostic" "2.9.2"
"@parcel/plugin" "2.9.2"
"@parcel/source-map" "^2.1.1"
"@parcel/ts-utils" "2.9.2"
"@parcel/utils" "2.9.2"
nullthrows "^1.1.1"

"@parcel/[email protected]":
version "2.9.2"
resolved "https://registry.yarnpkg.com/@parcel/ts-utils/-/ts-utils-2.9.2.tgz#873a341f592743b617333d07198fe888a99dffa3"
integrity sha512-Julkwe/iJ/CWrL+/s0L/LUq7FWyB0bRvd7G1qnL1cGjCuspD6qSp6Ko4xLmSYakco8FTlIU8VRbRTBs9UHOIEQ==
dependencies:
nullthrows "^1.1.1"

"@parcel/[email protected]":
version "2.9.2"
resolved "https://registry.yarnpkg.com/@parcel/types/-/types-2.9.2.tgz#195ce0075c9d084c5f57cdffba9ba75ea96e4993"
Expand Down

0 comments on commit b2e9899

Please sign in to comment.