diff --git a/.gitignore b/.gitignore
index 9266bf1d..eb3eae65 100644
--- a/.gitignore
+++ b/.gitignore
@@ -45,3 +45,4 @@ yarn.lock
public/robots.txt
public/sitemap.xml
public/sitemap-*.xml
+api.json
\ No newline at end of file
diff --git a/docs/articles/key-value-store.md b/docs/articles/key-value-store.md
deleted file mode 100644
index 340deebe..00000000
--- a/docs/articles/key-value-store.md
+++ /dev/null
@@ -1,57 +0,0 @@
----
-title: Key Value Store
-sidebar_label: Key Value Store
----
-
-Zuplo has a globally distributed key-value store called `KeyValueStore`. When
-running in developer mode (e.g. in the portal at portal.zuplo.com) your cache
-will reset with each build. When running in production mode at the edge the
-cache will support edge distribution - it can take up to ~1 minute for writes to
-sync across all nodes globally (though is usually much quicker).
-
-
-
-## Example
-
-```ts
-import { ZuploContext, ZuploRequest, KeyValueStore } from "@zuplo/runtime";
-
-export async function setCache(request: ZuploRequest, context: ZuploContext) {
- const cache = new KeyValueStore(context);
- // This cache entry will expire in 60s
- await cache.put("string-key", "some-value", { expirationSecondsTtl: 60 });
- return "OK";
-}
-
-export async function getCache(request: ZuploRequest, context: ZuploContext) {
- const cache = new KeyValueStore(context);
- const value = await cache.get("string-key");
- return value;
-}
-```
-
-## Constructing the KeyValueStore
-
-```ts
-// This creates a new instance of the KeyValueStore. This should be performed inside the lifecycle of a request (it's an inexpensive operation that just creates a reference to the real store)
-const cache = new KeyValueStore(context);
-```
-
-## Writing to the KeyValueStore
-
-```ts
-// This cache entry will expire in 60s
-await cache.put("string-key", "some-value", { expirationSecondsTtl: 60 });
-```
-
-## Reading from the KeyValueStore
-
-```ts
-const data = await cache.get("string-key");
-```
-
-## Deleting from the KeyValueStore
-
-```ts
-await cache.delete("string-key");
-```
diff --git a/docs/articles/policies.md b/docs/articles/policies.md
index d6d21988..0520e1d4 100644
--- a/docs/articles/policies.md
+++ b/docs/articles/policies.md
@@ -1,5 +1,5 @@
---
-title: Policies
+title: Policy Fundamentals
---
Policies are modules that can intercept an incoming request. You can have
diff --git a/package.json b/package.json
index 7998ffab..2807c7c4 100644
--- a/package.json
+++ b/package.json
@@ -14,9 +14,10 @@
"build": "zudoku build",
"format": "prettier --write .",
"typecheck": "tsc",
- "postinstall": "npm run policies:get && npm run policies:generate && npm run errors:generate",
+ "postinstall": "npm run policies:get && npm run policies:generate && npm run errors:generate && npm run api:get",
"policies:get": "sh ./scripts/get-policies.sh",
"policies:generate": "tsx scripts/generate-policies.ts",
+ "api:get": "curl -o ./api.json https://dev.zuplo.com/openapi",
"errors:generate": "tsx scripts/generate-errors.ts"
},
"dependencies": {
diff --git a/scripts/generate-policies.ts b/scripts/generate-policies.ts
index b018dbfd..ad1ea1fa 100644
--- a/scripts/generate-policies.ts
+++ b/scripts/generate-policies.ts
@@ -1,8 +1,8 @@
+import { glob } from "glob";
+import type { JSONSchema7, JSONSchema7Definition } from "json-schema";
import fs from "node:fs/promises";
import path from "node:path";
import prettier from "prettier";
-import { glob } from "glob";
-import type { JSONSchema7, JSONSchema7Definition } from "json-schema";
import { fixMarkdown } from "./fix-markdown.js";
const projectDir = path.join(import.meta.dirname, "..");
@@ -195,6 +195,10 @@ Read more about [how policies work](/articles/policies)
}
const policyIndex = `
+---
+title: Policy Catalog
+---
+
{/* This file is auto-generated by generate-policies.ts. Do not edit manually! Re-run with \`generate:policies\` script. */}
Zuplo includes policies for any solution you need for securing and sharing your API. See the [policy introduction](/docs/articles/policies) to learn about using policies.
diff --git a/sidebar.ts b/sidebar.ts
index a4cbfcd4..7beec10f 100644
--- a/sidebar.ts
+++ b/sidebar.ts
@@ -1,7 +1,7 @@
import type { SidebarEntry } from "zudoku";
import { errors } from "./generated/errors";
-export const sidebar: SidebarEntry = [
+export const docs: SidebarEntry = [
{
type: "category",
label: "Introduction",
@@ -222,36 +222,6 @@ export const sidebar: SidebarEntry = [
"articles/convert-urls-to-openapi",
],
},
- {
- type: "category",
- label: "Programming API",
- items: [
- "articles/zuplo-request",
- "articles/zuplo-context",
- "articles/context-data",
- "articles/route-raw",
- "articles/background-loader",
- "articles/background-dispatcher",
- "articles/web-standard-apis",
- "articles/web-crypto-apis",
- "articles/cache",
- "articles/node-modules",
- "articles/http-problems",
- "articles/reusing-code",
- "articles/zone-cache",
- "articles/key-value-store",
- "articles/zuplo-id-token",
- "articles/safely-clone-a-request-or-response",
- "articles/runtime-behaviors",
- "articles/zp-body-removed",
- "articles/audit-log",
- "articles/hooks",
- "articles/custom-cors-policy",
- "articles/runtime-extensions",
- "articles/not-found-handler",
- "articles/zuplo-json",
- ],
- },
{
type: "category",
label: "Zuplo CLI",
@@ -333,11 +303,6 @@ export const sidebar: SidebarEntry = [
type: "doc",
id: "articles/support",
},
- {
- type: "doc",
- id: "articles/developer-api",
- },
- "ask",
{
type: "link",
label: "Trust & Compliance",
@@ -352,12 +317,60 @@ export const sidebar: SidebarEntry = [
},
];
+export const programming: SidebarEntry = [
+ {
+ type: "category",
+ label: "Core Concepts",
+ items: [
+ "articles/zuplo-request",
+ "articles/zuplo-context",
+ "articles/web-standard-apis",
+ "articles/web-crypto-apis",
+ "articles/node-modules",
+
+ "articles/context-data",
+ "articles/route-raw",
+
+ "articles/reusing-code",
+
+ "articles/zuplo-id-token",
+ "articles/safely-clone-a-request-or-response",
+ "articles/runtime-behaviors",
+ "articles/zp-body-removed",
+ "articles/audit-log",
+
+ "articles/custom-cors-policy",
+
+ "articles/zuplo-json",
+ ],
+ },
+ {
+ type: "category",
+ label: "Error Handling",
+ items: ["articles/http-problems", "articles/not-found-handler"],
+ },
+ {
+ type: "category",
+ label: "Extensions & Hooks",
+ items: ["articles/hooks", "articles/runtime-extensions"],
+ },
+ {
+ type: "category",
+ label: "Cache & Data Loading",
+ items: [
+ "articles/cache",
+ "articles/zone-cache",
+ "articles/background-loader",
+ "articles/background-dispatcher",
+ ],
+ },
+];
+
export const policies: SidebarEntry = [
{
- type: "doc",
- // this file is auto-generated, see generate-policies.ts
- id: "policies/index",
+ type: "category",
label: "Overview",
+ items: ["policies/index", "articles/policies"],
},
{
type: "category",
diff --git a/src/PolicyOverview.tsx b/src/PolicyOverview.tsx
index 12467c78..3b332d18 100644
--- a/src/PolicyOverview.tsx
+++ b/src/PolicyOverview.tsx
@@ -1,4 +1,4 @@
-import React, { type CSSProperties } from "react";
+import { type CSSProperties } from "react";
import { Link } from "zudoku/components";
export const PolicyOverview = ({
@@ -19,12 +19,14 @@ export const PolicyOverview = ({
key={policy.policyId}
className="flex items-center gap-4 rounded-lg border border-border shadow-sm p-4 transition-colors hover:bg-accent md:h-36 md:flex-col md:justify-center md:px-5 md:py-6 md:text-center no-underline"
>
-
+
);
},
- BundlesTables: () => ,
+ BundlesTable: () => ,
};
const config: ZudokuConfig = {
@@ -89,21 +89,26 @@ const config: ZudokuConfig = {
id: "policies",
label: "Policies & Handlers",
},
+ {
+ id: "programming",
+ label: "Programming API",
+ },
{
id: "api",
- label: "API Reference",
+ label: "REST API",
},
],
sidebar: {
- docs: sidebar,
- policies: policies,
+ docs,
+ policies,
+ programming,
},
mdx: {
components: mdxComponents,
},
apis: {
- type: "url",
- input: "https://developer-api-main-5b4bb7c.d2.zuplo.dev/openapi",
+ type: "file",
+ input: "./api.json",
navigationId: "api",
},
docs: [