From 38beca412e0dc23efb533e6b18ca02cf0e2d70ef Mon Sep 17 00:00:00 2001 From: "codegen-sh[bot]" <131295404+codegen-sh[bot]@users.noreply.github.com> Date: Sat, 20 Sep 2025 08:34:28 -0400 Subject: [PATCH] Add originalDocumentId to sourceMetadata when duplicating documents (#10215) - Added originalDocumentId property to SourceMetadata type - Updated documentDuplicator to set originalDocumentId for both parent and child documents - Added comprehensive tests to verify the functionality works correctly - Preserves existing sourceMetadata while adding the new property Co-authored-by: codegen-sh[bot] <131295404+codegen-sh[bot]@users.noreply.github.com> --- server/commands/documentDuplicator.test.ts | 66 ++++++++++++++++++++++ server/commands/documentDuplicator.ts | 8 +++ shared/types.ts | 2 + yarn.lock | 4 +- 4 files changed, 78 insertions(+), 2 deletions(-) diff --git a/server/commands/documentDuplicator.test.ts b/server/commands/documentDuplicator.test.ts index 1024a55822..37ba909f41 100644 --- a/server/commands/documentDuplicator.test.ts +++ b/server/commands/documentDuplicator.test.ts @@ -106,4 +106,70 @@ describe("documentDuplicator", () => { expect(response[0].color).toEqual(original.color); expect(response[0].publishedAt).toBeNull(); }); + + it("should set originalDocumentId in sourceMetadata when duplicating", async () => { + const user = await buildUser(); + const original = await buildDocument({ + userId: user.id, + teamId: user.teamId, + sourceMetadata: { fileName: "test.md", externalId: "ext123" }, + }); + + const response = await sequelize.transaction((transaction) => + documentDuplicator({ + document: original, + collection: original.collection, + user, + ctx: createContext({ user, transaction }), + }) + ); + + expect(response).toHaveLength(1); + expect(response[0].sourceMetadata).toEqual({ + fileName: "test.md", + externalId: "ext123", + originalDocumentId: original.id, + }); + }); + + it("should set originalDocumentId for child documents when duplicating recursively", async () => { + const user = await buildUser(); + const original = await buildDocument({ + userId: user.id, + teamId: user.teamId, + }); + + const childDocument = await buildDocument({ + userId: user.id, + teamId: user.teamId, + parentDocumentId: original.id, + collection: original.collection, + sourceMetadata: { fileName: "child.md" }, + }); + + const response = await sequelize.transaction((transaction) => + documentDuplicator({ + document: original, + collection: original.collection, + user, + recursive: true, + ctx: createContext({ user, transaction }), + }) + ); + + expect(response).toHaveLength(2); + + // Check parent document + const duplicatedParent = response.find((doc) => !doc.parentDocumentId); + expect(duplicatedParent?.sourceMetadata?.originalDocumentId).toEqual( + original.id + ); + + // Check child document + const duplicatedChild = response.find((doc) => doc.parentDocumentId); + expect(duplicatedChild?.sourceMetadata?.originalDocumentId).toEqual( + childDocument.id + ); + expect(duplicatedChild?.sourceMetadata?.fileName).toEqual("child.md"); + }); }); diff --git a/server/commands/documentDuplicator.ts b/server/commands/documentDuplicator.ts index d82e003aa6..f7d3e1d4e7 100644 --- a/server/commands/documentDuplicator.ts +++ b/server/commands/documentDuplicator.ts @@ -52,6 +52,10 @@ export default async function documentDuplicator({ DocumentHelper.toProsemirror(document), ["comment"] ), + sourceMetadata: { + ...document.sourceMetadata, + originalDocumentId: document.id, + }, ...sharedProperties, }); @@ -85,6 +89,10 @@ export default async function documentDuplicator({ DocumentHelper.toProsemirror(childDocument), ["comment"] ), + sourceMetadata: { + ...childDocument.sourceMetadata, + originalDocumentId: childDocument.id, + }, ...sharedProperties, }); diff --git a/shared/types.ts b/shared/types.ts index 0e0c6e3d98..8b0de99203 100644 --- a/shared/types.ts +++ b/shared/types.ts @@ -257,6 +257,8 @@ export type SourceMetadata = { externalName?: string; /** Whether the item was created through a trial license. */ trial?: boolean; + /** The ID of the original document when this document was duplicated. */ + originalDocumentId?: string; }; export type CustomTheme = { diff --git a/yarn.lock b/yarn.lock index 61435a8248..b6a0c81c1f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4135,7 +4135,7 @@ "@smithy/types" "^4.5.0" tslib "^2.6.2" -"@smithy/node-config-provider@^4.1.4", "@smithy/node-config-provider@^4.2.1": +"@smithy/node-config-provider@^4.2.1": version "4.2.1" resolved "https://registry.yarnpkg.com/@smithy/node-config-provider/-/node-config-provider-4.2.1.tgz#31be8865dbea9a9f23aee278a6728317d0ed0250" integrity sha512-AIA0BJZq2h295J5NeCTKhg1WwtdTA/GqBCaVjk30bDgMHwniUETyh5cP9IiE9VrId7Kt8hS7zvREVMTv1VfA6g== @@ -4238,7 +4238,7 @@ dependencies: tslib "^2.6.2" -"@smithy/url-parser@^4.0.5", "@smithy/url-parser@^4.1.1": +"@smithy/url-parser@^4.1.1": version "4.1.1" resolved "https://registry.yarnpkg.com/@smithy/url-parser/-/url-parser-4.1.1.tgz#0e9a5e72b3cf9d7ab7305f9093af5528d9debaf6" integrity sha512-bx32FUpkhcaKlEoOMbScvc93isaSiRM75pQ5IgIBaMkT7qMlIibpPRONyx/0CvrXHzJLpOn/u6YiDX2hcvs7Dg==