aboutsummaryrefslogtreecommitdiff
path: root/packages/sdk/src
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-02-03 05:05:53 -0800
committerFuwn <[email protected]>2026-02-03 19:34:35 -0800
commitfe9ef2582d2dc8263dfa83fac598ae416ce9997d (patch)
tree52a7d7cf60fde06cdd933cb5652a200327a73ffd /packages/sdk/src
parentfeat(sdk): Implement project and folder storage (diff)
downloadarchived-imemio-fe9ef2582d2dc8263dfa83fac598ae416ce9997d.tar.xz
archived-imemio-fe9ef2582d2dc8263dfa83fac598ae416ce9997d.zip
test(sdk): Add in-memory store tests
Diffstat (limited to 'packages/sdk/src')
-rw-r--r--packages/sdk/src/in-memory-project-store.test.ts490
-rw-r--r--packages/sdk/src/in-memory-store.test.ts293
2 files changed, 783 insertions, 0 deletions
diff --git a/packages/sdk/src/in-memory-project-store.test.ts b/packages/sdk/src/in-memory-project-store.test.ts
new file mode 100644
index 0000000..4bf485e
--- /dev/null
+++ b/packages/sdk/src/in-memory-project-store.test.ts
@@ -0,0 +1,490 @@
+import { describe, it, expect, beforeEach } from "vitest";
+import { InMemoryProjectStore } from "./in-memory-project-store.js";
+
+describe("InMemoryProjectStore", () => {
+ let store: InMemoryProjectStore;
+
+ beforeEach(() => {
+ store = new InMemoryProjectStore();
+ });
+
+ describe("create", () => {
+ it("creates a project and returns it with generated id", async () => {
+ const result = await store.create({ name: "Test Project" });
+
+ expect(result.success).toBe(true);
+
+ if (result.success) {
+ expect(result.value.id).toBeDefined();
+ expect(result.value.name).toBe("Test Project");
+ expect(result.value.description).toBeNull();
+ expect(result.value.isGlobal).toBe(false);
+ expect(result.value.folders).toEqual([]);
+ expect(result.value.createdAt).toBeInstanceOf(Date);
+ expect(result.value.updatedAt).toBeInstanceOf(Date);
+ }
+ });
+
+ it("creates a project with optional fields", async () => {
+ const result = await store.create({
+ name: "Test Project",
+ description: "A test project",
+ isGlobal: true,
+ });
+
+ expect(result.success).toBe(true);
+
+ if (result.success) {
+ expect(result.value.description).toBe("A test project");
+ expect(result.value.isGlobal).toBe(true);
+ }
+ });
+ });
+
+ describe("get", () => {
+ it("returns a project by id", async () => {
+ const createResult = await store.create({ name: "Test Project" });
+
+ if (!createResult.success) {
+ throw new Error("Failed to create project");
+ }
+
+ const result = await store.get(createResult.value.id);
+
+ expect(result.success).toBe(true);
+
+ if (result.success) {
+ expect(result.value).toEqual(createResult.value);
+ }
+ });
+
+ it("returns failure when project does not exist", async () => {
+ const result = await store.get("non-existent-id");
+
+ expect(result.success).toBe(false);
+
+ if (!result.success) {
+ expect(result.error.type).toBe("PROJECT_NOT_FOUND");
+ expect(result.error.projectId).toBe("non-existent-id");
+ }
+ });
+ });
+
+ describe("update", () => {
+ it("updates a project and returns the updated version", async () => {
+ const createResult = await store.create({ name: "Original Name" });
+
+ if (!createResult.success) {
+ throw new Error("Failed to create project");
+ }
+
+ const result = await store.update(createResult.value.id, {
+ name: "Updated Name",
+ });
+
+ expect(result.success).toBe(true);
+
+ if (result.success) {
+ expect(result.value.name).toBe("Updated Name");
+ expect(result.value.updatedAt.getTime()).toBeGreaterThanOrEqual(
+ createResult.value.updatedAt.getTime(),
+ );
+ }
+ });
+
+ it("updates only specified fields", async () => {
+ const createResult = await store.create({
+ name: "Test Project",
+ description: "Original description",
+ isGlobal: false,
+ });
+
+ if (!createResult.success) {
+ throw new Error("Failed to create project");
+ }
+
+ const result = await store.update(createResult.value.id, {
+ name: "Updated Name",
+ });
+
+ expect(result.success).toBe(true);
+
+ if (result.success) {
+ expect(result.value.name).toBe("Updated Name");
+ expect(result.value.description).toBe("Original description");
+ expect(result.value.isGlobal).toBe(false);
+ }
+ });
+
+ it("allows setting description to null", async () => {
+ const createResult = await store.create({
+ name: "Test Project",
+ description: "Original description",
+ });
+
+ if (!createResult.success) {
+ throw new Error("Failed to create project");
+ }
+
+ const result = await store.update(createResult.value.id, {
+ description: null,
+ });
+
+ expect(result.success).toBe(true);
+
+ if (result.success) {
+ expect(result.value.description).toBeNull();
+ }
+ });
+
+ it("returns failure when project does not exist", async () => {
+ const result = await store.update("non-existent-id", {
+ name: "Updated Name",
+ });
+
+ expect(result.success).toBe(false);
+
+ if (!result.success) {
+ expect(result.error.type).toBe("PROJECT_NOT_FOUND");
+ expect(result.error.projectId).toBe("non-existent-id");
+ }
+ });
+ });
+
+ describe("delete", () => {
+ it("deletes a project", async () => {
+ const createResult = await store.create({ name: "Test Project" });
+
+ if (!createResult.success) {
+ throw new Error("Failed to create project");
+ }
+
+ const deleteResult = await store.delete(createResult.value.id);
+
+ expect(deleteResult.success).toBe(true);
+
+ const getResult = await store.get(createResult.value.id);
+
+ expect(getResult.success).toBe(false);
+ });
+
+ it("returns failure when project does not exist", async () => {
+ const result = await store.delete("non-existent-id");
+
+ expect(result.success).toBe(false);
+
+ if (!result.success) {
+ expect(result.error.type).toBe("PROJECT_NOT_FOUND");
+ expect(result.error.projectId).toBe("non-existent-id");
+ }
+ });
+ });
+
+ describe("list", () => {
+ it("returns empty array when no projects exist", async () => {
+ const result = await store.list();
+
+ expect(result.success).toBe(true);
+
+ if (result.success) {
+ expect(result.value).toEqual([]);
+ }
+ });
+
+ it("returns all projects", async () => {
+ const createResult1 = await store.create({ name: "Project 1" });
+ const createResult2 = await store.create({ name: "Project 2" });
+
+ if (!createResult1.success || !createResult2.success) {
+ throw new Error("Failed to create projects");
+ }
+
+ const result = await store.list();
+
+ expect(result.success).toBe(true);
+
+ if (result.success) {
+ expect(result.value).toHaveLength(2);
+ expect(result.value).toContainEqual(createResult1.value);
+ expect(result.value).toContainEqual(createResult2.value);
+ }
+ });
+ });
+
+ describe("addFolder", () => {
+ it("adds a folder to a project", async () => {
+ const createResult = await store.create({ name: "Test Project" });
+
+ if (!createResult.success) {
+ throw new Error("Failed to create project");
+ }
+
+ const result = await store.addFolder(createResult.value.id, {
+ name: "Test Folder",
+ });
+
+ expect(result.success).toBe(true);
+
+ if (result.success) {
+ expect(result.value.id).toBeDefined();
+ expect(result.value.name).toBe("Test Folder");
+ expect(result.value.description).toBeNull();
+ expect(result.value.projectId).toBe(createResult.value.id);
+ expect(result.value.createdAt).toBeInstanceOf(Date);
+ expect(result.value.updatedAt).toBeInstanceOf(Date);
+ }
+ });
+
+ it("adds a folder with description", async () => {
+ const createResult = await store.create({ name: "Test Project" });
+
+ if (!createResult.success) {
+ throw new Error("Failed to create project");
+ }
+
+ const result = await store.addFolder(createResult.value.id, {
+ name: "Test Folder",
+ description: "A test folder",
+ });
+
+ expect(result.success).toBe(true);
+
+ if (result.success) {
+ expect(result.value.description).toBe("A test folder");
+ }
+ });
+
+ it("returns failure when project does not exist", async () => {
+ const result = await store.addFolder("non-existent-id", {
+ name: "Test Folder",
+ });
+
+ expect(result.success).toBe(false);
+
+ if (!result.success) {
+ expect(result.error.type).toBe("PROJECT_NOT_FOUND");
+ expect(result.error.projectId).toBe("non-existent-id");
+ }
+ });
+ });
+
+ describe("updateFolder", () => {
+ it("updates a folder and returns the updated version", async () => {
+ const createResult = await store.create({ name: "Test Project" });
+
+ if (!createResult.success) {
+ throw new Error("Failed to create project");
+ }
+
+ const folderResult = await store.addFolder(createResult.value.id, {
+ name: "Original Name",
+ });
+
+ if (!folderResult.success) {
+ throw new Error("Failed to create folder");
+ }
+
+ const result = await store.updateFolder(
+ createResult.value.id,
+ folderResult.value.id,
+ { name: "Updated Name" },
+ );
+
+ expect(result.success).toBe(true);
+
+ if (result.success) {
+ expect(result.value.name).toBe("Updated Name");
+ expect(result.value.updatedAt.getTime()).toBeGreaterThanOrEqual(
+ folderResult.value.updatedAt.getTime(),
+ );
+ }
+ });
+
+ it("allows setting description to null", async () => {
+ const createResult = await store.create({ name: "Test Project" });
+
+ if (!createResult.success) {
+ throw new Error("Failed to create project");
+ }
+
+ const folderResult = await store.addFolder(createResult.value.id, {
+ name: "Test Folder",
+ description: "Original description",
+ });
+
+ if (!folderResult.success) {
+ throw new Error("Failed to create folder");
+ }
+
+ const result = await store.updateFolder(
+ createResult.value.id,
+ folderResult.value.id,
+ { description: null },
+ );
+
+ expect(result.success).toBe(true);
+
+ if (result.success) {
+ expect(result.value.description).toBeNull();
+ }
+ });
+
+ it("returns failure when project does not exist", async () => {
+ const result = await store.updateFolder("non-existent-id", "folder-id", {
+ name: "Updated Name",
+ });
+
+ expect(result.success).toBe(false);
+
+ if (!result.success) {
+ expect(result.error.type).toBe("PROJECT_NOT_FOUND");
+ }
+ });
+
+ it("returns failure when folder does not exist", async () => {
+ const createResult = await store.create({ name: "Test Project" });
+
+ if (!createResult.success) {
+ throw new Error("Failed to create project");
+ }
+
+ const result = await store.updateFolder(
+ createResult.value.id,
+ "non-existent-folder-id",
+ { name: "Updated Name" },
+ );
+
+ expect(result.success).toBe(false);
+
+ if (!result.success) {
+ expect(result.error.type).toBe("FOLDER_NOT_FOUND");
+
+ if (result.error.type === "FOLDER_NOT_FOUND") {
+ expect(result.error.folderId).toBe("non-existent-folder-id");
+ }
+ }
+ });
+ });
+
+ describe("removeFolder", () => {
+ it("removes a folder from a project", async () => {
+ const createResult = await store.create({ name: "Test Project" });
+
+ if (!createResult.success) {
+ throw new Error("Failed to create project");
+ }
+
+ const folderResult = await store.addFolder(createResult.value.id, {
+ name: "Test Folder",
+ });
+
+ if (!folderResult.success) {
+ throw new Error("Failed to create folder");
+ }
+
+ const removeResult = await store.removeFolder(
+ createResult.value.id,
+ folderResult.value.id,
+ );
+
+ expect(removeResult.success).toBe(true);
+
+ const listResult = await store.listFolders(createResult.value.id);
+
+ if (listResult.success) {
+ expect(listResult.value).toHaveLength(0);
+ }
+ });
+
+ it("returns failure when project does not exist", async () => {
+ const result = await store.removeFolder("non-existent-id", "folder-id");
+
+ expect(result.success).toBe(false);
+
+ if (!result.success) {
+ expect(result.error.type).toBe("PROJECT_NOT_FOUND");
+ }
+ });
+
+ it("returns failure when folder does not exist", async () => {
+ const createResult = await store.create({ name: "Test Project" });
+
+ if (!createResult.success) {
+ throw new Error("Failed to create project");
+ }
+
+ const result = await store.removeFolder(
+ createResult.value.id,
+ "non-existent-folder-id",
+ );
+
+ expect(result.success).toBe(false);
+
+ if (!result.success) {
+ expect(result.error.type).toBe("FOLDER_NOT_FOUND");
+
+ if (result.error.type === "FOLDER_NOT_FOUND") {
+ expect(result.error.folderId).toBe("non-existent-folder-id");
+ }
+ }
+ });
+ });
+
+ describe("listFolders", () => {
+ it("returns empty array when project has no folders", async () => {
+ const createResult = await store.create({ name: "Test Project" });
+
+ if (!createResult.success) {
+ throw new Error("Failed to create project");
+ }
+
+ const result = await store.listFolders(createResult.value.id);
+
+ expect(result.success).toBe(true);
+
+ if (result.success) {
+ expect(result.value).toEqual([]);
+ }
+ });
+
+ it("returns all folders for a project", async () => {
+ const createResult = await store.create({ name: "Test Project" });
+
+ if (!createResult.success) {
+ throw new Error("Failed to create project");
+ }
+
+ const folder1Result = await store.addFolder(createResult.value.id, {
+ name: "Folder 1",
+ });
+ const folder2Result = await store.addFolder(createResult.value.id, {
+ name: "Folder 2",
+ });
+
+ if (!folder1Result.success || !folder2Result.success) {
+ throw new Error("Failed to create folders");
+ }
+
+ const result = await store.listFolders(createResult.value.id);
+
+ expect(result.success).toBe(true);
+
+ if (result.success) {
+ expect(result.value).toHaveLength(2);
+ expect(result.value).toContainEqual(folder1Result.value);
+ expect(result.value).toContainEqual(folder2Result.value);
+ }
+ });
+
+ it("returns failure when project does not exist", async () => {
+ const result = await store.listFolders("non-existent-id");
+
+ expect(result.success).toBe(false);
+
+ if (!result.success) {
+ expect(result.error.type).toBe("PROJECT_NOT_FOUND");
+ expect(result.error.projectId).toBe("non-existent-id");
+ }
+ });
+ });
+});
diff --git a/packages/sdk/src/in-memory-store.test.ts b/packages/sdk/src/in-memory-store.test.ts
new file mode 100644
index 0000000..e55eaf1
--- /dev/null
+++ b/packages/sdk/src/in-memory-store.test.ts
@@ -0,0 +1,293 @@
+import { describe, it, expect, beforeEach } from "vitest";
+import { InMemoryStore } from "./in-memory-store.js";
+import type { Tag } from "./types.js";
+
+describe("InMemoryStore", () => {
+ let store: InMemoryStore;
+
+ beforeEach(() => {
+ store = new InMemoryStore();
+ });
+
+ describe("create", () => {
+ it("creates a memory and returns it with generated id", async () => {
+ const memory = await store.create({
+ content: "Test memory content",
+ projectId: "project-1",
+ });
+
+ expect(memory.id).toBeDefined();
+ expect(memory.content).toBe("Test memory content");
+ expect(memory.projectId).toBe("project-1");
+ expect(memory.folderId).toBeNull();
+ expect(memory.tags).toEqual([]);
+ expect(memory.metadata).toEqual({});
+ expect(memory.createdAt).toBeInstanceOf(Date);
+ expect(memory.updatedAt).toBeInstanceOf(Date);
+ });
+
+ it("creates a memory with optional fields", async () => {
+ const tags: Tag[] = [{ id: "tag-1", name: "important" }];
+ const metadata = { source: "test" };
+ const memory = await store.create({
+ content: "Test memory content",
+ projectId: "project-1",
+ folderId: "folder-1",
+ tags,
+ metadata,
+ });
+
+ expect(memory.folderId).toBe("folder-1");
+ expect(memory.tags).toEqual(tags);
+ expect(memory.metadata).toEqual(metadata);
+ });
+ });
+
+ describe("read", () => {
+ it("returns a memory by id", async () => {
+ const created = await store.create({
+ content: "Test memory content",
+ projectId: "project-1",
+ });
+ const result = await store.read(created.id);
+
+ expect(result.success).toBe(true);
+
+ if (result.success) {
+ expect(result.value).toEqual(created);
+ }
+ });
+
+ it("returns failure when memory does not exist", async () => {
+ const result = await store.read("non-existent-id");
+
+ expect(result.success).toBe(false);
+
+ if (!result.success) {
+ expect(result.error.type).toBe("MEMORY_NOT_FOUND");
+ expect(result.error.memoryId).toBe("non-existent-id");
+ }
+ });
+ });
+
+ describe("update", () => {
+ it("updates a memory and returns the updated version", async () => {
+ const created = await store.create({
+ content: "Original content",
+ projectId: "project-1",
+ });
+ const result = await store.update(created.id, {
+ content: "Updated content",
+ });
+
+ expect(result.success).toBe(true);
+
+ if (result.success) {
+ expect(result.value.content).toBe("Updated content");
+ expect(result.value.updatedAt.getTime()).toBeGreaterThanOrEqual(
+ created.updatedAt.getTime(),
+ );
+ }
+ });
+
+ it("updates only specified fields", async () => {
+ const tags: Tag[] = [{ id: "tag-1", name: "important" }];
+ const created = await store.create({
+ content: "Original content",
+ projectId: "project-1",
+ folderId: "folder-1",
+ tags,
+ });
+ const result = await store.update(created.id, {
+ content: "Updated content",
+ });
+
+ expect(result.success).toBe(true);
+
+ if (result.success) {
+ expect(result.value.content).toBe("Updated content");
+ expect(result.value.folderId).toBe("folder-1");
+ expect(result.value.tags).toEqual(tags);
+ }
+ });
+
+ it("allows setting folderId to null", async () => {
+ const created = await store.create({
+ content: "Test content",
+ projectId: "project-1",
+ folderId: "folder-1",
+ });
+ const result = await store.update(created.id, {
+ folderId: null,
+ });
+
+ expect(result.success).toBe(true);
+
+ if (result.success) {
+ expect(result.value.folderId).toBeNull();
+ }
+ });
+
+ it("returns failure when memory does not exist", async () => {
+ const result = await store.update("non-existent-id", {
+ content: "Updated content",
+ });
+
+ expect(result.success).toBe(false);
+
+ if (!result.success) {
+ expect(result.error.type).toBe("MEMORY_NOT_FOUND");
+ expect(result.error.memoryId).toBe("non-existent-id");
+ }
+ });
+ });
+
+ describe("delete", () => {
+ it("deletes a memory", async () => {
+ const created = await store.create({
+ content: "Test content",
+ projectId: "project-1",
+ });
+ const deleteResult = await store.delete(created.id);
+
+ expect(deleteResult.success).toBe(true);
+
+ const readResult = await store.read(created.id);
+
+ expect(readResult.success).toBe(false);
+ });
+
+ it("returns failure when memory does not exist", async () => {
+ const result = await store.delete("non-existent-id");
+
+ expect(result.success).toBe(false);
+
+ if (!result.success) {
+ expect(result.error.type).toBe("MEMORY_NOT_FOUND");
+ expect(result.error.memoryId).toBe("non-existent-id");
+ }
+ });
+ });
+
+ describe("list", () => {
+ it("returns empty array when no memories exist", async () => {
+ const memories = await store.list();
+
+ expect(memories).toEqual([]);
+ });
+
+ it("returns all memories when no filter is provided", async () => {
+ const memory1 = await store.create({
+ content: "Memory 1",
+ projectId: "project-1",
+ });
+ const memory2 = await store.create({
+ content: "Memory 2",
+ projectId: "project-2",
+ });
+ const memories = await store.list();
+
+ expect(memories).toHaveLength(2);
+ expect(memories).toContainEqual(memory1);
+ expect(memories).toContainEqual(memory2);
+ });
+
+ it("filters memories by projectId", async () => {
+ const memory1 = await store.create({
+ content: "Memory 1",
+ projectId: "project-1",
+ });
+
+ await store.create({
+ content: "Memory 2",
+ projectId: "project-2",
+ });
+
+ const memories = await store.list({ projectId: "project-1" });
+
+ expect(memories).toHaveLength(1);
+ expect(memories[0]).toEqual(memory1);
+ });
+
+ it("filters memories by folderId", async () => {
+ const memory1 = await store.create({
+ content: "Memory 1",
+ projectId: "project-1",
+ folderId: "folder-1",
+ });
+
+ await store.create({
+ content: "Memory 2",
+ projectId: "project-1",
+ folderId: "folder-2",
+ });
+ await store.create({
+ content: "Memory 3",
+ projectId: "project-1",
+ });
+
+ const memories = await store.list({ folderId: "folder-1" });
+
+ expect(memories).toHaveLength(1);
+ expect(memories[0]).toEqual(memory1);
+ });
+
+ it("filters memories by tags", async () => {
+ const tag1: Tag = { id: "tag-1", name: "important" };
+ const tag2: Tag = { id: "tag-2", name: "work" };
+ const memory1 = await store.create({
+ content: "Memory 1",
+ projectId: "project-1",
+ tags: [tag1, tag2],
+ });
+
+ await store.create({
+ content: "Memory 2",
+ projectId: "project-1",
+ tags: [tag1],
+ });
+ await store.create({
+ content: "Memory 3",
+ projectId: "project-1",
+ tags: [],
+ });
+
+ const memories = await store.list({ tags: ["tag-1", "tag-2"] });
+
+ expect(memories).toHaveLength(1);
+ expect(memories[0]).toEqual(memory1);
+ });
+
+ it("filters memories by multiple criteria", async () => {
+ const tag: Tag = { id: "tag-1", name: "important" };
+ const memory1 = await store.create({
+ content: "Memory 1",
+ projectId: "project-1",
+ folderId: "folder-1",
+ tags: [tag],
+ });
+
+ await store.create({
+ content: "Memory 2",
+ projectId: "project-1",
+ folderId: "folder-2",
+ tags: [tag],
+ });
+ await store.create({
+ content: "Memory 3",
+ projectId: "project-2",
+ folderId: "folder-1",
+ tags: [tag],
+ });
+
+ const memories = await store.list({
+ projectId: "project-1",
+ folderId: "folder-1",
+ tags: ["tag-1"],
+ });
+
+ expect(memories).toHaveLength(1);
+ expect(memories[0]).toEqual(memory1);
+ });
+ });
+});