db-json-cli 2.0.2 → 2.0.4
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.
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/app-path-routes-manifest.json +1 -1
- package/.next/standalone/.next/build-manifest.json +2 -2
- package/.next/standalone/.next/prerender-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +1 -1
- package/.next/standalone/.next/server/app-paths-manifest.json +3 -3
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/pages-manifest.json +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/package.json +3 -8
- package/bin/cli.js +1 -12
- package/package.json +3 -8
- package/.next/BUILD_ID +0 -1
- package/.next/app-build-manifest.json +0 -26
- package/.next/app-path-routes-manifest.json +0 -1
- package/.next/build-manifest.json +0 -32
- package/.next/cache/webpack/client-production/0.pack +0 -0
- package/.next/cache/webpack/client-production/1.pack +0 -0
- package/.next/cache/webpack/client-production/2.pack +0 -0
- package/.next/cache/webpack/client-production/index.pack +0 -0
- package/.next/cache/webpack/client-production/index.pack.old +0 -0
- package/.next/cache/webpack/edge-server-production/0.pack +0 -0
- package/.next/cache/webpack/edge-server-production/index.pack +0 -0
- package/.next/cache/webpack/server-production/0.pack +0 -0
- package/.next/cache/webpack/server-production/1.pack +0 -0
- package/.next/cache/webpack/server-production/2.pack +0 -0
- package/.next/cache/webpack/server-production/index.pack +0 -0
- package/.next/cache/webpack/server-production/index.pack.old +0 -0
- package/.next/export-marker.json +0 -1
- package/.next/images-manifest.json +0 -1
- package/.next/next-minimal-server.js.nft.json +0 -1
- package/.next/next-server.js.nft.json +0 -1
- package/.next/package.json +0 -1
- package/.next/prerender-manifest.json +0 -1
- package/.next/react-loadable-manifest.json +0 -1
- package/.next/required-server-files.json +0 -1
- package/.next/routes-manifest.json +0 -1
- package/.next/server/app/_not-found/page.js +0 -1
- package/.next/server/app/_not-found/page.js.nft.json +0 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +0 -1
- package/.next/server/app/_not-found.html +0 -1
- package/.next/server/app/_not-found.meta +0 -6
- package/.next/server/app/_not-found.rsc +0 -9
- package/.next/server/app/api/[resource]/[id]/route.js +0 -1
- package/.next/server/app/api/[resource]/[id]/route.js.nft.json +0 -1
- package/.next/server/app/api/[resource]/route.js +0 -1
- package/.next/server/app/api/[resource]/route.js.nft.json +0 -1
- package/.next/server/app/api/info/route.js +0 -1
- package/.next/server/app/api/info/route.js.nft.json +0 -1
- package/.next/server/app/api/info.body +0 -1
- package/.next/server/app/api/info.meta +0 -1
- package/.next/server/app/api/login/route.js +0 -1
- package/.next/server/app/api/login/route.js.nft.json +0 -1
- package/.next/server/app/api/register/route.js +0 -1
- package/.next/server/app/api/register/route.js.nft.json +0 -1
- package/.next/server/app/index.html +0 -1
- package/.next/server/app/index.meta +0 -5
- package/.next/server/app/index.rsc +0 -7
- package/.next/server/app/page.js +0 -1
- package/.next/server/app/page.js.nft.json +0 -1
- package/.next/server/app/page_client-reference-manifest.js +0 -1
- package/.next/server/app-paths-manifest.json +0 -9
- package/.next/server/chunks/276.js +0 -2
- package/.next/server/chunks/471.js +0 -2
- package/.next/server/chunks/610.js +0 -12
- package/.next/server/chunks/682.js +0 -6
- package/.next/server/chunks/944.js +0 -1
- package/.next/server/chunks/font-manifest.json +0 -1
- package/.next/server/font-manifest.json +0 -1
- package/.next/server/functions-config-manifest.json +0 -1
- package/.next/server/interception-route-rewrite-manifest.js +0 -1
- package/.next/server/middleware-build-manifest.js +0 -1
- package/.next/server/middleware-manifest.json +0 -6
- package/.next/server/middleware-react-loadable-manifest.js +0 -1
- package/.next/server/next-font-manifest.js +0 -1
- package/.next/server/next-font-manifest.json +0 -1
- package/.next/server/pages/404.html +0 -1
- package/.next/server/pages/500.html +0 -1
- package/.next/server/pages/_app.js +0 -1
- package/.next/server/pages/_app.js.nft.json +0 -1
- package/.next/server/pages/_document.js +0 -1
- package/.next/server/pages/_document.js.nft.json +0 -1
- package/.next/server/pages/_error.js +0 -1
- package/.next/server/pages/_error.js.nft.json +0 -1
- package/.next/server/pages-manifest.json +0 -1
- package/.next/server/server-reference-manifest.js +0 -1
- package/.next/server/server-reference-manifest.json +0 -1
- package/.next/server/webpack-runtime.js +0 -1
- package/.next/trace +0 -2
- package/.next/types/app/api/[resource]/[id]/route.ts +0 -343
- package/.next/types/app/api/[resource]/route.ts +0 -343
- package/.next/types/app/api/info/route.ts +0 -343
- package/.next/types/app/api/login/route.ts +0 -343
- package/.next/types/app/api/register/route.ts +0 -343
- package/.next/types/app/layout.ts +0 -79
- package/.next/types/app/page.ts +0 -79
- package/.next/types/package.json +0 -1
- package/app/api/[resource]/[id]/route.js +0 -34
- package/app/api/[resource]/route.js +0 -74
- package/app/api/info/route.js +0 -26
- package/app/api/login/route.js +0 -27
- package/app/api/register/route.js +0 -32
- package/app/layout.jsx +0 -7
- package/app/page.jsx +0 -321
- package/db.json +0 -57
- package/jsconfig.json +0 -8
- package/lib/auth.js +0 -36
- package/lib/db.js +0 -47
- package/next.config.js +0 -7
- /package/.next/{static/rOhPoETBKkPu45bm2zUCI → standalone/.next/static/LxEs0HRjC2mVTMFB0QPeP}/_buildManifest.js +0 -0
- /package/.next/{static/rOhPoETBKkPu45bm2zUCI → standalone/.next/static/LxEs0HRjC2mVTMFB0QPeP}/_ssgManifest.js +0 -0
- /package/.next/{static → standalone/.next/static}/chunks/117-9bcfe95f89d4b2e1.js +0 -0
- /package/.next/{static → standalone/.next/static}/chunks/29-984b7c92c950b64f.js +0 -0
- /package/.next/{static → standalone/.next/static}/chunks/app/_not-found/page-32c70da5a397ed57.js +0 -0
- /package/.next/{static → standalone/.next/static}/chunks/app/layout-cbd3ebdc4ecc5247.js +0 -0
- /package/.next/{static → standalone/.next/static}/chunks/app/page-448ab87af648362a.js +0 -0
- /package/.next/{static → standalone/.next/static}/chunks/fd9d1056-9f91b5e418130764.js +0 -0
- /package/.next/{static → standalone/.next/static}/chunks/framework-f66176bb897dc684.js +0 -0
- /package/.next/{static → standalone/.next/static}/chunks/main-a3aef5995f5a9328.js +0 -0
- /package/.next/{static → standalone/.next/static}/chunks/main-app-9982ced3bf7037dc.js +0 -0
- /package/.next/{static → standalone/.next/static}/chunks/pages/_app-72b849fbd24ac258.js +0 -0
- /package/.next/{static → standalone/.next/static}/chunks/pages/_error-7ba65e1336b92748.js +0 -0
- /package/.next/{static → standalone/.next/static}/chunks/polyfills-42372ed130431b0a.js +0 -0
- /package/.next/{static → standalone/.next/static}/chunks/webpack-35b091ca5c5192ac.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__'
|
package/.next/types/app/page.ts
DELETED
|
@@ -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__'
|
package/.next/types/package.json
DELETED
|
@@ -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
|
-
}
|
package/app/api/info/route.js
DELETED
|
@@ -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
|
-
}
|
package/app/api/login/route.js
DELETED
|
@@ -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
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
|
-
}
|