Skip to content

feat: route installer #71

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 20 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,38 +7,40 @@
<!-- START PACKAGES -->

**Packages**
[@truffle/ui@`0.1.12`](./ui) - Unified UI library (WIP)
[@truffle/context@`1.0.0`](./context) - Framework-agnostic context
[@truffle/youtube-js@`0.5.9`](./youtube-js) - Truffle fork of [Youtube.js](https://github.com/LuanRT/YouTube.js)
[@truffle/config@`1.0.0`](./config) - Env/API config
[@truffle/utils@`0.0.35`](./utils) - Browser & Node utilities
[@truffle/state@`0.0.12`](./state) - Signals coupled with Legend state for React
[@truffle/router@`1.0.0`](./router) - Framework-agnostic fs router
[@truffle/events@`0.0.1`](./events) - Utilities for handling webhooks from Truffle
[@truffle/distribute@`2.0.20`](./distribute) - Wrappers to create web components from various frameworks
[@truffle/global-context@`1.0.0`](./global-context) - Truffle Global Context to share info between packages
[@truffle/config@`1.0.0`](./config) - Env/API config
[@truffle/third-party-oauth@`2.0.22`](./third-party-oauth) - Login and other auth utilities
[@truffle/api@`0.2.27`](./api) - Hooks and functions for interacting with Truffle's backend
[@truffle/global-context@`1.0.0`](./global-context) - Truffle Global Context to share info between packages
[@truffle/events@`0.0.1`](./events) - Utilities for handling webhooks from Truffle
[@truffle/router@`1.0.0`](./router) - Framework-agnostic fs router
[@truffle/utils@`0.0.35`](./utils) - Browser & Node utilities
[@truffle/ui@`0.1.12`](./ui) - Unified UI library (WIP)
[@truffle/context@`1.0.0`](./context) - Framework-agnostic context
[@truffle/state@`0.0.12`](./state) - Signals coupled with Legend state for React
[@truffle/youtube-js@`0.5.9`](./youtube-js) - Truffle fork of [Youtube.js](https://github.com/LuanRT/YouTube.js)
[@truffle/route-installer@`0.5.7`](./route-installer) - Provides an action that allows packages to add their routes into other packages.
[@truffle/functions@`0.0.4`](./functions) - Utilities for creating Truffle Edge Functions

**Examples**
[@truffle/spotify-integration@`3.0.1`](./examples/spotify-integration) - Spotify Now Playing widget
[@truffle/create-react-project@`0.5.8`](./examples/create-react-project) - Truffle project React template
[@truffle/mashing-minigame@`0.2.12`](./examples/mashing-minigame) - Round-based minigame example
[@truffle/mutation-observer@`0.4.2`](./examples/mutation-observer) - Mutation Observer example
[@truffle/chants@`0.0.5`](./examples/chants) - Chants
[@truffle/mashing-minigame@`0.2.12`](./examples/mashing-minigame) - Round-based minigame example
[@truffle/spotify-integration@`3.0.1`](./examples/spotify-integration) - Spotify Now Playing widget
[@truffle/events-demo-backend@`0.0.12`](./examples/events-demo-backend) - [Events](../../events) demo
[@truffle/create-react-project@`0.5.8`](./examples/create-react-project) - Truffle project React template
[@dev/chessmaster@`0.6.3`](./examples/chessmaster) - A package to facilitate a streamer vs chat chess game using https://lichess.org.
[@truffle/demo-discord-bot@`0.0.1`](./examples/discord-bot-demo) - Discord bot using Truffle API
[@truffle/viewer-polls@`0.2.4`](./examples/viewer-polls) - Stream Polls
[@truffle/song-suggestions@`0.0.24`](./examples/song-suggestions) - Song Suggestions Suite
[@truffle/demo-discord-bot@`0.0.1`](./examples/discord-bot-demo) - Discord bot using Truffle API
[@truffle/song-suggestions@`0.0.24`](./examples/song-suggestions) - Song Suggestions Suite
[@truffle/chants@`0.0.5`](./examples/chants) - Chants

**Stream Projects**
[@truffle/chat@`0.0.16`](./stream-projects/chat) - Chat client for 3rd party chats
[@truffle/notifications@`0.1.4`](./stream-projects/notifications) - Send notifications to your users when you go live.
[@truffle/do-something@`0.1.4`](./stream-projects/do-something) - Let your audience control you through collectibles!
[@truffle/raid@`1.0.4`](./stream-projects/raid) - Stream Raids
[@truffle/better-chat@`0.0.13`](./stream-projects/better-chat) - Youtube chat mutation observer
[@truffle/notifications@`0.1.2`](./stream-projects/notifications) - Send notifications to your users when you go live.
[@truffle/chat-theme@`0.0.2`](./stream-projects/chat-theme) - Theme for chat
[@truffle/chat@`0.0.16`](./stream-projects/chat) - Chat client for 3rd party chats
[@truffle/chat-theme@`0.0.3`](./stream-projects/chat-theme) - Theme for chat

<!-- END PACKAGES -->

Expand Down
1 change: 1 addition & 0 deletions route-installer/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
truffle.secret.*
3 changes: 3 additions & 0 deletions route-installer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# truffle-default-site

Requires Node >= 18
18 changes: 18 additions & 0 deletions route-installer/deno.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"tasks": {
"dev": "we'll add as soon as deno is ready for us :)"
},
"compilerOptions": {
"jsx": "react-jsxdev",
"jsxImportSource": "react",
"lib": [
"deno.ns",
"dom"
]
},
"fmt": {
"options": {
"lineWidth": 100
}
}
}
24 changes: 24 additions & 0 deletions route-installer/deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions route-installer/deps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export {
makeResp,
serveTruffleEdgeFunction,
MyceliumClient,
gql,
} from "https://tfl.dev/@truffle/functions@~0.0.4/mod.ts";
59 changes: 59 additions & 0 deletions route-installer/functions/install-routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { makeResp, serveTruffleEdgeFunction } from "../deps.ts";
import { getModulesByPackageVersionId } from "./util/modules.ts";
import { getPackageByPath } from "./util/package.ts";
import { saveRoute } from "./util/route.ts";

interface InstallRouteRuntimeData {
packagePath: string;
}

serveTruffleEdgeFunction<InstallRouteRuntimeData>(
async ({ myceliumClient, runtimeData }) => {
// get the package version id
const packagePath = runtimeData?.packagePath;
if (!packagePath) {
return makeResp(400, {
error: true,
message: "Please specify packagePath in the runtimeData.",
});
}
const pkg = await getPackageByPath(packagePath, myceliumClient);
if (!pkg) {
return makeResp(404, {
error: true,
message: "Could not find package with specified slug.",
});
}

const packageVersionId = pkg.latestPackageVersionId;

// query for the modules
const modules = await getModulesByPackageVersionId(
packageVersionId,
myceliumClient
);

// console.log({ modules });

// for each module, check if it has a ROUTE_INSTALL_PATH export;
// if it does, upsert a route
for (const module of modules) {
const filename = module.filename;
const filenameParts = filename.split("/");
const isLayoutFile = filename.indexOf("layout.tsx") !== -1;
if (filenameParts[1] === "routes" && !isLayoutFile) {
console.log("saving route", module);
await saveRoute({
filenameParts: filenameParts.slice(1),
module,
otherModules: modules,
// FIXME this is the wrong packageVersionId... it needs to be the packageVersionId of the package that we're installing into
packageVersionId,
myceliumClient,
});
}
}

return makeResp(200, { message: "success" });
}
);
31 changes: 31 additions & 0 deletions route-installer/functions/util/graphql-client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const MYCELIUM_API_URL = "https://mycelium.truffle.vip/graphql";

interface MyceliumOptions {
accessToken: string;
orgId: string;
}

export interface GQLResponse<T = unknown> {
data: T;
errors: unknown[];
}

export function graphqlReq(
query: string,
variables: Record<string, unknown>,
options: MyceliumOptions
) {
return fetch(MYCELIUM_API_URL, {
method: "POST",
body: JSON.stringify({ query, variables }),
headers: {
"Content-Type": "application/json",
"x-org-id": options.orgId,
"x-access-token": options.accessToken,
},
});
}

export function gql(strings: TemplateStringsArray, ..._values: string[]) {
return strings.join();
}
8 changes: 8 additions & 0 deletions route-installer/functions/util/make-resp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export function makeResp(statusCode: number, body: unknown) {
return new Response(JSON.stringify(body), {
status: statusCode,
headers: {
"Content-Type": "application/json",
},
});
}
49 changes: 49 additions & 0 deletions route-installer/functions/util/modules.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { MyceliumClient, gql } from "../../deps.ts";

export interface Module {
id: string;
filename: string;
exports: {
name: string;
type: string;
componentRel: {
id: string;
};
}[];
}

interface ModuleConnection {
nodes: Module[];
}

const MODULE_CONNECTION_QUERY = gql`
query ($packageVersionId: ID!) {
moduleConnection(input: { packageVersionId: $packageVersionId }) {
nodes {
id
filename
exports {
name
type
componentRel {
id
}
}
}
}
}
`;

export async function getModulesByPackageVersionId(
packageVersionId: string,
myceliumClient: MyceliumClient
) {
return (
await myceliumClient.query<{ moduleConnection: ModuleConnection }>(
MODULE_CONNECTION_QUERY,
{
packageVersionId,
}
)
)?.moduleConnection?.nodes;
}
24 changes: 24 additions & 0 deletions route-installer/functions/util/package.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { MyceliumClient, gql } from "../../deps.ts";

interface Package {
id: string;
latestPackageVersionId: string;
}

const PACKAGE_QUERY = gql`
query ($path: String!) {
package(input: { path: $path }) {
id
latestPackageVersionId
}
}
`;

export async function getPackageByPath(
path: string,
myceliumClient: MyceliumClient
) {
return (
await myceliumClient.query<{ package: Package }>(PACKAGE_QUERY, { path })
)?.package;
}
Loading