From e72e34a4b95c106c6ecddfec9ab86004ca9f86b7 Mon Sep 17 00:00:00 2001 From: mazuh Date: Tue, 30 Jan 2024 23:14:02 -0300 Subject: [PATCH] init request spec management --- package-lock.json | 26 ++++- package.json | 2 + .../project-workspace/opfs-project-service.ts | 99 +++++++++++++++++++ 3 files changed, 122 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index c45d1ef..e63e352 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "@radix-ui/react-slot": "^1.0.2", "class-variance-authority": "^0.7.0", "clsx": "^2.0.0", + "lodash.debounce": "^4.0.8", "lucide-react": "^0.293.0", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -35,6 +36,7 @@ "@testing-library/react": "^14.1.2", "@testing-library/user-event": "^14.5.1", "@types/jest": "^29.5.8", + "@types/lodash.debounce": "^4.0.9", "@types/react": "^18.2.37", "@types/react-dom": "^18.2.15", "@types/uuid": "^9.0.7", @@ -4246,6 +4248,21 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, + "node_modules/@types/lodash": { + "version": "4.14.202", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.202.tgz", + "integrity": "sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==", + "dev": true + }, + "node_modules/@types/lodash.debounce": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/lodash.debounce/-/lodash.debounce-4.0.9.tgz", + "integrity": "sha512-Ma5JcgTREwpLRwMM+XwBR7DaWe96nC38uCBDFKZWbNKD+osjVzdpnUSwBcqCptrp16sSOLBAUb50Car5I0TCsQ==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, "node_modules/@types/node": { "version": "20.9.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.2.tgz", @@ -9311,8 +9328,7 @@ "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" }, "node_modules/lodash.merge": { "version": "4.6.2", @@ -11348,9 +11364,9 @@ } }, "node_modules/vite": { - "version": "5.0.11", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.11.tgz", - "integrity": "sha512-XBMnDjZcNAw/G1gEiskiM1v6yzM4GE5aMGvhWTlHAYYhxb7S3/V1s3m2LDHa8Vh6yIWYYB0iJwsEaS523c4oYA==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.12.tgz", + "integrity": "sha512-4hsnEkG3q0N4Tzf1+t6NdN9dg/L3BM+q8SWgbSPnJvrgH2kgdyzfVJwbR1ic69/4uMJJ/3dqDZZE5/WwqW8U1w==", "dev": true, "dependencies": { "esbuild": "^0.19.3", diff --git a/package.json b/package.json index f23a7c4..852b4bb 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@radix-ui/react-slot": "^1.0.2", "class-variance-authority": "^0.7.0", "clsx": "^2.0.0", + "lodash.debounce": "^4.0.8", "lucide-react": "^0.293.0", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -39,6 +40,7 @@ "@testing-library/react": "^14.1.2", "@testing-library/user-event": "^14.5.1", "@types/jest": "^29.5.8", + "@types/lodash.debounce": "^4.0.9", "@types/react": "^18.2.37", "@types/react-dom": "^18.2.15", "@types/uuid": "^9.0.7", diff --git a/src/features/project-workspace/opfs-project-service.ts b/src/features/project-workspace/opfs-project-service.ts index d42b30b..6f13a67 100644 --- a/src/features/project-workspace/opfs-project-service.ts +++ b/src/features/project-workspace/opfs-project-service.ts @@ -1 +1,100 @@ +/** + * Implements management of each single project using the Origin Private File System. + */ +import { v4 as uuidv4 } from "uuid"; +import type { + Project, + ProjectRequestSpec, + ProjectRequestSpecHeader, +} from "@/entities/management"; +import { retrieveProject } from "./opfs-project-service"; +import { persistProject } from "@/services/opfs-projects-shared-internals"; +import debounce from "lodash.debounce"; + export { retrieveProject } from "@/services/opfs-projects-shared-internals"; + +/** Params for `createRequestSpec` */ +export interface CreateRequestSpecParams { + projectUuid: Project["uuid"]; +} + +/** + * Persist a new spec in the project. + */ +export async function createRequestSpec( + params: CreateRequestSpecParams +): Promise { + const creating: ProjectRequestSpec = { + uuid: uuidv4(), + url: "", + method: "GET", + headers: [...DEFAULT_REQUEST_SPEC_HEADERS], + body: "", + }; + + const project = await retrieveProject(params.projectUuid); + const updatedProject: Project = { + ...project, + specs: [...project.specs, creating], + }; + await persistProject(updatedProject); + + return creating; +} + +/** Params for `removeRequestSpec` */ +export interface RemoveRequestSpecParams { + projectUuid: Project["uuid"]; + removingUuid: ProjectRequestSpec["uuid"]; +} + +/** + * Remove a spec from the project. + */ +export async function removeRequestSpec( + params: RemoveRequestSpecParams +): Promise<{ specUuid: ProjectRequestSpec["uuid"] }> { + const project = await retrieveProject(params.projectUuid); + const updatedProject: Project = { + ...project, + specs: project.specs.filter((spec) => spec.uuid !== params.removingUuid), + }; + await persistProject(updatedProject); + + return { specUuid: params.removingUuid }; +} + +/** Params for `patchRequestSpec` */ +export interface PatchRequestSpecParams { + projectUuid: Project["uuid"]; + patching: Partial; +} + +/** + * Update a spec in the project. + * + * Debounced. + */ +export const patchRequestSpec = debounce(doPatchRequestSpec, 300); + +async function doPatchRequestSpec( + params: PatchRequestSpecParams +): Promise { + const project = await retrieveProject(params.projectUuid); + const updatedProject: Project = { + ...project, + specs: project.specs.map((existing) => + existing.uuid === params.patching.uuid + ? { ...existing, ...params.patching } + : existing + ), + }; + await persistProject(updatedProject); + + return params.patching as ProjectRequestSpec; +} + +const DEFAULT_REQUEST_SPEC_HEADERS: readonly ProjectRequestSpecHeader[] = [ + { key: "Content-Type", value: "application/json", isEnabled: false }, + { key: "Accept", value: "application/json", isEnabled: true }, +];