diff --git a/Makefile b/Makefile index 4c6f93b9d..d05d08bfc 100644 --- a/Makefile +++ b/Makefile @@ -77,7 +77,6 @@ deploy: @echo "Deploy..." aws s3 sync --region eu-west-2 --cache-control "public, max-age=31536000, immutable" --exclude '.DS_Store' --exclude '*' --include '*.webp' --content-type 'image/webp' ./dist/docs/_astro s3://www.surrealdb.com/docs/_astro/ aws s3 sync --region eu-west-2 --cache-control "public, max-age=31536000, immutable" --exclude '.DS_Store' --exclude '*.webp' ./dist/docs/_astro s3://www.surrealdb.com/docs/_astro/ - aws s3 sync --region eu-west-2 --cache-control "public, max-age=86400" --exclude '.DS_Store' ./dist/docs/~partytown s3://www.surrealdb.com/docs/~partytown/ aws s3 sync --region eu-west-2 --cache-control "public, max-age=30" --delete --exclude '*' --include '*.html' ./dist/docs/ s3://www.surrealdb.com/docs/ .PHONY: stage @@ -85,5 +84,4 @@ stage: @echo "Stage..." aws s3 sync --region eu-west-2 --cache-control "public, max-age=31536000, immutable" --exclude '.DS_Store' --exclude '*' --include '*.webp' --content-type 'image/webp' ./dist/docs/_astro s3://www.surrealdb.dev/docs/_astro/ aws s3 sync --region eu-west-2 --cache-control "public, max-age=31536000, immutable" --exclude '.DS_Store' --exclude '*.webp' ./dist/docs/_astro s3://www.surrealdb.dev/docs/_astro/ - aws s3 sync --region eu-west-2 --cache-control "public, max-age=86400" --exclude '.DS_Store' ./dist/docs/~partytown s3://www.surrealdb.dev/docs/~partytown/ aws s3 sync --region eu-west-2 --cache-control "public, max-age=30" --delete --exclude '*' --include '*.html' ./dist/docs/ s3://www.surrealdb.dev/docs/ diff --git a/astro.config.mjs b/astro.config.mjs index 2c172b5b9..3263f8e9a 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -1,5 +1,4 @@ import mdx from '@astrojs/mdx'; -import partytown from '@astrojs/partytown'; import solidJs from '@astrojs/solid-js'; import tailwind from '@astrojs/tailwind'; import compress from 'astro-compress'; @@ -32,7 +31,6 @@ export default defineConfig({ tailwind({ nesting: true, }), - partytown(), compress({ Image: false, }), diff --git a/aws/viewer-request/index.js b/aws/viewer-request/index.js index d270a32cc..9d27c2262 100644 --- a/aws/viewer-request/index.js +++ b/aws/viewer-request/index.js @@ -244,6 +244,7 @@ function handler(event) { case 'surrealql': case 'sdk': case 'tutorials': + case 'cloud': case undefined: break; default: @@ -256,4 +257,4 @@ function handler(event) { return request; -} \ No newline at end of file +} diff --git a/bun.lockb b/bun.lockb index 21293ac5e..0325a2426 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index cbd9244c0..3dce2f932 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,6 @@ "unist-util-visit": "^5.0.0" }, "devDependencies": { - "@astrojs/partytown": "^2.1.2", "@biomejs/biome": "1.8.3", "astro-compress": "^2.3.5", "esbuild": "^0.23.1", diff --git a/scripts/post-build.ts b/scripts/post-build.ts index 9a477285c..8d5bbdbcf 100644 --- a/scripts/post-build.ts +++ b/scripts/post-build.ts @@ -15,8 +15,132 @@ const scripts = [ 'https://static.ads-twitter.com/uwt.js', ]; -await extractInlineResources(); +await checkBrokenLinks(); await fetchRemoteResources(); +await extractInlineResources(); + +async function checkBrokenLinks() { + const broken: string[] = []; + const files = await glob('**/*.html', { + cwd: __dist, + dot: true, + absolute: true, + filesOnly: true, + }); + + const websiteCache = new Map(); + const self = ['https://surrealdb.com', 'https://www.surrealdb.com']; + + for (const file of files) { + let loggedFile = false; + const raw = fs.readFileSync(file, { encoding: 'utf-8' }); + const parsed = parseHTML(raw, { + comment: true, + }); + + const links = parsed.querySelectorAll('a'); + for (const link of links) { + let href = link.getAttribute('href'); + if (!href) { + continue; + } + + let hasIssue = false; + function issue(issue: string) { + if (!href) { + return; + } + + if (!broken.includes(href)) { + broken.push(href); + } + + if (!hasIssue && !loggedFile) { + console.error(`\n[ERROR] In file: ${file}`); + loggedFile = true; + } + + hasIssue = true; + console.error(`[ERROR] ${issue}`); + } + + for (const domain of self) { + if (href.startsWith(domain)) { + issue(`External link should be local: ${href}`); + href = href.slice(domain.length); + break; + } + } + + if (href.startsWith('/')) { + href = href.split('#')[0]; + href = href.split('?')[0]; + + let exists = false; + + switch (true) { + case href === '/docs': + case href.startsWith('/docs/'): { + exists = fs.existsSync( + path.join(__root, 'dist', href, 'index.html') + ); + break; + } + + default: { + if (!websiteCache.has(href)) { + const res = await fetch( + `https://surrealdb.com${href}`, + { + redirect: 'manual', + } + ); + websiteCache.set(href, res.ok); + } + + const res = websiteCache.get(href); + if (res === undefined) { + throw new Error(`Cache miss for ${href}`); + } + + exists = res; + break; + } + } + + if (!exists) { + issue(`Broken link: ${href}`); + } + } + + if (hasIssue) { + let elemStr = link.toString(); + if (elemStr.length > 100) { + elemStr = `${elemStr.slice(0, 97)}...`; + } + + console.error(`[ERROR] For element: ${elemStr}`); + } + } + } + + if (broken.length > 0) { + console.error('\n============================================='); + console.error('\n[ERROR] Broken links found.'); + console.error( + '[ERROR] Possible issues include dead links, redirected links, or external links that should be local.' + ); + console.error('[ERROR] Check the above logs for more in-depth details'); + console.error("[ERROR] Here's the list: \n"); + for (const link of broken) { + console.error(`[ERROR] Broken link: ${link}`); + } + + console.error('\n'); + + throw new Error('Broken links found'); + } +} async function fetchRemoteResources() { // Fetch the remote scripts @@ -28,12 +152,20 @@ async function fetchRemoteResources() { fs.writeFileSync(path.join(__astro, name), await minifyJS(content)); // Scan the JS files in the dist folder console.log('[EXTRACT] Scanning JS files in dist/docs/ folder'); - const files = await glob('**/*.js', { - cwd: __dist, - dot: true, - absolute: true, - filesOnly: true, - }); + const files = [ + ...(await glob('**/*.js', { + cwd: __dist, + dot: true, + absolute: true, + filesOnly: true, + })), + ...(await glob('**/*.html', { + cwd: __dist, + dot: true, + absolute: true, + filesOnly: true, + })), + ]; // Loop over each file and process the content console.log(`[EXTRACT] Found ${files.length} JS files`); for (const file of files) { diff --git a/src/assets/img/image/cloud/cloud-architecture-dark.png b/src/assets/img/image/cloud/cloud-architecture-dark.png new file mode 100644 index 000000000..5515dba48 Binary files /dev/null and b/src/assets/img/image/cloud/cloud-architecture-dark.png differ diff --git a/src/assets/img/image/cloud/cloud-dark.png b/src/assets/img/image/cloud/cloud-dark.png new file mode 100644 index 000000000..d970bda12 Binary files /dev/null and b/src/assets/img/image/cloud/cloud-dark.png differ diff --git a/src/assets/img/image/cloud/configure-dark.png b/src/assets/img/image/cloud/configure-dark.png new file mode 100644 index 000000000..14adaba0e Binary files /dev/null and b/src/assets/img/image/cloud/configure-dark.png differ diff --git a/src/assets/img/image/cloud/create-instance.png b/src/assets/img/image/cloud/create-instance.png new file mode 100644 index 000000000..5de21d86e Binary files /dev/null and b/src/assets/img/image/cloud/create-instance.png differ diff --git a/src/assets/img/image/cloud/create-root-user.png b/src/assets/img/image/cloud/create-root-user.png new file mode 100644 index 000000000..993a65b8a Binary files /dev/null and b/src/assets/img/image/cloud/create-root-user.png differ diff --git a/src/assets/img/image/cloud/highly-available-and-scalable-dark.png b/src/assets/img/image/cloud/highly-available-and-scalable-dark.png new file mode 100644 index 000000000..52f7bc1de Binary files /dev/null and b/src/assets/img/image/cloud/highly-available-and-scalable-dark.png differ diff --git a/src/assets/img/image/cloud/instance-capabilities.png b/src/assets/img/image/cloud/instance-capabilities.png new file mode 100644 index 000000000..c57766cd6 Binary files /dev/null and b/src/assets/img/image/cloud/instance-capabilities.png differ diff --git a/src/assets/img/image/cloud/light/cloud-architecture-light.png b/src/assets/img/image/cloud/light/cloud-architecture-light.png new file mode 100644 index 000000000..d81d3bcea Binary files /dev/null and b/src/assets/img/image/cloud/light/cloud-architecture-light.png differ diff --git a/src/assets/img/image/cloud/light/cloud-light.png b/src/assets/img/image/cloud/light/cloud-light.png new file mode 100644 index 000000000..84fd5da23 Binary files /dev/null and b/src/assets/img/image/cloud/light/cloud-light.png differ diff --git a/src/assets/img/image/cloud/light/highly-available-and-scalable-light.png b/src/assets/img/image/cloud/light/highly-available-and-scalable-light.png new file mode 100644 index 000000000..204eb2c9e Binary files /dev/null and b/src/assets/img/image/cloud/light/highly-available-and-scalable-light.png differ diff --git a/src/assets/img/image/cloud/namespace-database.png b/src/assets/img/image/cloud/namespace-database.png new file mode 100644 index 000000000..5a8c3dc30 Binary files /dev/null and b/src/assets/img/image/cloud/namespace-database.png differ diff --git a/src/assets/img/image/cloud/open-in-cli.png b/src/assets/img/image/cloud/open-in-cli.png new file mode 100644 index 000000000..9e80d5f67 Binary files /dev/null and b/src/assets/img/image/cloud/open-in-cli.png differ diff --git a/src/assets/img/image/cloud/open-in-http.png b/src/assets/img/image/cloud/open-in-http.png new file mode 100644 index 000000000..2dff7609a Binary files /dev/null and b/src/assets/img/image/cloud/open-in-http.png differ diff --git a/src/assets/img/image/cloud/open-in-sdk.png b/src/assets/img/image/cloud/open-in-sdk.png new file mode 100644 index 000000000..ee5239edb Binary files /dev/null and b/src/assets/img/image/cloud/open-in-sdk.png differ diff --git a/src/assets/img/image/cloud/open-in-surrealist.png b/src/assets/img/image/cloud/open-in-surrealist.png new file mode 100644 index 000000000..7c5bedc7f Binary files /dev/null and b/src/assets/img/image/cloud/open-in-surrealist.png differ diff --git a/src/assets/img/image/cloud/querying-instance.png b/src/assets/img/image/cloud/querying-instance.png new file mode 100644 index 000000000..c40027cf7 Binary files /dev/null and b/src/assets/img/image/cloud/querying-instance.png differ diff --git a/src/assets/img/image/cloud/surreal-sidekick.png b/src/assets/img/image/cloud/surreal-sidekick.png new file mode 100644 index 000000000..eeb6c07a6 Binary files /dev/null and b/src/assets/img/image/cloud/surreal-sidekick.png differ diff --git a/src/assets/img/image/cloud/surrealcloud.png b/src/assets/img/image/cloud/surrealcloud.png new file mode 100644 index 000000000..5194bb1cb Binary files /dev/null and b/src/assets/img/image/cloud/surrealcloud.png differ diff --git a/src/assets/img/image/cloud/update-billing.png b/src/assets/img/image/cloud/update-billing.png new file mode 100644 index 000000000..31677e1a5 Binary files /dev/null and b/src/assets/img/image/cloud/update-billing.png differ diff --git a/src/components/RenderDoc.astro b/src/components/RenderDoc.astro index d2110930a..25356fbf3 100644 --- a/src/components/RenderDoc.astro +++ b/src/components/RenderDoc.astro @@ -4,7 +4,12 @@ import { getEntry } from 'astro:content'; import type { CollectionKey } from 'astro:content'; import { PageHeadings } from '@components/PageHeadings.tsx'; import Sidebar from '@components/Sidebar/index.astro'; -import { generateBreadcrumb, generateSidebar } from '@src/util/doc'; +import { + findNextPage, + findPreviousPage, + generateBreadcrumb, + generateSidebar, +} from '@src/util/doc'; import { Icon } from 'astro-icon/components'; import BaseLayout from './layout/BaseLayout.astro'; import MarkdownContainer from './shared/MarkdownContainer.astro'; @@ -31,8 +36,9 @@ if (!entry) { const { Content, headings } = await entry.render(); const sidebarItems = await generateSidebar(collection); const sidebarIndex = sidebarItems.flat.findIndex((item) => item.slug === slug); -const prev = sidebarItems.flat.at(sidebarIndex - 1); -const next = sidebarItems.flat.at(sidebarIndex + 1) ?? sidebarItems.flat[0]; +const prev = findPreviousPage(sidebarItems.flat, sidebarIndex); +const next = + findNextPage(sidebarItems.flat, sidebarIndex) ?? sidebarItems.flat[0]; function filteredHeadings() { if ( diff --git a/src/components/Sidebar/metadata.ts b/src/components/Sidebar/metadata.ts index 9ebccf55e..4b2a60ab9 100644 --- a/src/components/Sidebar/metadata.ts +++ b/src/components/Sidebar/metadata.ts @@ -21,6 +21,8 @@ import LightSurrealDB from '@img/icon/light/surrealdb.png'; import LightSurrealist from '@img/icon/light/surrealdb.png'; import LightSurrealML from '@img/icon/light/surrealml.png'; import LightSurrealQL from '@img/icon/light/surrealql.png'; +import LightCloud from '@img/image/cloud/surrealcloud.png'; +import DarkCloud from '@img/image/cloud/surrealcloud.png'; import DarkSurrealDB from '@img/icon/dark/surrealdb.png'; import DarkSurrealist from '@img/icon/dark/surrealist.png'; @@ -127,6 +129,17 @@ export const metadata = { href: 'https://github.com/surrealdb/surrealdb', }, }, + 'doc-cloud': { + title: 'Surreal Cloud (Beta)', + icon: { + light: LightCloud, + dark: DarkCloud, + }, + repo: { + title: 'Forum', + href: '/community', + }, + }, 'doc-surrealist': { title: 'Surrealist', icon: { diff --git a/src/components/layout/Analytics.astro b/src/components/layout/Analytics.astro index e981d5fb7..7dd3da029 100644 --- a/src/components/layout/Analytics.astro +++ b/src/components/layout/Analytics.astro @@ -9,22 +9,6 @@ - -