@lukoweb/apitogo 0.2.30 → 0.2.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/cli/cli.js +794 -248
  2. package/dist/declarations/app/entry.server.d.ts +2 -2
  3. package/dist/declarations/app/main.d.ts +3 -1
  4. package/dist/declarations/cli/platform/client/platform-api.d.ts +16 -5
  5. package/dist/declarations/cli/platform/helpers/deploy-artifact-hash.d.ts +1 -1
  6. package/dist/declarations/cli/platform/helpers/package-files.d.ts +1 -1
  7. package/dist/declarations/cli/platform/helpers/platform-plan.d.ts +1 -1
  8. package/dist/declarations/cli/platform/helpers/zip.d.ts +1 -1
  9. package/dist/declarations/cli/platform/tools/infrastructure.d.ts +0 -4
  10. package/dist/declarations/config/effective-redirects.d.ts +6 -0
  11. package/dist/declarations/config/header-navigation-guard.d.ts +2 -0
  12. package/dist/declarations/config/resolve-modules.d.ts +1 -4
  13. package/dist/declarations/config/validators/HeaderNavigationSchema.d.ts +1 -2
  14. package/docs/cli/commands.md +151 -75
  15. package/docs/cli/go-live.md +135 -123
  16. package/docs/cli/walkthrough.md +40 -1
  17. package/docs/configuration/gateway.md +52 -0
  18. package/docs/guides/customer-account.md +33 -2
  19. package/docs/mcp/tools.md +101 -102
  20. package/package.json +2 -1
  21. package/src/app/demo.tsx +78 -77
  22. package/src/app/entry.client.tsx +115 -107
  23. package/src/app/entry.server.tsx +164 -160
  24. package/src/app/main.tsx +175 -167
  25. package/src/app/standalone.tsx +61 -60
  26. package/src/config/effective-redirects.ts +31 -0
  27. package/src/config/header-navigation-guard.ts +13 -0
  28. package/src/config/resolve-modules.ts +331 -354
  29. package/src/config/v2/home-redirect.ts +104 -98
  30. package/src/config/v2/index.ts +127 -126
  31. package/src/config/v2/ledger.ts +242 -235
  32. package/src/config/v2/resolve.ts +12 -4
  33. package/src/config/v2/rules.ts +716 -714
  34. package/src/config/v2/services.ts +799 -663
  35. package/src/config/v2/workspace.ts +17 -1
  36. package/src/config/validators/HeaderNavigationSchema.ts +42 -44
  37. package/src/lib/assets/powered-by-icon.png +0 -0
  38. package/src/lib/authentication/providers/dev-portal-auth-pages.tsx +667 -602
  39. package/src/lib/authentication/providers/dev-portal.tsx +476 -448
  40. package/src/lib/components/HeaderNavigation.tsx +176 -176
  41. package/src/lib/components/MobileTopNavigation.tsx +283 -283
  42. package/src/lib/components/navigation/PoweredByZudoku.tsx +42 -39
  43. package/src/vite/plugin-offroot-resolve.ts +68 -67
  44. package/src/vite/prerender/prerender.ts +242 -242
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lukoweb/apitogo",
3
- "version": "0.2.30",
3
+ "version": "0.2.34",
4
4
  "type": "module",
5
5
  "sideEffects": [
6
6
  "**/*.css",
@@ -171,6 +171,7 @@
171
171
  "build": "esbuild src/cli/cli.ts src/vite/prerender/worker.ts --outdir=dist/cli --entry-names=[name] --bundle --format=esm --packages=external --target=node20 --platform=node --log-level=error",
172
172
  "postbuild": "tsx scripts/check-external-deps.ts",
173
173
  "typecheck": "tsc --project tsconfig.app.json --noEmit",
174
+ "test:e2e": "vitest run --config vitest.e2e.config.ts",
174
175
  "generate:types": "tsx scripts/generate-types.js && tsx scripts/generate-flat-config.js",
175
176
  "build:standalone": "vite build --mode standalone --config vite.standalone.config.ts --log-level=error",
176
177
  "prepack": "npm run build && tsx scripts/generate-publish-exports.ts",
package/src/app/demo.tsx CHANGED
@@ -1,77 +1,78 @@
1
- import logger from "loglevel";
2
- import { createRoot } from "react-dom/client";
3
- import { createBrowserRouter } from "react-router";
4
- import type { ZudokuConfig } from "../config/validators/ZudokuConfig.js";
5
- import { Bootstrap } from "../lib/components/Bootstrap.js";
6
- import DemoAnnouncement from "../lib/demo/DemoAnnouncement.js";
7
- import "../lib/util/logInit.js";
8
- import "./main.css";
9
- import { openApiPlugin } from "../lib/plugins/openapi/index.js";
10
- import { getRoutesByConfig } from "./main.js";
11
-
12
- const apiUrl = new URL(window.location.href).searchParams.get("api-url");
13
- const logoUrl = new URL(window.location.href).searchParams.get("logo-url");
14
- const logoWidth = new URL(window.location.href).searchParams.get("logo-width");
15
- const title =
16
- new URL(window.location.href).searchParams.get("title") ?? "Zudoku Demo";
17
-
18
- if (!apiUrl) {
19
- throw new Error(
20
- "No API URL in query parameters. Please provide an API URL using the `api-url` query parameter.",
21
- );
22
- }
23
-
24
- logger.info(`API URL: ${apiUrl}`);
25
-
26
- const root =
27
- document.getElementById("zudoku") ?? document.getElementById("root");
28
-
29
- if (!root) {
30
- throw new Error("No div found with id root");
31
- }
32
-
33
- // IMPORTANT: This component must not contain tailwind classes
34
- // This directory is not processed by the tailwind plugin
35
-
36
- const config: ZudokuConfig = {
37
- site: {
38
- title,
39
- banner: {
40
- message: <DemoAnnouncement />,
41
- },
42
- },
43
- navigation: [
44
- {
45
- type: "link",
46
- to: "/",
47
- label: "API Reference",
48
- },
49
- ],
50
- plugins: [
51
- // Using the plugin directly because there's no config file to load in the virtual plugins
52
- openApiPlugin({
53
- type: "url",
54
- input: apiUrl,
55
- path: "/",
56
- }),
57
- ],
58
- } satisfies ZudokuConfig;
59
-
60
- if (logoUrl && logoWidth) {
61
- config.site = {
62
- ...config.site,
63
- logo: {
64
- src: {
65
- light: logoUrl,
66
- dark: logoUrl,
67
- },
68
- width: logoWidth,
69
- },
70
- };
71
- }
72
-
73
- const routes = getRoutesByConfig(config);
74
- const router = createBrowserRouter(routes, {
75
- basename: window.location.pathname,
76
- });
77
- createRoot(root).render(<Bootstrap router={router} />);
1
+ import logger from "loglevel";
2
+ import { createRoot } from "react-dom/client";
3
+ import { createBrowserRouter } from "react-router";
4
+ import { resolveModulesConfig } from "../config/resolve-modules.js";
5
+ import type { ZudokuConfig } from "../config/validators/ZudokuConfig.js";
6
+ import { Bootstrap } from "../lib/components/Bootstrap.js";
7
+ import "../lib/util/logInit.js";
8
+ import "./main.css";
9
+ import DemoAnnouncement from "../lib/demo/DemoAnnouncement.js";
10
+ import { openApiPlugin } from "../lib/plugins/openapi/index.js";
11
+ import { getRoutesByConfig } from "./main.js";
12
+
13
+ const apiUrl = new URL(window.location.href).searchParams.get("api-url");
14
+ const logoUrl = new URL(window.location.href).searchParams.get("logo-url");
15
+ const logoWidth = new URL(window.location.href).searchParams.get("logo-width");
16
+ const title =
17
+ new URL(window.location.href).searchParams.get("title") ?? "Zudoku Demo";
18
+
19
+ if (!apiUrl) {
20
+ throw new Error(
21
+ "No API URL in query parameters. Please provide an API URL using the `api-url` query parameter.",
22
+ );
23
+ }
24
+
25
+ logger.info(`API URL: ${apiUrl}`);
26
+
27
+ const root =
28
+ document.getElementById("zudoku") ?? document.getElementById("root");
29
+
30
+ if (!root) {
31
+ throw new Error("No div found with id root");
32
+ }
33
+
34
+ // IMPORTANT: This component must not contain tailwind classes
35
+ // This directory is not processed by the tailwind plugin
36
+
37
+ const config: ZudokuConfig = {
38
+ site: {
39
+ title,
40
+ banner: {
41
+ message: <DemoAnnouncement />,
42
+ },
43
+ },
44
+ navigation: [
45
+ {
46
+ type: "link",
47
+ to: "/",
48
+ label: "API Reference",
49
+ },
50
+ ],
51
+ plugins: [
52
+ // Using the plugin directly because there's no config file to load in the virtual plugins
53
+ openApiPlugin({
54
+ type: "url",
55
+ input: apiUrl,
56
+ path: "/",
57
+ }),
58
+ ],
59
+ } satisfies ZudokuConfig;
60
+
61
+ if (logoUrl && logoWidth) {
62
+ config.site = {
63
+ ...config.site,
64
+ logo: {
65
+ src: {
66
+ light: logoUrl,
67
+ dark: logoUrl,
68
+ },
69
+ width: logoWidth,
70
+ },
71
+ };
72
+ }
73
+
74
+ const routes = getRoutesByConfig(config, resolveModulesConfig);
75
+ const router = createBrowserRouter(routes, {
76
+ basename: window.location.pathname,
77
+ });
78
+ createRoot(root).render(<Bootstrap router={router} />);
@@ -1,107 +1,115 @@
1
- import { createRoot, hydrateRoot } from "react-dom/client";
2
- import {
3
- createBrowserRouter,
4
- matchRoutes,
5
- type RouteObject,
6
- } from "react-router";
7
- import config from "virtual:zudoku-config";
8
- import "vite/modulepreload-polyfill";
9
- import { Bootstrap } from "../lib/components/Bootstrap.js";
10
- import { getRoutesByConfig, shikiReady } from "./main.js";
11
-
12
- const routes = getRoutesByConfig(config);
13
- // biome-ignore lint/style/noNonNullAssertion: We know the root element exists
14
- const root = document.getElementById("root")!;
15
-
16
- declare global {
17
- interface Window {
18
- ZUDOKU_VERSION: string;
19
- }
20
- }
21
-
22
- window.ZUDOKU_VERSION = process.env.ZUDOKU_VERSION ?? "unknown";
23
-
24
- if (process.env.SENTRY_DSN) {
25
- void import("./sentry.js").then((mod) => {
26
- mod.initSentry({ dsn: process.env.SENTRY_DSN as string });
27
- });
28
- }
29
-
30
- if (root.childElementCount > 0) {
31
- void hydrate(routes);
32
- } else {
33
- void render(routes);
34
- }
35
-
36
- if (import.meta.env.IS_ZUPLO) {
37
- // biome-ignore lint/suspicious/noConsole: Logging allowed here
38
- console.log(
39
- `%cPowered by Zuplo v${window.ZUDOKU_VERSION}`,
40
- [
41
- "color: #Df0097",
42
- "line-height: 50px",
43
- "font-weight: bolder",
44
- "font-size: 15px",
45
- "text-align: center",
46
- "letter-spacing: 5px",
47
- ].join(" ;"),
48
- );
49
- } else {
50
- // biome-ignore lint/suspicious/noConsole: Logging allowed here
51
- console.log(
52
- `%cAPITOGO v${window.ZUDOKU_VERSION}`,
53
- [
54
- "color: #0d9488",
55
- "line-height: 50px",
56
- "font-weight: bolder",
57
- "font-size: 15px",
58
- "text-align: center",
59
- "letter-spacing: 5px",
60
- ].join(" ;"),
61
- );
62
- // biome-ignore lint/suspicious/noConsole: Logging allowed here
63
- console.log("» Learn more at https://apitogo.com");
64
- }
65
-
66
- async function hydrateLazyRoutes(routes: RouteObject[]) {
67
- const path = window.location.pathname;
68
- const lazyMatches = matchRoutes(routes, path, config.basePath)?.filter(
69
- (m) => m.route.lazy,
70
- );
71
-
72
- if (lazyMatches?.length) {
73
- await Promise.all(
74
- lazyMatches.map(async (m) => {
75
- if (typeof m.route.lazy !== "function") return;
76
-
77
- const routeModule = await m.route.lazy();
78
- Object.assign(m.route, { ...routeModule, lazy: undefined });
79
- }),
80
- );
81
- }
82
- }
83
-
84
- function render(routes: RouteObject[]) {
85
- const router = createBrowserRouter(routes, {
86
- basename: config.basePath,
87
- });
88
- createRoot(root).render(<Bootstrap router={router} />);
89
- }
90
-
91
- async function hydrate(routes: RouteObject[]) {
92
- await Promise.all([hydrateLazyRoutes(routes), shikiReady]);
93
-
94
- const router = createBrowserRouter(routes, {
95
- basename: config.basePath,
96
- });
97
-
98
- hydrateRoot(root, <Bootstrap hydrate router={router} />);
99
- }
100
-
101
- // This is a workaround to avoid version skewing
102
- // See https://vite.dev/guide/build.html#load-error-handling
103
- // TODO: Implement a more advanced solution if there are CDN urls or e.g. Vercel Skew Protection
104
- window.addEventListener("vite:preloadError", (e) => {
105
- e.preventDefault();
106
- window.location.reload();
107
- });
1
+ import { createRoot, hydrateRoot } from "react-dom/client";
2
+ import {
3
+ createBrowserRouter,
4
+ matchRoutes,
5
+ type RouteObject,
6
+ } from "react-router";
7
+ import config from "virtual:zudoku-config";
8
+ import "vite/modulepreload-polyfill";
9
+ import type { ResolvedModulesConfig } from "../config/validators/ModulesSchema.js";
10
+ import { Bootstrap } from "../lib/components/Bootstrap.js";
11
+ import { getRoutesByConfig } from "./main.js";
12
+
13
+ // The build resolved the modules and put them in the config; parsing them again would put zod in this bundle.
14
+ const routes = getRoutesByConfig(
15
+ config,
16
+ (c) => (c as { __resolvedModules: ResolvedModulesConfig }).__resolvedModules,
17
+ );
18
+ // biome-ignore lint/style/noNonNullAssertion: We know the root element exists
19
+ const root = document.getElementById("root")!;
20
+
21
+ declare global {
22
+ interface Window {
23
+ ZUDOKU_VERSION: string;
24
+ }
25
+ }
26
+
27
+ window.ZUDOKU_VERSION = process.env.ZUDOKU_VERSION ?? "unknown";
28
+
29
+ if (process.env.SENTRY_DSN) {
30
+ void import("./sentry.js").then((mod) => {
31
+ mod.initSentry({ dsn: process.env.SENTRY_DSN as string });
32
+ });
33
+ }
34
+
35
+ if (root.childElementCount > 0) {
36
+ void hydrate(routes);
37
+ } else {
38
+ void render(routes);
39
+ }
40
+
41
+ if (import.meta.env.IS_ZUPLO) {
42
+ // biome-ignore lint/suspicious/noConsole: Logging allowed here
43
+ console.log(
44
+ `%cPowered by Zuplo v${window.ZUDOKU_VERSION}`,
45
+ [
46
+ "color: #Df0097",
47
+ "line-height: 50px",
48
+ "font-weight: bolder",
49
+ "font-size: 15px",
50
+ "text-align: center",
51
+ "letter-spacing: 5px",
52
+ ].join(" ;"),
53
+ );
54
+ } else {
55
+ // biome-ignore lint/suspicious/noConsole: Logging allowed here
56
+ console.log(
57
+ `%cAPITOGO v${window.ZUDOKU_VERSION}`,
58
+ [
59
+ "color: #0d9488",
60
+ "line-height: 50px",
61
+ "font-weight: bolder",
62
+ "font-size: 15px",
63
+ "text-align: center",
64
+ "letter-spacing: 5px",
65
+ ].join(" ;"),
66
+ );
67
+ // biome-ignore lint/suspicious/noConsole: Logging allowed here
68
+ console.log("» Learn more at https://apitogo.com");
69
+ }
70
+
71
+ async function hydrateLazyRoutes(routes: RouteObject[]) {
72
+ const path = window.location.pathname;
73
+ const lazyMatches = matchRoutes(routes, path, config.basePath)?.filter(
74
+ (m) => m.route.lazy,
75
+ );
76
+
77
+ if (lazyMatches?.length) {
78
+ await Promise.all(
79
+ lazyMatches.map(async (m) => {
80
+ if (typeof m.route.lazy !== "function") return;
81
+
82
+ const routeModule = await m.route.lazy();
83
+ Object.assign(m.route, { ...routeModule, lazy: undefined });
84
+ }),
85
+ );
86
+ }
87
+ }
88
+
89
+ function render(routes: RouteObject[]) {
90
+ const router = createBrowserRouter(routes, {
91
+ basename: config.basePath,
92
+ });
93
+ createRoot(root).render(<Bootstrap router={router} />);
94
+ }
95
+
96
+ async function hydrate(routes: RouteObject[]) {
97
+ // Only the route chunks are awaited. The highlighter keeps loading in the background: whatever needs it reads
98
+ // it with use() and waits on its own, with the prerendered HTML staying on screen, so a page without code
99
+ // (pricing, account, checkout) is not held back by ~260 KB of grammars it never uses.
100
+ await hydrateLazyRoutes(routes);
101
+
102
+ const router = createBrowserRouter(routes, {
103
+ basename: config.basePath,
104
+ });
105
+
106
+ hydrateRoot(root, <Bootstrap hydrate router={router} />);
107
+ }
108
+
109
+ // This is a workaround to avoid version skewing
110
+ // See https://vite.dev/guide/build.html#load-error-handling
111
+ // TODO: Implement a more advanced solution if there are CDN urls or e.g. Vercel Skew Protection
112
+ window.addEventListener("vite:preloadError", (e) => {
113
+ e.preventDefault();
114
+ window.location.reload();
115
+ });