Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
pmelab committed Jun 13, 2024
1 parent 5cd2b89 commit f998d89
Show file tree
Hide file tree
Showing 68 changed files with 1,387 additions and 135 deletions.
1 change: 1 addition & 0 deletions .pnpmfile.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ function readPackage(pkg) {
'react-dom': '19.0.0-rc.0',
'@types/react': '18.3.3',
'@types/react-dom': '18.3.0',
'react-server-dom-webpack': '19.0.0-rc.0',
graphql: '16.8.1',
};
for (const type of ['dependencies', 'devDependencies', 'peerDependencies']) {
Expand Down
7 changes: 7 additions & 0 deletions apps/website/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Local Netlify folder
.netlify
.cache
.turbo
dist
styles.css
persisted-store
2 changes: 1 addition & 1 deletion apps/website/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
.netlify
.cache
.turbo
public
dist
styles.css
persisted-store
2 changes: 1 addition & 1 deletion apps/website/has-drupal.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import pkgJson from './package.json';
import pkgJson from './package.json' assert { type: 'json' };

if (pkgJson.dependencies['@custom/cms']) {
process.exit(0);
Expand Down
13 changes: 9 additions & 4 deletions apps/website/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{
"name": "@custom/website",
"private": true,
"type": "module",
"dependencies": {
"@amazeelabs/bridge-waku": "workspace:*",
"@amazeelabs/decap-cms-backend-token-auth": "^1.1.7",
"@amazeelabs/publisher": "^2.4.30",
"@amazeelabs/strangler-netlify": "^1.1.9",
Expand All @@ -11,8 +13,11 @@
"@custom/schema": "workspace:*",
"@custom/ui": "workspace:*",
"netlify-cli": "^17.21.1",
"react": "^18.2.0",
"react-dom": "^18.2.0"
"react": "19.0.0-rc.0",
"react-dom": "19.0.0-rc.0",
"react-error-boundary": "^4.0.13",
"react-server-dom-webpack": "19.0.0-rc.0",
"waku": "0.21.0-alpha.2"
},
"devDependencies": {
"@netlify/edge-functions": "^2.3.1",
Expand All @@ -28,10 +33,10 @@
"full-rebuild": "pnpm clean && pnpm build:waku",
"start:drupal": "pnpm run --filter @custom/cms start",
"build:drupal": "CLOUDINARY_CLOUDNAME=test pnpm start-test start:drupal 8888 build:waku",
"build:waku": "exit 0",
"build:waku": "waku build",
"build": "if node has-drupal.mjs; then pnpm build:drupal; else pnpm build:waku; fi",
"start": "publisher",
"serve": "netlify dev --cwd=. --dir=public --port=8000",
"serve": "netlify dev --cwd=. --dir=dist/public --port=8000",
"dev": "pnpm clean && publisher",
"open": "open http://127.0.0.1:8000/___status/"
}
Expand Down
1 change: 1 addition & 0 deletions apps/website/src/bridge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from '@amazeelabs/bridge-waku';
20 changes: 20 additions & 0 deletions apps/website/src/broken-link-handler.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use client';
import React, { PropsWithChildren } from 'react';
import { ErrorBoundary } from 'react-error-boundary';

export function BrokenLinkHandler({ children }: PropsWithChildren) {
return (
<ErrorBoundary
onError={(error) => {
if ((error as any).statusCode === 404) {
window.location.reload();
} else {
console.error(error);
}
}}
fallback={<h1>Something went wrong.</h1>}
>
{children}
</ErrorBoundary>
);
}
74 changes: 74 additions & 0 deletions apps/website/src/drupal-executor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import {
AnyOperationId,
OperationExecutor,
OperationVariables,
} from '@custom/schema';
import React, { PropsWithChildren } from 'react';

/**
* Create an executor that operates against a Drupal endpoint.
*/
function drupalExecutor(endpoint: string, forward: boolean = true) {
return async function <OperationId extends AnyOperationId>(
id: OperationId,
variables?: OperationVariables<OperationId>,
) {
const url = new URL(endpoint);
const isMutation = id.includes('Mutation:');
if (isMutation) {
const { data, errors } = await (
await fetch(url, {
method: 'POST',
credentials: 'include',
body: JSON.stringify({
queryId: id,
variables: variables || {},
}),
headers: forward
? {
'SLB-Forwarded-Proto': window.location.protocol.slice(0, -1),
'SLB-Forwarded-Host': window.location.hostname,
'SLB-Forwarded-Port': window.location.port,
'Content-Type': 'application/json',
}
: {
'Content-Type': 'application/json',
},
})
).json();
if (errors) {
throw errors;
}
return data;
} else {
url.searchParams.set('queryId', id);
url.searchParams.set('variables', JSON.stringify(variables || {}));
const { data, errors } = await (
await fetch(url, {
credentials: 'include',
headers: forward
? {
'SLB-Forwarded-Proto': window.location.protocol.slice(0, -1),
'SLB-Forwarded-Host': window.location.hostname,
'SLB-Forwarded-Port': window.location.port,
}
: {},
})
).json();
if (errors) {
throw errors;
}
return data;
}
};
}

export function DrupalExecutor({ children }: PropsWithChildren) {
return (
<OperationExecutor
executor={drupalExecutor('http://localhost:8888/graphql', false)}
>
{children}
</OperationExecutor>
);
}
91 changes: 91 additions & 0 deletions apps/website/src/entries.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import '@custom/ui/styles.css';

import {
AnyOperationId,
ListPagesQuery,
Locale,
LocationProvider,
OperationResult,
OperationVariables,
} from '@custom/schema';
import { Frame } from '@custom/ui/routes/Frame';
import { HomePage } from '@custom/ui/routes/HomePage';
import { NotFoundPage } from '@custom/ui/routes/NotFoundPage';
import { Page } from '@custom/ui/routes/Page';
import React from 'react';
import { createPages } from 'waku';

import { BrokenLinkHandler } from './broken-link-handler.js';
import { ExecutorsClient } from './executors-client.js';
import { ExecutorsServer } from './executors-server.js';

async function query<TOperation extends AnyOperationId>(
operation: TOperation,
variables: OperationVariables<TOperation>,
) {
const url = new URL('http://localhost:8888/graphql');
url.searchParams.set('queryId', operation);
url.searchParams.set('variables', JSON.stringify(variables || {}));
const { data, errors } = await (await fetch(url)).json();
if (errors) {
throw errors;
}
return data as OperationResult<TOperation>;
}

export default createPages(async ({ createPage, createLayout }) => {
createLayout({
render: 'static',
path: '/',
component: ({ children, path }) => (
<BrokenLinkHandler>
<LocationProvider
currentLocation={{
pathname: path,
searchParams: new URLSearchParams(),
search: '',
hash: '',
}}
>
<ExecutorsServer>
<ExecutorsClient>
<Frame>{children}</Frame>
</ExecutorsClient>
</ExecutorsServer>
</LocationProvider>
</BrokenLinkHandler>
),
});

Object.values(Locale).forEach((lang) => {
createPage({
render: 'static',
path: `/${lang}`,
component: HomePage,
});
});

createPage({
render: 'static',
path: '/404',
component: NotFoundPage,
});

// TODO: Paginate properly to not load all nodes in Drupal
const pagePaths = new Set<string>();
const pages = await query(ListPagesQuery, { args: 'pageSize=0&page=1' });
pages.ssgPages?.rows.forEach((page) => {
page?.translations?.forEach((translation) => {
if (translation?.path) {
pagePaths.add(translation.path);
}
});
});

createPage({
render: 'static',
path: '/[...path]',
staticPaths: [...pagePaths].map((path) => path.substring(1).split('/')),
component: Page,
});
});
8 changes: 8 additions & 0 deletions apps/website/src/executors-client.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use client';
import React, { PropsWithChildren } from 'react';

import { DrupalExecutor } from './drupal-executor.js';

export function ExecutorsClient({ children }: PropsWithChildren) {
return <DrupalExecutor>{children}</DrupalExecutor>;
}
7 changes: 7 additions & 0 deletions apps/website/src/executors-server.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React, { PropsWithChildren } from 'react';

import { DrupalExecutor } from './drupal-executor.js';

export function ExecutorsServer({ children }: PropsWithChildren) {
return <DrupalExecutor>{children}</DrupalExecutor>;
}
15 changes: 15 additions & 0 deletions apps/website/src/main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React, { StrictMode } from 'react';
import { createRoot, hydrateRoot } from 'react-dom/client';
import { Router } from 'waku/router/client';

const rootElement = (
<StrictMode>
<Router />
</StrictMode>
);

if (document.body.dataset.hydrate) {
hydrateRoot(document.body, rootElement);
} else {
createRoot(document.body).render(rootElement);
}
4 changes: 2 additions & 2 deletions apps/website/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "Node",
"moduleResolution": "Node16",
"resolveJsonModule": true,
"isolatedModules": true,
"checkJs": true,
"jsx": "react"
},
"exclude": ["netlify", "node_modules", "public"]
"exclude": ["netlify", "node_modules", "public", "dist"]
}
7 changes: 7 additions & 0 deletions apps/website/vite.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default {
resolve: {
alias: {
'@amazeelabs/bridge': './src/bridge.tsx',
},
},
};
57 changes: 57 additions & 0 deletions packages/bridge-waku/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"$schema": "https://json.schemastore.org/eslintrc.json",
"root": true,
"settings": {
"react": {
"version": "18"
}
},
"env": {
"browser": true,
"es6": true,
"node": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:promise/recommended",
"plugin:react/recommended",
"prettier"
],
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"plugins": [
"@typescript-eslint",
"promise",
"simple-import-sort",
"import",
"no-only-tests",
"react",
"react-hooks"
],
"rules": {
"no-unused-vars": ["off"],
"@typescript-eslint/no-unused-vars": ["error"],
"simple-import-sort/imports": "error",
"sort-imports": "off",
"import/first": "error",
"import/newline-after-import": "error",
"import/no-duplicates": "error",
"no-only-tests/no-only-tests": "error",
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
"react/prop-types": ["off"],
"react/prefer-stateless-function": ["error"],
"react/react-in-jsx-scope": ["off"]
}
}
1 change: 1 addition & 0 deletions packages/bridge-waku/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build
4 changes: 4 additions & 0 deletions packages/bridge-waku/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
**
!build/*
!CHANGELOG.md
!README.md
1 change: 1 addition & 0 deletions packages/bridge-waku/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"@amazeelabs/prettier-config"
Loading

0 comments on commit f998d89

Please sign in to comment.