Skip to content

Commit

Permalink
add loaders and actions
Browse files Browse the repository at this point in the history
  • Loading branch information
tlgimenes committed Jan 11, 2024
1 parent a78487f commit c2a45c7
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 182 deletions.
96 changes: 96 additions & 0 deletions admin/actions/environments/connect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { fjp } from "../../deps.ts";
import { storage } from "../../fsStorage.ts";
import { Acked, Commands, Events, State } from "../../types.ts";

export interface Props {
/** Environment name to connect to */
name: string;
}

const subscribers: WebSocket[] = [];

export const fetchState = async (): Promise<State> => ({
decofile: await storage.state({ forceFresh: true }),
});

const saveState = ({ decofile }: State): Promise<void> =>
storage.update(decofile);

// Apply patch and save state ATOMICALLY!
// This is easily done on play. On production, however, we probably
// need a distributed queue
let queue = Promise.resolve();
const patchState = (ops: fjp.Operation[]) => {
queue = queue.catch(() => null).then(async () =>
saveState(ops.reduce(fjp.applyReducer, await fetchState()))
);

return queue;
};

const action = (_props: Props, req: Request) => {
const { socket, response } = Deno.upgradeWebSocket(req);

const broadcast = (event: Acked<Events>) => {
const message = JSON.stringify(event);
subscribers.forEach((s) => s.send(message));
};
const send = (event: Acked<Events>) => socket.send(JSON.stringify(event));
const parse = (event: MessageEvent<string>): Acked<Commands> =>
JSON.parse(event.data);

const open = () => subscribers.push(socket);
const close = () => subscribers.splice(subscribers.indexOf(socket), 1);
const message = async (event: MessageEvent<string>) => {
const data = parse(event);

const { ack } = data;

if (data.type === "patch-state") {
try {
const { payload: operations } = data;

await patchState(operations);

// Broadcast changes
broadcast({
type: "state-patched",
payload: operations,
etag: await storage.revision(),
metadata: {}, // TODO: add metadataß
ack,
});
} catch ({ name, operation }) {
console.error({ name, operation });
}
} else if (data.type === "fetch-state") {
send({
type: "state-fetched",
payload: await fetchState(),
etag: await storage.revision(),
ack,
});
} else {
console.error("UNKNOWN EVENT", event);
}
};

/**
* Handles the WebSocket connection on open event.
*/
socket.onopen = open;
/**
* Handles the WebSocket connection on close event.
*/
socket.onclose = close;

/**
* Handles the WebSocket connection on message event.
* @param {MessageEvent} event - The WebSocket message event.
*/
socket.onmessage = (e) => message(e).catch(() => {});

return response;
};

export default action;
18 changes: 18 additions & 0 deletions admin/actions/environments/decofile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { fetchState } from "./connect.ts";
import { State } from "../../types.ts";
import { storage } from "../../fsStorage.ts";

interface Props {
name: string;
}

/** TODO(@gimenes): Implement fetching the state from the proper environment name */
const action = async (_props: Props): Promise<State["decofile"]> => {
const { decofile } = await fetchState();

console.log("serving revision", await storage.revision());

return decofile;
};

export default action;
162 changes: 0 additions & 162 deletions admin/actions/workspaces/connect.ts

This file was deleted.

38 changes: 20 additions & 18 deletions admin/manifest.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@ import * as $$$$$$$$$1 from "./actions/blocks/restore.ts";
import * as $$$$$$$$$2 from "./actions/blocks/safeDelete.ts";
import * as $$$$$$$$$3 from "./actions/blocks/newRevision.ts";
import * as $$$$$$$$$4 from "./actions/blocks/delete.ts";
import * as $$$$$$$$$5 from "./actions/workspaces/connect.ts";
import * as $$$$$$$$$6 from "./actions/sites/linkRepo.ts";
import * as $$$$$$$$$7 from "./actions/sites/newDomain.ts";
import * as $$$$$$$$$8 from "./actions/sites/unlinkRepo.ts";
import * as $$$$$$$$$9 from "./actions/github/setStatus.ts";
import * as $$$$$$$$$10 from "./actions/github/webhooks/broker.ts";
import * as $$$$$$$$$11 from "./actions/pages/publish.ts";
import * as $$$$$$$$$12 from "./actions/pages/new.ts";
import * as $$$$$$$$$13 from "./actions/pages/delete.ts";
import * as $$$$$$$$$5 from "./actions/environments/decofile.ts";
import * as $$$$$$$$$6 from "./actions/environments/connect.ts";
import * as $$$$$$$$$7 from "./actions/sites/linkRepo.ts";
import * as $$$$$$$$$8 from "./actions/sites/newDomain.ts";
import * as $$$$$$$$$9 from "./actions/sites/unlinkRepo.ts";
import * as $$$$$$$$$10 from "./actions/github/setStatus.ts";
import * as $$$$$$$$$11 from "./actions/github/webhooks/broker.ts";
import * as $$$$$$$$$12 from "./actions/pages/publish.ts";
import * as $$$$$$$$$13 from "./actions/pages/new.ts";
import * as $$$$$$$$$14 from "./actions/pages/delete.ts";

const manifest = {
"loaders": {
Expand All @@ -44,15 +45,16 @@ const manifest = {
"deco-sites/admin/actions/blocks/publish.ts": $$$$$$$$$0,
"deco-sites/admin/actions/blocks/restore.ts": $$$$$$$$$1,
"deco-sites/admin/actions/blocks/safeDelete.ts": $$$$$$$$$2,
"deco-sites/admin/actions/github/setStatus.ts": $$$$$$$$$9,
"deco-sites/admin/actions/github/webhooks/broker.ts": $$$$$$$$$10,
"deco-sites/admin/actions/pages/delete.ts": $$$$$$$$$13,
"deco-sites/admin/actions/pages/new.ts": $$$$$$$$$12,
"deco-sites/admin/actions/pages/publish.ts": $$$$$$$$$11,
"deco-sites/admin/actions/sites/linkRepo.ts": $$$$$$$$$6,
"deco-sites/admin/actions/sites/newDomain.ts": $$$$$$$$$7,
"deco-sites/admin/actions/sites/unlinkRepo.ts": $$$$$$$$$8,
"deco-sites/admin/actions/workspaces/connect.ts": $$$$$$$$$5,
"deco-sites/admin/actions/environments/connect.ts": $$$$$$$$$6,
"deco-sites/admin/actions/environments/decofile.ts": $$$$$$$$$5,
"deco-sites/admin/actions/github/setStatus.ts": $$$$$$$$$10,
"deco-sites/admin/actions/github/webhooks/broker.ts": $$$$$$$$$11,
"deco-sites/admin/actions/pages/delete.ts": $$$$$$$$$14,
"deco-sites/admin/actions/pages/new.ts": $$$$$$$$$13,
"deco-sites/admin/actions/pages/publish.ts": $$$$$$$$$12,
"deco-sites/admin/actions/sites/linkRepo.ts": $$$$$$$$$7,
"deco-sites/admin/actions/sites/newDomain.ts": $$$$$$$$$8,
"deco-sites/admin/actions/sites/unlinkRepo.ts": $$$$$$$$$9,
},
"name": "deco-sites/admin",
"baseUrl": import.meta.url,
Expand Down
35 changes: 35 additions & 0 deletions admin/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,41 @@
import { type Resolvable } from "deco/engine/core/resolver.ts";
import { type fjp } from "./deps.ts";

export interface Pagination<T> {
data: T[];
page: number;
pageSize: number;
total: number;
}

export interface PatchState {
type: "patch-state";
payload: fjp.Operation[];
}

export interface FetchState {
type: "fetch-state";
}

export interface StatePatched {
type: "state-patched";
payload: fjp.Operation[];
etag: string;
// Maybe add data and user info in here
metadata?: unknown;
}

export interface StateFetched {
type: "state-fetched";
payload: State;
etag: string;
}

export type Acked<T> = T & { ack: string };

export interface State {
decofile: Record<string, Resolvable>;
}

export type Commands = PatchState | FetchState;
export type Events = StatePatched | StateFetched;
5 changes: 3 additions & 2 deletions files/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ const compile = async (
): Promise<[AppManifest, SourceMap]> => {
await initializePromise;
const tsModule = await importFromString(content);
const blockPath = join(currdir, blockType, path);
const blockKey = `${manifest.name}/${blockType}/${path}`;
const blockPath = join(currdir, path);
const blockKey = join(manifest.name, path);

return [{
...manifest,
[blockType]: {
Expand Down

0 comments on commit c2a45c7

Please sign in to comment.