next-dev
Version:
Tentu, berikut adalah markdown yang telah diperbaiki:
104 lines (99 loc) • 4.33 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const lodash_1 = __importDefault(require("lodash"));
const path_1 = __importDefault(require("path"));
const readdirp_1 = __importDefault(require("readdirp"));
const generateState = async (argv) => {
const listFunctionCode = [];
for await (const entry of (0, readdirp_1.default)(path_1.default.join(process.cwd(), 'src/app/api'), { fileFilter: '*.ts' })) {
const method = detectHttpMethod(entry.fullPath);
if (method === 'GET') {
listFunctionCode.push(generateFunctionCode(entry.fullPath, entry.path));
}
}
fs_1.default.writeFileSync(path_1.default.join(process.cwd(), 'src/lib/stateApi.ts'), declaration(`${listFunctionCode.join('\n')}\n`), { encoding: 'utf8' });
console.log('generate src/lib/stateApi.ts DONE');
};
const extractParams = (filePath) => {
const matches = filePath.match(/\[([^\]]+)\]/g);
return matches ? matches.map(param => param.replace(/[\[\]]/g, '')) : [];
};
const generateFunctionName = (filePath) => {
let baseFunctionName = filePath
.replace('/route.ts', '')
.replace(/[^\w\s]/g, ' ')
.replace(/\s+/g, ' ')
.trim()
.split(' ')
.map((word, index) => index === 0 ? word : word.charAt(0).toUpperCase() + word.slice(1))
.join('');
const params = extractParams(filePath);
if (params.length > 0) {
const paramPart = params.map(param => 'By' + param.charAt(0).toUpperCase() + param.slice(1)).join('');
baseFunctionName += paramPart;
}
return baseFunctionName;
};
const detectHttpMethod = (fullPath) => {
const content = fs_1.default.readFileSync(fullPath, 'utf8');
const match = content.match(/export\s+async\s+function\s+(GET|POST|DELETE|PUT|PATCH)\s*\(/);
return match ? match[1].toUpperCase() : 'GET';
};
const generateFunctionCode = (fullPath, filePath) => {
const functionName = generateFunctionName(filePath);
const params = extractParams(filePath);
const method = detectHttpMethod(fullPath);
const paramString = params.map(param => `${param}: string`).join(', ');
const paramObjString = params.join(', ');
const apiPath = filePath.replace(/\[([^\]]+)\]/g, '${$1}').replace(/\\/g, '/');
let paramDestructure = "";
if (params.length > 0) {
paramDestructure += paramObjString;
}
if (method === 'POST') {
paramDestructure += (paramDestructure ? ", " : "") + "body";
}
paramDestructure += (paramDestructure ? ", " : "") + "searchParams";
paramDestructure += (paramDestructure ? ", " : "") + "token";
return `
const ${functionName} = hookstate<any | undefined>(undefined);
export const Provider${lodash_1.default.upperFirst(functionName)} = ({data}: {data: any}) => {
if(data && ${functionName}.value === undefined) {
${functionName}.set(data)
}
return null
}
export const use${lodash_1.default.upperFirst(functionName)} = () => {
const state = wrapState(useHookstate(${functionName}))
async function load({ ${paramDestructure} }: { ${paramString}${paramString ? ", " : ""}${method === 'POST' ? "body?: string, " : ""}searchParams?: string[], token?: string }) {
const headers: Record<string, string> = token ? { 'Authorization': \`Bearer \${token}\` } : {};
const search = searchParams ? '?' + searchParams.join('&') : '';
const res = await fetch(\`/api/${apiPath.replace('route.ts', '').slice(0, -1)}\${searchParams || ''}\`, { method: '${method}', headers, ${method === 'POST' ? "body," : ""} cache: "no-cache" });
const json = await res.json().then((json) => json).catch(() => null);
if(json) state.set(json);
return {
res,
json
};
}
return [state.get, state.set, load] as const
};
`;
};
function declaration(fun) {
return `
'use client';
import { State, hookstate, useHookstate } from '@hookstate/core';
import _ from 'lodash';
const wrapState = <T>(s: State<T | undefined>) => ({
get: s.value,
set: (v: T) => s.set(v)
});
${fun}
`;
}
exports.default = generateState;