db-json-cli 2.0.2 → 2.0.3

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 (114) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +1 -1
  3. package/.next/standalone/.next/build-manifest.json +2 -2
  4. package/.next/standalone/.next/prerender-manifest.json +1 -1
  5. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  6. package/.next/standalone/.next/server/app/_not-found.rsc +1 -1
  7. package/.next/standalone/.next/server/app/index.html +1 -1
  8. package/.next/standalone/.next/server/app/index.rsc +1 -1
  9. package/.next/standalone/.next/server/app-paths-manifest.json +3 -3
  10. package/.next/standalone/.next/server/pages/404.html +1 -1
  11. package/.next/standalone/.next/server/pages/500.html +1 -1
  12. package/.next/standalone/.next/server/pages-manifest.json +1 -1
  13. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  14. package/.next/standalone/package.json +3 -7
  15. package/package.json +3 -7
  16. package/.next/BUILD_ID +0 -1
  17. package/.next/app-build-manifest.json +0 -26
  18. package/.next/app-path-routes-manifest.json +0 -1
  19. package/.next/build-manifest.json +0 -32
  20. package/.next/cache/webpack/client-production/0.pack +0 -0
  21. package/.next/cache/webpack/client-production/1.pack +0 -0
  22. package/.next/cache/webpack/client-production/2.pack +0 -0
  23. package/.next/cache/webpack/client-production/index.pack +0 -0
  24. package/.next/cache/webpack/client-production/index.pack.old +0 -0
  25. package/.next/cache/webpack/edge-server-production/0.pack +0 -0
  26. package/.next/cache/webpack/edge-server-production/index.pack +0 -0
  27. package/.next/cache/webpack/server-production/0.pack +0 -0
  28. package/.next/cache/webpack/server-production/1.pack +0 -0
  29. package/.next/cache/webpack/server-production/2.pack +0 -0
  30. package/.next/cache/webpack/server-production/index.pack +0 -0
  31. package/.next/cache/webpack/server-production/index.pack.old +0 -0
  32. package/.next/export-marker.json +0 -1
  33. package/.next/images-manifest.json +0 -1
  34. package/.next/next-minimal-server.js.nft.json +0 -1
  35. package/.next/next-server.js.nft.json +0 -1
  36. package/.next/package.json +0 -1
  37. package/.next/prerender-manifest.json +0 -1
  38. package/.next/react-loadable-manifest.json +0 -1
  39. package/.next/required-server-files.json +0 -1
  40. package/.next/routes-manifest.json +0 -1
  41. package/.next/server/app/_not-found/page.js +0 -1
  42. package/.next/server/app/_not-found/page.js.nft.json +0 -1
  43. package/.next/server/app/_not-found/page_client-reference-manifest.js +0 -1
  44. package/.next/server/app/_not-found.html +0 -1
  45. package/.next/server/app/_not-found.meta +0 -6
  46. package/.next/server/app/_not-found.rsc +0 -9
  47. package/.next/server/app/api/[resource]/[id]/route.js +0 -1
  48. package/.next/server/app/api/[resource]/[id]/route.js.nft.json +0 -1
  49. package/.next/server/app/api/[resource]/route.js +0 -1
  50. package/.next/server/app/api/[resource]/route.js.nft.json +0 -1
  51. package/.next/server/app/api/info/route.js +0 -1
  52. package/.next/server/app/api/info/route.js.nft.json +0 -1
  53. package/.next/server/app/api/info.body +0 -1
  54. package/.next/server/app/api/info.meta +0 -1
  55. package/.next/server/app/api/login/route.js +0 -1
  56. package/.next/server/app/api/login/route.js.nft.json +0 -1
  57. package/.next/server/app/api/register/route.js +0 -1
  58. package/.next/server/app/api/register/route.js.nft.json +0 -1
  59. package/.next/server/app/index.html +0 -1
  60. package/.next/server/app/index.meta +0 -5
  61. package/.next/server/app/index.rsc +0 -7
  62. package/.next/server/app/page.js +0 -1
  63. package/.next/server/app/page.js.nft.json +0 -1
  64. package/.next/server/app/page_client-reference-manifest.js +0 -1
  65. package/.next/server/app-paths-manifest.json +0 -9
  66. package/.next/server/chunks/276.js +0 -2
  67. package/.next/server/chunks/471.js +0 -2
  68. package/.next/server/chunks/610.js +0 -12
  69. package/.next/server/chunks/682.js +0 -6
  70. package/.next/server/chunks/944.js +0 -1
  71. package/.next/server/chunks/font-manifest.json +0 -1
  72. package/.next/server/font-manifest.json +0 -1
  73. package/.next/server/functions-config-manifest.json +0 -1
  74. package/.next/server/interception-route-rewrite-manifest.js +0 -1
  75. package/.next/server/middleware-build-manifest.js +0 -1
  76. package/.next/server/middleware-manifest.json +0 -6
  77. package/.next/server/middleware-react-loadable-manifest.js +0 -1
  78. package/.next/server/next-font-manifest.js +0 -1
  79. package/.next/server/next-font-manifest.json +0 -1
  80. package/.next/server/pages/404.html +0 -1
  81. package/.next/server/pages/500.html +0 -1
  82. package/.next/server/pages/_app.js +0 -1
  83. package/.next/server/pages/_app.js.nft.json +0 -1
  84. package/.next/server/pages/_document.js +0 -1
  85. package/.next/server/pages/_document.js.nft.json +0 -1
  86. package/.next/server/pages/_error.js +0 -1
  87. package/.next/server/pages/_error.js.nft.json +0 -1
  88. package/.next/server/pages-manifest.json +0 -1
  89. package/.next/server/server-reference-manifest.js +0 -1
  90. package/.next/server/server-reference-manifest.json +0 -1
  91. package/.next/server/webpack-runtime.js +0 -1
  92. package/.next/trace +0 -2
  93. package/.next/types/app/api/[resource]/[id]/route.ts +0 -343
  94. package/.next/types/app/api/[resource]/route.ts +0 -343
  95. package/.next/types/app/api/info/route.ts +0 -343
  96. package/.next/types/app/api/login/route.ts +0 -343
  97. package/.next/types/app/api/register/route.ts +0 -343
  98. package/.next/types/app/layout.ts +0 -79
  99. package/.next/types/app/page.ts +0 -79
  100. package/.next/types/package.json +0 -1
  101. package/app/api/[resource]/[id]/route.js +0 -34
  102. package/app/api/[resource]/route.js +0 -74
  103. package/app/api/info/route.js +0 -26
  104. package/app/api/login/route.js +0 -27
  105. package/app/api/register/route.js +0 -32
  106. package/app/layout.jsx +0 -7
  107. package/app/page.jsx +0 -321
  108. package/db.json +0 -57
  109. package/jsconfig.json +0 -8
  110. package/lib/auth.js +0 -36
  111. package/lib/db.js +0 -47
  112. package/next.config.js +0 -7
  113. /package/.next/static/{rOhPoETBKkPu45bm2zUCI → FILmz7SXSZj16Eu_uBk6b}/_buildManifest.js +0 -0
  114. /package/.next/static/{rOhPoETBKkPu45bm2zUCI → FILmz7SXSZj16Eu_uBk6b}/_ssgManifest.js +0 -0
@@ -1,79 +0,0 @@
1
- // File: D:\잡동사니\db-json-cli\app\layout.jsx
2
- import * as entry from '../../../app/layout.js'
3
- import type { ResolvingMetadata, ResolvingViewport } from 'next/dist/lib/metadata/types/metadata-interface.js'
4
-
5
- type TEntry = typeof import('../../../app/layout.js')
6
-
7
- // Check that the entry is a valid entry
8
- checkFields<Diff<{
9
- default: Function
10
- config?: {}
11
- generateStaticParams?: Function
12
- revalidate?: RevalidateRange<TEntry> | false
13
- dynamic?: 'auto' | 'force-dynamic' | 'error' | 'force-static'
14
- dynamicParams?: boolean
15
- fetchCache?: 'auto' | 'force-no-store' | 'only-no-store' | 'default-no-store' | 'default-cache' | 'only-cache' | 'force-cache'
16
- preferredRegion?: 'auto' | 'global' | 'home' | string | string[]
17
- runtime?: 'nodejs' | 'experimental-edge' | 'edge'
18
- maxDuration?: number
19
-
20
- metadata?: any
21
- generateMetadata?: Function
22
- viewport?: any
23
- generateViewport?: Function
24
-
25
- }, TEntry, ''>>()
26
-
27
- // Check the prop type of the entry function
28
- checkFields<Diff<LayoutProps, FirstArg<TEntry['default']>, 'default'>>()
29
-
30
- // Check the arguments and return type of the generateMetadata function
31
- if ('generateMetadata' in entry) {
32
- checkFields<Diff<LayoutProps, FirstArg<MaybeField<TEntry, 'generateMetadata'>>, 'generateMetadata'>>()
33
- checkFields<Diff<ResolvingMetadata, SecondArg<MaybeField<TEntry, 'generateMetadata'>>, 'generateMetadata'>>()
34
- }
35
-
36
- // Check the arguments and return type of the generateViewport function
37
- if ('generateViewport' in entry) {
38
- checkFields<Diff<LayoutProps, FirstArg<MaybeField<TEntry, 'generateViewport'>>, 'generateViewport'>>()
39
- checkFields<Diff<ResolvingViewport, SecondArg<MaybeField<TEntry, 'generateViewport'>>, 'generateViewport'>>()
40
- }
41
-
42
- // Check the arguments and return type of the generateStaticParams function
43
- if ('generateStaticParams' in entry) {
44
- checkFields<Diff<{ params: PageParams }, FirstArg<MaybeField<TEntry, 'generateStaticParams'>>, 'generateStaticParams'>>()
45
- checkFields<Diff<{ __tag__: 'generateStaticParams', __return_type__: any[] | Promise<any[]> }, { __tag__: 'generateStaticParams', __return_type__: ReturnType<MaybeField<TEntry, 'generateStaticParams'>> }>>()
46
- }
47
-
48
- type PageParams = any
49
- export interface PageProps {
50
- params?: any
51
- searchParams?: any
52
- }
53
- export interface LayoutProps {
54
- children?: React.ReactNode
55
-
56
- params?: any
57
- }
58
-
59
- // =============
60
- // Utility types
61
- type RevalidateRange<T> = T extends { revalidate: any } ? NonNegative<T['revalidate']> : never
62
-
63
- // If T is unknown or any, it will be an empty {} type. Otherwise, it will be the same as Omit<T, keyof Base>.
64
- type OmitWithTag<T, K extends keyof any, _M> = Omit<T, K>
65
- type Diff<Base, T extends Base, Message extends string = ''> = 0 extends (1 & T) ? {} : OmitWithTag<T, keyof Base, Message>
66
-
67
- type FirstArg<T extends Function> = T extends (...args: [infer T, any]) => any ? unknown extends T ? any : T : never
68
- type SecondArg<T extends Function> = T extends (...args: [any, infer T]) => any ? unknown extends T ? any : T : never
69
- type MaybeField<T, K extends string> = T extends { [k in K]: infer G } ? G extends Function ? G : never : never
70
-
71
-
72
-
73
- function checkFields<_ extends { [k in keyof any]: never }>() {}
74
-
75
- // https://github.com/sindresorhus/type-fest
76
- type Numeric = number | bigint
77
- type Zero = 0 | 0n
78
- type Negative<T extends Numeric> = T extends Zero ? never : `${T}` extends `-${string}` ? T : never
79
- type NonNegative<T extends Numeric> = T extends Zero ? T : Negative<T> extends never ? T : '__invalid_negative_number__'
@@ -1,79 +0,0 @@
1
- // File: D:\잡동사니\db-json-cli\app\page.jsx
2
- import * as entry from '../../../app/page.js'
3
- import type { ResolvingMetadata, ResolvingViewport } from 'next/dist/lib/metadata/types/metadata-interface.js'
4
-
5
- type TEntry = typeof import('../../../app/page.js')
6
-
7
- // Check that the entry is a valid entry
8
- checkFields<Diff<{
9
- default: Function
10
- config?: {}
11
- generateStaticParams?: Function
12
- revalidate?: RevalidateRange<TEntry> | false
13
- dynamic?: 'auto' | 'force-dynamic' | 'error' | 'force-static'
14
- dynamicParams?: boolean
15
- fetchCache?: 'auto' | 'force-no-store' | 'only-no-store' | 'default-no-store' | 'default-cache' | 'only-cache' | 'force-cache'
16
- preferredRegion?: 'auto' | 'global' | 'home' | string | string[]
17
- runtime?: 'nodejs' | 'experimental-edge' | 'edge'
18
- maxDuration?: number
19
-
20
- metadata?: any
21
- generateMetadata?: Function
22
- viewport?: any
23
- generateViewport?: Function
24
-
25
- }, TEntry, ''>>()
26
-
27
- // Check the prop type of the entry function
28
- checkFields<Diff<PageProps, FirstArg<TEntry['default']>, 'default'>>()
29
-
30
- // Check the arguments and return type of the generateMetadata function
31
- if ('generateMetadata' in entry) {
32
- checkFields<Diff<PageProps, FirstArg<MaybeField<TEntry, 'generateMetadata'>>, 'generateMetadata'>>()
33
- checkFields<Diff<ResolvingMetadata, SecondArg<MaybeField<TEntry, 'generateMetadata'>>, 'generateMetadata'>>()
34
- }
35
-
36
- // Check the arguments and return type of the generateViewport function
37
- if ('generateViewport' in entry) {
38
- checkFields<Diff<PageProps, FirstArg<MaybeField<TEntry, 'generateViewport'>>, 'generateViewport'>>()
39
- checkFields<Diff<ResolvingViewport, SecondArg<MaybeField<TEntry, 'generateViewport'>>, 'generateViewport'>>()
40
- }
41
-
42
- // Check the arguments and return type of the generateStaticParams function
43
- if ('generateStaticParams' in entry) {
44
- checkFields<Diff<{ params: PageParams }, FirstArg<MaybeField<TEntry, 'generateStaticParams'>>, 'generateStaticParams'>>()
45
- checkFields<Diff<{ __tag__: 'generateStaticParams', __return_type__: any[] | Promise<any[]> }, { __tag__: 'generateStaticParams', __return_type__: ReturnType<MaybeField<TEntry, 'generateStaticParams'>> }>>()
46
- }
47
-
48
- type PageParams = any
49
- export interface PageProps {
50
- params?: any
51
- searchParams?: any
52
- }
53
- export interface LayoutProps {
54
- children?: React.ReactNode
55
-
56
- params?: any
57
- }
58
-
59
- // =============
60
- // Utility types
61
- type RevalidateRange<T> = T extends { revalidate: any } ? NonNegative<T['revalidate']> : never
62
-
63
- // If T is unknown or any, it will be an empty {} type. Otherwise, it will be the same as Omit<T, keyof Base>.
64
- type OmitWithTag<T, K extends keyof any, _M> = Omit<T, K>
65
- type Diff<Base, T extends Base, Message extends string = ''> = 0 extends (1 & T) ? {} : OmitWithTag<T, keyof Base, Message>
66
-
67
- type FirstArg<T extends Function> = T extends (...args: [infer T, any]) => any ? unknown extends T ? any : T : never
68
- type SecondArg<T extends Function> = T extends (...args: [any, infer T]) => any ? unknown extends T ? any : T : never
69
- type MaybeField<T, K extends string> = T extends { [k in K]: infer G } ? G extends Function ? G : never : never
70
-
71
-
72
-
73
- function checkFields<_ extends { [k in keyof any]: never }>() {}
74
-
75
- // https://github.com/sindresorhus/type-fest
76
- type Numeric = number | bigint
77
- type Zero = 0 | 0n
78
- type Negative<T extends Numeric> = T extends Zero ? never : `${T}` extends `-${string}` ? T : never
79
- type NonNegative<T extends Numeric> = T extends Zero ? T : Negative<T> extends never ? T : '__invalid_negative_number__'
@@ -1 +0,0 @@
1
- {"type": "module"}
@@ -1,34 +0,0 @@
1
- import { NextResponse } from "next/server";
2
- import { getDB } from "@/lib/db";
3
- import { authMiddleware } from "@/lib/auth";
4
-
5
- export async function GET(request, { params }) {
6
- try {
7
- const { resource, id } = params;
8
- const db = await getDB();
9
-
10
- if (!db[resource]) {
11
- return NextResponse.json({ message: "Resource not found" }, { status: 404 });
12
- }
13
-
14
- // Check if private
15
- const isPrivate = db.rules?.[resource] === "private";
16
- if (isPrivate) {
17
- const user = authMiddleware(request);
18
- if (!user) {
19
- return NextResponse.json({ message: "No token" }, { status: 401 });
20
- }
21
- }
22
-
23
- const itemId = Number(id);
24
- const item = db[resource].find((i) => i.id === itemId);
25
-
26
- if (!item) {
27
- return NextResponse.json({ message: "Not found" }, { status: 404 });
28
- }
29
-
30
- return NextResponse.json(item);
31
- } catch (error) {
32
- return NextResponse.json({ message: "Failed to fetch item" }, { status: 500 });
33
- }
34
- }
@@ -1,74 +0,0 @@
1
- import { NextResponse } from "next/server";
2
- import { getDB, saveDB } from "@/lib/db";
3
- import { authMiddleware } from "@/lib/auth";
4
-
5
- export async function GET(request, { params }) {
6
- try {
7
- const { resource } = params;
8
- const db = await getDB();
9
-
10
- if (!db[resource]) {
11
- return NextResponse.json({ message: "Resource not found" }, { status: 404 });
12
- }
13
-
14
- // Check if private
15
- const isPrivate = db.rules?.[resource] === "private";
16
- if (isPrivate) {
17
- const user = authMiddleware(request);
18
- if (!user) {
19
- return NextResponse.json({ message: "No token" }, { status: 401 });
20
- }
21
- }
22
-
23
- // Filter by range
24
- const { searchParams } = new URL(request.url);
25
- const from = searchParams.get("from");
26
- const to = searchParams.get("to");
27
-
28
- let data = db[resource];
29
- if (from && to) {
30
- const fromNum = Number(from);
31
- const toNum = Number(to);
32
- data = data.filter((item) => item.id >= fromNum && item.id <= toNum);
33
- }
34
-
35
- return NextResponse.json(data);
36
- } catch (error) {
37
- return NextResponse.json({ message: "Failed to fetch data" }, { status: 500 });
38
- }
39
- }
40
-
41
- export async function POST(request, { params }) {
42
- try {
43
- const { resource } = params;
44
- const db = await getDB();
45
-
46
- if (!db[resource]) {
47
- return NextResponse.json({ message: "Resource not found" }, { status: 404 });
48
- }
49
-
50
- // Check if private
51
- const isPrivate = db.rules?.[resource] === "private";
52
- if (isPrivate) {
53
- const user = authMiddleware(request);
54
- if (!user) {
55
- return NextResponse.json({ message: "No token" }, { status: 401 });
56
- }
57
- }
58
-
59
- const newItem = await request.json();
60
- if (!newItem || typeof newItem !== "object") {
61
- return NextResponse.json({ message: "Invalid body" }, { status: 400 });
62
- }
63
-
64
- const id = db[resource].length ? Math.max(...db[resource].map((i) => i.id)) + 1 : 1;
65
- const item = { id, ...newItem };
66
-
67
- db[resource].push(item);
68
- await saveDB(db);
69
-
70
- return NextResponse.json(item);
71
- } catch (error) {
72
- return NextResponse.json({ message: "Failed to create item" }, { status: 500 });
73
- }
74
- }
@@ -1,26 +0,0 @@
1
- import { NextResponse } from "next/server";
2
- import { getDB } from "@/lib/db";
3
-
4
- export async function GET() {
5
- try {
6
- const db = await getDB();
7
- const routeList = [];
8
-
9
- Object.keys(db).forEach((key) => {
10
- if (["users", "rules"].includes(key)) return;
11
- const isPrivate = db.rules?.[key] === "private";
12
- routeList.push({
13
- key,
14
- count: db[key].length,
15
- permission: isPrivate ? "private" : "public",
16
- });
17
- });
18
-
19
- return NextResponse.json({
20
- routeList,
21
- port: process.env.PORT || 4000,
22
- });
23
- } catch (error) {
24
- return NextResponse.json({ message: "Failed to load DB info" }, { status: 500 });
25
- }
26
- }
@@ -1,27 +0,0 @@
1
- import { NextResponse } from "next/server";
2
- import { getDB } from "@/lib/db";
3
- import { comparePassword, generateTokens } from "@/lib/auth";
4
-
5
- export async function POST(request) {
6
- try {
7
- const { email, password } = await request.json();
8
-
9
- const db = await getDB();
10
- const user = db.users.find((u) => u.email === email);
11
-
12
- if (!user) {
13
- return NextResponse.json({ message: "Invalid credentials" }, { status: 401 });
14
- }
15
-
16
- const valid = await comparePassword(password, user.password);
17
-
18
- if (!valid) {
19
- return NextResponse.json({ message: "Invalid credentials" }, { status: 401 });
20
- }
21
-
22
- const tokens = generateTokens({ id: user.id, email: user.email });
23
- return NextResponse.json(tokens);
24
- } catch (error) {
25
- return NextResponse.json({ message: "Login failed" }, { status: 500 });
26
- }
27
- }
@@ -1,32 +0,0 @@
1
- import { NextResponse } from "next/server";
2
- import { getDB, saveDB } from "@/lib/db";
3
- import { hashPassword, generateTokens } from "@/lib/auth";
4
-
5
- export async function POST(request) {
6
- try {
7
- const { email, password, name } = await request.json();
8
-
9
- if (!email || !password) {
10
- return NextResponse.json({ message: "Email/password required" }, { status: 400 });
11
- }
12
-
13
- const db = await getDB();
14
- const exists = db.users.find((u) => u.email === email);
15
-
16
- if (exists) {
17
- return NextResponse.json({ message: "User already exists" }, { status: 409 });
18
- }
19
-
20
- const hashed = await hashPassword(password);
21
- const id = db.users.length ? Math.max(...db.users.map((u) => u.id)) + 1 : 1;
22
- const newUser = { id, email, name: name || "", password: hashed };
23
-
24
- db.users.push(newUser);
25
- await saveDB(db);
26
-
27
- const tokens = generateTokens({ id, email });
28
- return NextResponse.json(tokens);
29
- } catch (error) {
30
- return NextResponse.json({ message: "Registration failed" }, { status: 500 });
31
- }
32
- }
package/app/layout.jsx DELETED
@@ -1,7 +0,0 @@
1
- export default function RootLayout({ children }) {
2
- return (
3
- <html lang="en">
4
- <body style={{ margin: 0, padding: 0 }}>{children}</body>
5
- </html>
6
- );
7
- }
package/app/page.jsx DELETED
@@ -1,321 +0,0 @@
1
- "use client";
2
-
3
- import { useState, useEffect } from "react";
4
-
5
- export default function HomePage() {
6
- const [routeList, setRouteList] = useState([]);
7
- const [port, setPort] = useState(4000);
8
- const [loading, setLoading] = useState(true);
9
- const [activeEndpoint, setActiveEndpoint] = useState(null);
10
-
11
- useEffect(() => {
12
- fetch("/api/info")
13
- .then((res) => res.json())
14
- .then((data) => {
15
- setRouteList(data.routeList);
16
- setPort(data.port);
17
- setLoading(false);
18
- })
19
- .catch((err) => {
20
- console.error("Failed to load API info:", err);
21
- setLoading(false);
22
- });
23
- }, []);
24
-
25
- if (loading) {
26
- return (
27
- <>
28
- <div className="loading-container">Loading...</div>
29
- <style jsx>{`
30
- .loading-container {
31
- display: flex;
32
- justify-content: center;
33
- align-items: center;
34
- min-height: 100vh;
35
- background: linear-gradient(to bottom, #1a1a2e 0%, #16213e 100%);
36
- color: white;
37
- font-size: 1.5rem;
38
- }
39
- `}</style>
40
- </>
41
- );
42
- }
43
-
44
- return (
45
- <>
46
- <div className="container">
47
- <div className="header">
48
- <div className="header-content">
49
- <h1>🚀 db-json-cli API</h1>
50
- <p>RESTful JSON API Documentation</p>
51
- </div>
52
- </div>
53
-
54
- <div className="content">
55
- <div className="info-box">
56
- <h2>📖 API Information</h2>
57
- <p>Welcome to the db-json-cli API. This API provides RESTful endpoints for managing your data.</p>
58
- <div className="base-url">Base URL: http://localhost:{port}</div>
59
- </div>
60
-
61
- <div className="endpoints">
62
- <h2>Available Endpoints</h2>
63
-
64
- {routeList.map((r) => (
65
- <div key={r.key}>
66
- <div
67
- className={`endpoint-item ${activeEndpoint === `${r.key}-get` ? "active" : ""}`}
68
- onClick={() => setActiveEndpoint(activeEndpoint === `${r.key}-get` ? null : `${r.key}-get`)}
69
- >
70
- <div className="endpoint-header">
71
- <span className="method-badge method-get">GET</span>
72
- <span className="endpoint-path">/{r.key}</span>
73
- <span className={`permission-badge permission-${r.permission}`}>
74
- {r.permission === "public" ? "🔓" : "🔒"} {r.permission.toUpperCase()}
75
- </span>
76
- <span className="endpoint-count">
77
- {r.count} {r.count === 1 ? "item" : "items"}
78
- </span>
79
- </div>
80
- <div className="endpoint-description">
81
- Retrieve all {r.key} or filter by ID range using ?from=1&to=10
82
- </div>
83
- {activeEndpoint === `${r.key}-get` && (
84
- <div className="endpoint-actions">
85
- <a
86
- href={`/api/${r.key}`}
87
- target="_blank"
88
- rel="noopener noreferrer"
89
- className="action-btn btn-primary"
90
- onClick={(e) => e.stopPropagation()}
91
- >
92
- Try it out
93
- </a>
94
- </div>
95
- )}
96
- </div>
97
-
98
- <div className="endpoint-item">
99
- <div className="endpoint-header">
100
- <span className="method-badge method-get">GET</span>
101
- <span className="endpoint-path">/{r.key}/:id</span>
102
- <span className={`permission-badge permission-${r.permission}`}>
103
- {r.permission === "public" ? "🔓" : "🔒"} {r.permission.toUpperCase()}
104
- </span>
105
- </div>
106
- <div className="endpoint-description">Retrieve a specific item by ID</div>
107
- </div>
108
-
109
- <div className="endpoint-item">
110
- <div className="endpoint-header">
111
- <span className="method-badge method-post">POST</span>
112
- <span className="endpoint-path">/{r.key}</span>
113
- <span className={`permission-badge permission-${r.permission}`}>
114
- {r.permission === "public" ? "🔓" : "🔒"} {r.permission.toUpperCase()}
115
- </span>
116
- </div>
117
- <div className="endpoint-description">Create a new item (ID will be auto-generated)</div>
118
- </div>
119
- </div>
120
- ))}
121
-
122
- <div className="endpoint-item">
123
- <div className="endpoint-header">
124
- <span className="method-badge method-post">POST</span>
125
- <span className="endpoint-path">/register</span>
126
- </div>
127
- <div className="endpoint-description">Register a new user account</div>
128
- </div>
129
-
130
- <div className="endpoint-item">
131
- <div className="endpoint-header">
132
- <span className="method-badge method-post">POST</span>
133
- <span className="endpoint-path">/login</span>
134
- </div>
135
- <div className="endpoint-description">Login and receive access tokens</div>
136
- </div>
137
- </div>
138
- </div>
139
-
140
- <div className="footer">
141
- <p>Generated by db-json-cli • Made with ♥</p>
142
- </div>
143
- </div>
144
-
145
- <style jsx>{`
146
- * {
147
- margin: 0;
148
- padding: 0;
149
- box-sizing: border-box;
150
- }
151
- .container {
152
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
153
- background: linear-gradient(to bottom, #1a1a2e 0%, #16213e 100%);
154
- color: #333;
155
- min-height: 100vh;
156
- }
157
- .header {
158
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
159
- padding: 3rem 2rem;
160
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
161
- }
162
- .header-content {
163
- max-width: 1200px;
164
- margin: 0 auto;
165
- }
166
- .header h1 {
167
- color: white;
168
- font-size: 2.5rem;
169
- margin-bottom: 0.5rem;
170
- font-weight: 700;
171
- }
172
- .header p {
173
- color: rgba(255, 255, 255, 0.9);
174
- font-size: 1.1rem;
175
- }
176
- .content {
177
- max-width: 1200px;
178
- margin: 0 auto;
179
- padding: 2rem;
180
- }
181
- .info-box {
182
- background: white;
183
- border-radius: 12px;
184
- padding: 1.5rem;
185
- margin-bottom: 2rem;
186
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
187
- }
188
- .info-box h2 {
189
- color: #667eea;
190
- font-size: 1.3rem;
191
- margin-bottom: 0.5rem;
192
- }
193
- .info-box p {
194
- color: #666;
195
- line-height: 1.6;
196
- }
197
- .base-url {
198
- background: #f8f9fa;
199
- padding: 0.5rem 1rem;
200
- border-radius: 6px;
201
- font-family: "Courier New", monospace;
202
- color: #333;
203
- display: inline-block;
204
- margin-top: 0.5rem;
205
- }
206
- .endpoints {
207
- background: white;
208
- border-radius: 12px;
209
- padding: 2rem;
210
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
211
- }
212
- .endpoints h2 {
213
- color: #333;
214
- font-size: 1.5rem;
215
- margin-bottom: 1.5rem;
216
- padding-bottom: 0.5rem;
217
- border-bottom: 2px solid #667eea;
218
- }
219
- .endpoint-item {
220
- background: #f8f9fa;
221
- border: 1px solid #e9ecef;
222
- border-radius: 8px;
223
- padding: 1.5rem;
224
- margin-bottom: 1rem;
225
- transition: all 0.3s ease;
226
- cursor: pointer;
227
- }
228
- .endpoint-item:hover,
229
- .endpoint-item.active {
230
- transform: translateY(-2px);
231
- box-shadow: 0 4px 12px rgba(102, 126, 234, 0.2);
232
- border-color: #667eea;
233
- }
234
- .endpoint-header {
235
- display: flex;
236
- align-items: center;
237
- gap: 1rem;
238
- margin-bottom: 1rem;
239
- flex-wrap: wrap;
240
- }
241
- .method-badge {
242
- padding: 0.3rem 0.8rem;
243
- border-radius: 4px;
244
- font-weight: 600;
245
- font-size: 0.75rem;
246
- text-transform: uppercase;
247
- letter-spacing: 0.5px;
248
- }
249
- .method-get {
250
- background: #e7f5ff;
251
- color: #1971c2;
252
- }
253
- .method-post {
254
- background: #d3f9d8;
255
- color: #2f9e44;
256
- }
257
- .permission-badge {
258
- padding: 0.3rem 0.8rem;
259
- border-radius: 4px;
260
- font-weight: 600;
261
- font-size: 0.75rem;
262
- text-transform: uppercase;
263
- letter-spacing: 0.5px;
264
- }
265
- .permission-public {
266
- background: #d3f9d8;
267
- color: #2f9e44;
268
- }
269
- .permission-private {
270
- background: #ffd43b;
271
- color: #856404;
272
- }
273
- .endpoint-path {
274
- font-family: "Courier New", monospace;
275
- font-size: 1.1rem;
276
- color: #333;
277
- font-weight: 500;
278
- }
279
- .endpoint-count {
280
- margin-left: auto;
281
- background: #667eea;
282
- color: white;
283
- padding: 0.3rem 0.8rem;
284
- border-radius: 20px;
285
- font-size: 0.85rem;
286
- font-weight: 600;
287
- }
288
- .endpoint-description {
289
- color: #666;
290
- line-height: 1.5;
291
- }
292
- .endpoint-actions {
293
- margin-top: 1rem;
294
- }
295
- .action-btn {
296
- padding: 0.5rem 1rem;
297
- border-radius: 6px;
298
- text-decoration: none;
299
- font-size: 0.9rem;
300
- font-weight: 500;
301
- transition: all 0.2s;
302
- display: inline-block;
303
- }
304
- .btn-primary {
305
- background: #667eea;
306
- color: white;
307
- }
308
- .btn-primary:hover {
309
- background: #5568d3;
310
- transform: translateY(-1px);
311
- }
312
- .footer {
313
- text-align: center;
314
- padding: 2rem;
315
- color: rgba(255, 255, 255, 0.7);
316
- font-size: 0.9rem;
317
- }
318
- `}</style>
319
- </>
320
- );
321
- }