@open-mercato/documents 0.10.1-develop.7979.1.8f7a1e6df5 → 0.10.1-develop.7982.1.df20d84e85
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.
|
@@ -394,6 +394,7 @@ const deleteFolderCommand = {
|
|
|
394
394
|
assertCommandFeature(features, "documents.edit");
|
|
395
395
|
await assertFolderOwnerOrManager(undo.before.ownerUserId, actorUserId, features);
|
|
396
396
|
assertVersionedSnapshot(folder, undo.after, DOCUMENTS_ENTITY_IDS.documentFolder);
|
|
397
|
+
await assertOrganizationFolderCapacity(em, scope);
|
|
397
398
|
await assertWritableParent(em, undo.before.parentFolderId, scope, actorUserId, features);
|
|
398
399
|
await assertValidPlacement(em, scope, input.id, undo.before.parentFolderId);
|
|
399
400
|
if (folder) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/documents/commands/folders.ts"],
|
|
4
|
-
"sourcesContent": ["import { LockMode } from '@mikro-orm/core'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { isDeepStrictEqual } from 'node:util'\nimport { z } from 'zod'\nimport { registerCommand, type CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport { extractUndoPayload } from '@open-mercato/shared/lib/commands/undo'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { enforceCommandOptimisticLockWithGuards } from '@open-mercato/shared/lib/crud/optimistic-lock-command'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { hasAllFeatures } from '@open-mercato/shared/lib/auth/featureMatch'\nimport { DocumentFolder } from '../data/entities'\nimport { documentFolderCreateSchema, documentFolderUpdateSchema } from '../data/validators'\nimport { DOCUMENTS_ENTITY_IDS, DOCUMENTS_MAX_FOLDERS_PER_ORGANIZATION } from '../lib/constants'\nimport { acquireFolderHierarchyMutationLock } from '../lib/folderHierarchySerialization'\nimport { getFolderPlacementIssue, hasActiveFolderContents } from '../lib/visibility'\nimport {\n assertCommandFeature,\n resolveDocumentsCommandActor,\n resolveDocumentsCommandEntityManager,\n resolveDocumentsCommandFeatures,\n resolveDocumentsCommandScope,\n type DocumentsCommandScope,\n} from './shared'\nimport {\n assertVersionedSnapshot,\n documentsScopedCommandSchema,\n nextDocumentVersion,\n readCommandRedoInput,\n} from './mutation-helpers'\n\nconst folderSnapshotSchema = z.object({\n id: z.string().uuid(),\n tenantId: z.string().uuid(),\n organizationId: z.string().uuid(),\n name: z.string(),\n parentFolderId: z.string().uuid().nullable(),\n ownerUserId: z.string().uuid(),\n createdAt: z.string().datetime(),\n updatedAt: z.string().datetime(),\n deletedAt: z.string().datetime().nullable(),\n})\n\nconst folderUpdateRedoExpectationSchema = z.object({\n kind: z.literal('folder-update-post-undo'),\n folder: folderSnapshotSchema,\n})\n\nconst folderDeleteRedoExpectationSchema = z.object({\n kind: z.literal('folder-delete-post-undo'),\n folder: folderSnapshotSchema,\n})\n\nexport const folderCreateCommandSchema = documentsScopedCommandSchema\n .merge(documentFolderCreateSchema)\n .extend({ folderId: z.string().uuid() })\n\nexport const folderUpdateCommandSchema = documentsScopedCommandSchema\n .merge(documentFolderUpdateSchema)\n .extend({ redoExpectation: folderUpdateRedoExpectationSchema.optional() })\n\nexport const folderDeleteCommandSchema = documentsScopedCommandSchema.extend({\n id: z.string().uuid(),\n redoExpectation: folderDeleteRedoExpectationSchema.optional(),\n})\n\nexport type FolderCreateCommandInput = z.infer<typeof folderCreateCommandSchema>\nexport type FolderUpdateCommandInput = z.infer<typeof folderUpdateCommandSchema>\nexport type FolderDeleteCommandInput = z.infer<typeof folderDeleteCommandSchema>\n\ntype FolderSnapshot = z.infer<typeof folderSnapshotSchema>\n\ntype FolderUndoPayload = {\n before?: FolderSnapshot | null\n after?: FolderSnapshot | null\n}\n\ntype FolderCommandResult = {\n id: string\n updatedAt: string\n before: FolderSnapshot | null\n after: FolderSnapshot\n}\n\nfunction snapshotFolder(folder: DocumentFolder | null): FolderSnapshot | null {\n if (!folder) return null\n return {\n id: folder.id,\n tenantId: folder.tenantId,\n organizationId: folder.organizationId,\n name: folder.name,\n parentFolderId: folder.parentFolderId ?? null,\n ownerUserId: folder.ownerUserId,\n createdAt: folder.createdAt.toISOString(),\n updatedAt: folder.updatedAt.toISOString(),\n deletedAt: folder.deletedAt?.toISOString() ?? null,\n }\n}\n\nfunction changedError(): CrudHttpError {\n return new CrudHttpError(409, { error: 'Record changed by another user' })\n}\n\nfunction nextSnapshotVersion(updatedAt: string): string {\n return nextDocumentVersion(new Date(updatedAt), new Date(0)).toISOString()\n}\n\nfunction assertFolderStateMatches(folder: DocumentFolder, expected: FolderSnapshot): void {\n if (!isDeepStrictEqual(snapshotFolder(folder), expected)) throw changedError()\n}\n\nfunction resolveExactUndoVersion(current: Date, expectedUpdatedAt?: string): Date {\n if (!expectedUpdatedAt) return nextDocumentVersion(current)\n const expected = new Date(expectedUpdatedAt)\n if (!Number.isFinite(expected.getTime()) || expected.getTime() <= current.getTime()) {\n throw changedError()\n }\n return expected\n}\n\nfunction buildFolderUpdateRedoExpectation(\n before: FolderSnapshot,\n after: FolderSnapshot,\n): z.infer<typeof folderUpdateRedoExpectationSchema> {\n return {\n kind: 'folder-update-post-undo',\n folder: { ...before, updatedAt: nextSnapshotVersion(after.updatedAt) },\n }\n}\n\nfunction buildFolderDeleteRedoExpectation(\n before: FolderSnapshot,\n after: FolderSnapshot,\n): z.infer<typeof folderDeleteRedoExpectationSchema> {\n return {\n kind: 'folder-delete-post-undo',\n folder: { ...before, updatedAt: nextSnapshotVersion(after.updatedAt) },\n }\n}\n\nasync function loadLockedFolder(\n em: EntityManager,\n id: string,\n scope: DocumentsCommandScope,\n includeDeleted = false,\n): Promise<DocumentFolder | null> {\n return findOneWithDecryption(\n em,\n DocumentFolder,\n {\n id,\n ...scope,\n ...(includeDeleted ? {} : { deletedAt: null }),\n },\n {\n lockMode: LockMode.PESSIMISTIC_WRITE,\n ...(includeDeleted ? { filters: false } : {}),\n },\n scope,\n )\n}\n\nasync function assertFolderOwnerOrManager(\n ownerUserId: string,\n actorUserId: string,\n features: readonly string[],\n): Promise<void> {\n if (ownerUserId === actorUserId || hasAllFeatures(['documents.manage'], Array.from(features))) return\n throw new CrudHttpError(403, { error: 'Forbidden' })\n}\n\nasync function assertWritableParent(\n em: EntityManager,\n parentFolderId: string | null | undefined,\n scope: DocumentsCommandScope,\n actorUserId: string,\n features: readonly string[],\n): Promise<void> {\n if (!parentFolderId) return\n const parent = await loadLockedFolder(em, parentFolderId, scope)\n if (!parent) throw new CrudHttpError(404, { error: 'documents.folders.notFound' })\n await assertFolderOwnerOrManager(parent.ownerUserId, actorUserId, features)\n}\n\n/**\n * Call only while holding the folder hierarchy mutation lock, so the count and\n * the insert that follows it cannot interleave with a competing create.\n */\nasync function assertOrganizationFolderCapacity(\n em: EntityManager,\n scope: DocumentsCommandScope,\n): Promise<void> {\n const activeCount = await em.count(DocumentFolder, { ...scope, deletedAt: null })\n if (activeCount < DOCUMENTS_MAX_FOLDERS_PER_ORGANIZATION) return\n throw new CrudHttpError(422, { error: 'documents.errors.folderLimitReached' })\n}\n\nasync function assertValidPlacement(\n em: EntityManager,\n scope: DocumentsCommandScope,\n folderId: string | null,\n parentFolderId: string | null,\n): Promise<void> {\n const issue = await getFolderPlacementIssue({ em, ...scope, folderId, parentFolderId })\n if (issue) throw new CrudHttpError(400, { error: 'documents.folders.error.invalidPlacement' })\n}\n\nfunction applyFolderSnapshot(\n folder: DocumentFolder,\n snapshot: FolderSnapshot,\n expectedUpdatedAt?: string,\n): void {\n folder.name = snapshot.name\n folder.parentFolderId = snapshot.parentFolderId\n folder.ownerUserId = snapshot.ownerUserId\n folder.deletedAt = snapshot.deletedAt ? new Date(snapshot.deletedAt) : null\n folder.updatedAt = resolveExactUndoVersion(folder.updatedAt, expectedUpdatedAt)\n}\n\nfunction buildFolderLog(\n actionLabel: string,\n input: DocumentsCommandScope,\n result: FolderCommandResult,\n redoInput?: FolderUpdateCommandInput | FolderDeleteCommandInput,\n) {\n return {\n actionLabel,\n resourceKind: DOCUMENTS_ENTITY_IDS.documentFolder,\n resourceId: result.id,\n tenantId: input.tenantId,\n organizationId: input.organizationId,\n snapshotBefore: result.before,\n snapshotAfter: result.after,\n payload: {\n undo: { before: result.before, after: result.after } satisfies FolderUndoPayload,\n ...(redoInput ? { __redoInput: redoInput } : {}),\n },\n }\n}\n\nconst createFolderCommand: CommandHandler<FolderCreateCommandInput, FolderCommandResult> = {\n id: 'documents.folder.create',\n async execute(rawInput, ctx) {\n const input = folderCreateCommandSchema.parse(rawInput)\n const scope = resolveDocumentsCommandScope(ctx, input)\n const actorUserId = resolveDocumentsCommandActor(ctx)\n const em = resolveDocumentsCommandEntityManager(ctx)\n let folder!: DocumentFolder\n let before: FolderSnapshot | null = null\n await withAtomicFlush(em, [async () => {\n await acquireFolderHierarchyMutationLock(em, scope)\n const existing = await loadLockedFolder(em, input.folderId, scope, true)\n const features = await resolveDocumentsCommandFeatures(ctx, scope)\n assertCommandFeature(features, 'documents.edit')\n before = snapshotFolder(existing)\n if (existing && !existing.deletedAt) {\n throw new CrudHttpError(409, { error: 'Record changed by another user' })\n }\n // Reviving a soft-deleted row adds an active folder just like a fresh\n // insert, so both paths answer to the same organization-wide cap. Undo\n // stays exempt: it only restores state the organization already held.\n await assertOrganizationFolderCapacity(em, scope)\n await assertWritableParent(em, input.parentFolderId ?? null, scope, actorUserId, features)\n await assertValidPlacement(em, scope, null, input.parentFolderId ?? null)\n folder = existing ?? em.create(DocumentFolder, {\n id: input.folderId,\n ...scope,\n name: input.name,\n parentFolderId: input.parentFolderId ?? null,\n ownerUserId: actorUserId,\n })\n if (!existing) em.persist(folder)\n folder.name = input.name\n folder.parentFolderId = input.parentFolderId ?? null\n folder.ownerUserId = actorUserId\n folder.deletedAt = null\n if (existing) folder.updatedAt = nextDocumentVersion(folder.updatedAt)\n }], { transaction: true, label: 'documents.folder.create' })\n return {\n id: folder.id,\n updatedAt: folder.updatedAt.toISOString(),\n before,\n after: snapshotFolder(folder)!,\n }\n },\n async buildLog({ input, result }) {\n const { translate } = await resolveTranslations()\n return buildFolderLog(\n translate('documents.audit.folderCreated', 'Create folder'),\n input,\n result,\n )\n },\n async undo({ logEntry, ctx }) {\n const undo = extractUndoPayload<FolderUndoPayload>(logEntry)\n if (!undo?.after) return\n const input = folderCreateCommandSchema.parse(readCommandRedoInput(logEntry))\n const scope = resolveDocumentsCommandScope(ctx, input)\n const actorUserId = resolveDocumentsCommandActor(ctx)\n const em = resolveDocumentsCommandEntityManager(ctx)\n await withAtomicFlush(em, [async () => {\n await acquireFolderHierarchyMutationLock(em, scope)\n const folder = await loadLockedFolder(em, input.folderId, scope, true)\n const features = await resolveDocumentsCommandFeatures(ctx, scope)\n assertCommandFeature(features, 'documents.edit')\n await assertFolderOwnerOrManager(undo.after!.ownerUserId, actorUserId, features)\n assertVersionedSnapshot(folder, undo.after, DOCUMENTS_ENTITY_IDS.documentFolder)\n if (await hasActiveFolderContents({ em, ...scope, folderId: input.folderId })) {\n throw new CrudHttpError(409, { error: 'Record changed by another user' })\n }\n if (undo.before && folder) applyFolderSnapshot(folder, undo.before)\n else if (folder) {\n const now = nextDocumentVersion(folder.updatedAt)\n folder.deletedAt = now\n folder.updatedAt = now\n }\n }], { transaction: true, label: 'documents.folder.create.undo' })\n },\n}\n\nconst updateFolderCommand: CommandHandler<FolderUpdateCommandInput, FolderCommandResult> = {\n id: 'documents.folder.update',\n async execute(rawInput, ctx) {\n const input = folderUpdateCommandSchema.parse(rawInput)\n const scope = resolveDocumentsCommandScope(ctx, input)\n const actorUserId = resolveDocumentsCommandActor(ctx)\n const em = resolveDocumentsCommandEntityManager(ctx)\n let folder!: DocumentFolder\n let before!: FolderSnapshot\n await withAtomicFlush(em, [async () => {\n await acquireFolderHierarchyMutationLock(em, scope)\n const loaded = await loadLockedFolder(\n em,\n input.id,\n scope,\n input.redoExpectation !== undefined,\n )\n if (!loaded) throw new CrudHttpError(404, { error: 'documents.folders.notFound' })\n folder = loaded\n const features = await resolveDocumentsCommandFeatures(ctx, scope)\n assertCommandFeature(features, 'documents.edit')\n await assertFolderOwnerOrManager(folder.ownerUserId, actorUserId, features)\n if (input.redoExpectation) {\n assertFolderStateMatches(folder, input.redoExpectation.folder)\n } else {\n await enforceCommandOptimisticLockWithGuards(ctx.container, {\n resourceKind: DOCUMENTS_ENTITY_IDS.documentFolder,\n resourceId: folder.id,\n current: folder.updatedAt,\n request: ctx.request ?? null,\n })\n }\n before = snapshotFolder(folder)!\n if (Object.prototype.hasOwnProperty.call(input, 'parentFolderId')) {\n await assertWritableParent(em, input.parentFolderId ?? null, scope, actorUserId, features)\n await assertValidPlacement(em, scope, folder.id, input.parentFolderId ?? null)\n }\n if (input.name !== undefined) folder.name = input.name\n if (Object.prototype.hasOwnProperty.call(input, 'parentFolderId')) {\n folder.parentFolderId = input.parentFolderId ?? null\n }\n folder.updatedAt = nextDocumentVersion(folder.updatedAt)\n }], { transaction: true, label: 'documents.folder.update' })\n return {\n id: folder.id,\n updatedAt: folder.updatedAt.toISOString(),\n before,\n after: snapshotFolder(folder)!,\n }\n },\n async buildLog({ input, result }) {\n const { translate } = await resolveTranslations()\n if (!result.before) throw new Error('[internal] folder update produced no before snapshot')\n const redoInput: FolderUpdateCommandInput = {\n ...input,\n redoExpectation: buildFolderUpdateRedoExpectation(result.before, result.after),\n }\n return buildFolderLog(\n translate('documents.audit.folderUpdated', 'Update folder'),\n input,\n result,\n redoInput,\n )\n },\n async undo({ logEntry, ctx }) {\n const undo = extractUndoPayload<FolderUndoPayload>(logEntry)\n if (!undo?.before || !undo.after) return\n const before = undo.before\n const after = undo.after\n const input = folderUpdateCommandSchema.parse(readCommandRedoInput(logEntry))\n const scope = resolveDocumentsCommandScope(ctx, input)\n const actorUserId = resolveDocumentsCommandActor(ctx)\n const em = resolveDocumentsCommandEntityManager(ctx)\n await withAtomicFlush(em, [async () => {\n await acquireFolderHierarchyMutationLock(em, scope)\n const folder = await loadLockedFolder(em, input.id, scope)\n if (!folder) throw new CrudHttpError(404, { error: 'documents.folders.notFound' })\n const features = await resolveDocumentsCommandFeatures(ctx, scope)\n assertCommandFeature(features, 'documents.edit')\n await assertFolderOwnerOrManager(folder.ownerUserId, actorUserId, features)\n assertVersionedSnapshot(folder, after, DOCUMENTS_ENTITY_IDS.documentFolder)\n await assertWritableParent(em, before.parentFolderId, scope, actorUserId, features)\n await assertValidPlacement(em, scope, folder.id, before.parentFolderId)\n applyFolderSnapshot(\n folder,\n before,\n input.redoExpectation?.folder.updatedAt,\n )\n }], { transaction: true, label: 'documents.folder.update.undo' })\n },\n}\n\nconst deleteFolderCommand: CommandHandler<FolderDeleteCommandInput, FolderCommandResult> = {\n id: 'documents.folder.delete',\n async execute(rawInput, ctx) {\n const input = folderDeleteCommandSchema.parse(rawInput)\n const scope = resolveDocumentsCommandScope(ctx, input)\n const actorUserId = resolveDocumentsCommandActor(ctx)\n const em = resolveDocumentsCommandEntityManager(ctx)\n let folder!: DocumentFolder\n let before!: FolderSnapshot\n await withAtomicFlush(em, [async () => {\n await acquireFolderHierarchyMutationLock(em, scope)\n const loaded = await loadLockedFolder(\n em,\n input.id,\n scope,\n input.redoExpectation !== undefined,\n )\n if (!loaded) throw new CrudHttpError(404, { error: 'documents.folders.notFound' })\n folder = loaded\n const features = await resolveDocumentsCommandFeatures(ctx, scope)\n assertCommandFeature(features, 'documents.edit')\n await assertFolderOwnerOrManager(folder.ownerUserId, actorUserId, features)\n if (input.redoExpectation) {\n assertFolderStateMatches(folder, input.redoExpectation.folder)\n } else {\n await enforceCommandOptimisticLockWithGuards(ctx.container, {\n resourceKind: DOCUMENTS_ENTITY_IDS.documentFolder,\n resourceId: folder.id,\n current: folder.updatedAt,\n request: ctx.request ?? null,\n })\n }\n before = snapshotFolder(folder)!\n if (await hasActiveFolderContents({ em, ...scope, folderId: folder.id })) {\n throw new CrudHttpError(409, { error: 'documents.folders.error.delete' })\n }\n const now = nextDocumentVersion(folder.updatedAt)\n folder.deletedAt = now\n folder.updatedAt = now\n }], { transaction: true, label: 'documents.folder.delete' })\n return {\n id: folder.id,\n updatedAt: folder.updatedAt.toISOString(),\n before,\n after: snapshotFolder(folder)!,\n }\n },\n async buildLog({ input, result }) {\n const { translate } = await resolveTranslations()\n if (!result.before) throw new Error('[internal] folder delete produced no before snapshot')\n const redoInput: FolderDeleteCommandInput = {\n ...input,\n redoExpectation: buildFolderDeleteRedoExpectation(result.before, result.after),\n }\n return buildFolderLog(\n translate('documents.audit.folderDeleted', 'Delete folder'),\n input,\n result,\n redoInput,\n )\n },\n async undo({ logEntry, ctx }) {\n const undo = extractUndoPayload<FolderUndoPayload>(logEntry)\n if (!undo?.before || !undo.after) return\n const input = folderDeleteCommandSchema.parse(readCommandRedoInput(logEntry))\n const scope = resolveDocumentsCommandScope(ctx, input)\n const actorUserId = resolveDocumentsCommandActor(ctx)\n const em = resolveDocumentsCommandEntityManager(ctx)\n await withAtomicFlush(em, [async () => {\n await acquireFolderHierarchyMutationLock(em, scope)\n const folder = await loadLockedFolder(em, input.id, scope, true)\n const features = await resolveDocumentsCommandFeatures(ctx, scope)\n assertCommandFeature(features, 'documents.edit')\n await assertFolderOwnerOrManager(undo.before!.ownerUserId, actorUserId, features)\n assertVersionedSnapshot(folder, undo.after, DOCUMENTS_ENTITY_IDS.documentFolder)\n await assertWritableParent(em, undo.before!.parentFolderId, scope, actorUserId, features)\n await assertValidPlacement(em, scope, input.id, undo.before!.parentFolderId)\n if (folder) {\n applyFolderSnapshot(\n folder,\n undo.before!,\n input.redoExpectation?.folder.updatedAt,\n )\n }\n }], { transaction: true, label: 'documents.folder.delete.undo' })\n },\n}\n\nregisterCommand(createFolderCommand)\nregisterCommand(updateFolderCommand)\nregisterCommand(deleteFolderCommand)\n\nexport { createFolderCommand, updateFolderCommand, deleteFolderCommand }\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { LockMode } from '@mikro-orm/core'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { isDeepStrictEqual } from 'node:util'\nimport { z } from 'zod'\nimport { registerCommand, type CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport { extractUndoPayload } from '@open-mercato/shared/lib/commands/undo'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { enforceCommandOptimisticLockWithGuards } from '@open-mercato/shared/lib/crud/optimistic-lock-command'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { hasAllFeatures } from '@open-mercato/shared/lib/auth/featureMatch'\nimport { DocumentFolder } from '../data/entities'\nimport { documentFolderCreateSchema, documentFolderUpdateSchema } from '../data/validators'\nimport { DOCUMENTS_ENTITY_IDS, DOCUMENTS_MAX_FOLDERS_PER_ORGANIZATION } from '../lib/constants'\nimport { acquireFolderHierarchyMutationLock } from '../lib/folderHierarchySerialization'\nimport { getFolderPlacementIssue, hasActiveFolderContents } from '../lib/visibility'\nimport {\n assertCommandFeature,\n resolveDocumentsCommandActor,\n resolveDocumentsCommandEntityManager,\n resolveDocumentsCommandFeatures,\n resolveDocumentsCommandScope,\n type DocumentsCommandScope,\n} from './shared'\nimport {\n assertVersionedSnapshot,\n documentsScopedCommandSchema,\n nextDocumentVersion,\n readCommandRedoInput,\n} from './mutation-helpers'\n\nconst folderSnapshotSchema = z.object({\n id: z.string().uuid(),\n tenantId: z.string().uuid(),\n organizationId: z.string().uuid(),\n name: z.string(),\n parentFolderId: z.string().uuid().nullable(),\n ownerUserId: z.string().uuid(),\n createdAt: z.string().datetime(),\n updatedAt: z.string().datetime(),\n deletedAt: z.string().datetime().nullable(),\n})\n\nconst folderUpdateRedoExpectationSchema = z.object({\n kind: z.literal('folder-update-post-undo'),\n folder: folderSnapshotSchema,\n})\n\nconst folderDeleteRedoExpectationSchema = z.object({\n kind: z.literal('folder-delete-post-undo'),\n folder: folderSnapshotSchema,\n})\n\nexport const folderCreateCommandSchema = documentsScopedCommandSchema\n .merge(documentFolderCreateSchema)\n .extend({ folderId: z.string().uuid() })\n\nexport const folderUpdateCommandSchema = documentsScopedCommandSchema\n .merge(documentFolderUpdateSchema)\n .extend({ redoExpectation: folderUpdateRedoExpectationSchema.optional() })\n\nexport const folderDeleteCommandSchema = documentsScopedCommandSchema.extend({\n id: z.string().uuid(),\n redoExpectation: folderDeleteRedoExpectationSchema.optional(),\n})\n\nexport type FolderCreateCommandInput = z.infer<typeof folderCreateCommandSchema>\nexport type FolderUpdateCommandInput = z.infer<typeof folderUpdateCommandSchema>\nexport type FolderDeleteCommandInput = z.infer<typeof folderDeleteCommandSchema>\n\ntype FolderSnapshot = z.infer<typeof folderSnapshotSchema>\n\ntype FolderUndoPayload = {\n before?: FolderSnapshot | null\n after?: FolderSnapshot | null\n}\n\ntype FolderCommandResult = {\n id: string\n updatedAt: string\n before: FolderSnapshot | null\n after: FolderSnapshot\n}\n\nfunction snapshotFolder(folder: DocumentFolder | null): FolderSnapshot | null {\n if (!folder) return null\n return {\n id: folder.id,\n tenantId: folder.tenantId,\n organizationId: folder.organizationId,\n name: folder.name,\n parentFolderId: folder.parentFolderId ?? null,\n ownerUserId: folder.ownerUserId,\n createdAt: folder.createdAt.toISOString(),\n updatedAt: folder.updatedAt.toISOString(),\n deletedAt: folder.deletedAt?.toISOString() ?? null,\n }\n}\n\nfunction changedError(): CrudHttpError {\n return new CrudHttpError(409, { error: 'Record changed by another user' })\n}\n\nfunction nextSnapshotVersion(updatedAt: string): string {\n return nextDocumentVersion(new Date(updatedAt), new Date(0)).toISOString()\n}\n\nfunction assertFolderStateMatches(folder: DocumentFolder, expected: FolderSnapshot): void {\n if (!isDeepStrictEqual(snapshotFolder(folder), expected)) throw changedError()\n}\n\nfunction resolveExactUndoVersion(current: Date, expectedUpdatedAt?: string): Date {\n if (!expectedUpdatedAt) return nextDocumentVersion(current)\n const expected = new Date(expectedUpdatedAt)\n if (!Number.isFinite(expected.getTime()) || expected.getTime() <= current.getTime()) {\n throw changedError()\n }\n return expected\n}\n\nfunction buildFolderUpdateRedoExpectation(\n before: FolderSnapshot,\n after: FolderSnapshot,\n): z.infer<typeof folderUpdateRedoExpectationSchema> {\n return {\n kind: 'folder-update-post-undo',\n folder: { ...before, updatedAt: nextSnapshotVersion(after.updatedAt) },\n }\n}\n\nfunction buildFolderDeleteRedoExpectation(\n before: FolderSnapshot,\n after: FolderSnapshot,\n): z.infer<typeof folderDeleteRedoExpectationSchema> {\n return {\n kind: 'folder-delete-post-undo',\n folder: { ...before, updatedAt: nextSnapshotVersion(after.updatedAt) },\n }\n}\n\nasync function loadLockedFolder(\n em: EntityManager,\n id: string,\n scope: DocumentsCommandScope,\n includeDeleted = false,\n): Promise<DocumentFolder | null> {\n return findOneWithDecryption(\n em,\n DocumentFolder,\n {\n id,\n ...scope,\n ...(includeDeleted ? {} : { deletedAt: null }),\n },\n {\n lockMode: LockMode.PESSIMISTIC_WRITE,\n ...(includeDeleted ? { filters: false } : {}),\n },\n scope,\n )\n}\n\nasync function assertFolderOwnerOrManager(\n ownerUserId: string,\n actorUserId: string,\n features: readonly string[],\n): Promise<void> {\n if (ownerUserId === actorUserId || hasAllFeatures(['documents.manage'], Array.from(features))) return\n throw new CrudHttpError(403, { error: 'Forbidden' })\n}\n\nasync function assertWritableParent(\n em: EntityManager,\n parentFolderId: string | null | undefined,\n scope: DocumentsCommandScope,\n actorUserId: string,\n features: readonly string[],\n): Promise<void> {\n if (!parentFolderId) return\n const parent = await loadLockedFolder(em, parentFolderId, scope)\n if (!parent) throw new CrudHttpError(404, { error: 'documents.folders.notFound' })\n await assertFolderOwnerOrManager(parent.ownerUserId, actorUserId, features)\n}\n\n/**\n * Call only while holding the folder hierarchy mutation lock, so the count and\n * the insert that follows it cannot interleave with a competing create.\n */\nasync function assertOrganizationFolderCapacity(\n em: EntityManager,\n scope: DocumentsCommandScope,\n): Promise<void> {\n const activeCount = await em.count(DocumentFolder, { ...scope, deletedAt: null })\n if (activeCount < DOCUMENTS_MAX_FOLDERS_PER_ORGANIZATION) return\n throw new CrudHttpError(422, { error: 'documents.errors.folderLimitReached' })\n}\n\nasync function assertValidPlacement(\n em: EntityManager,\n scope: DocumentsCommandScope,\n folderId: string | null,\n parentFolderId: string | null,\n): Promise<void> {\n const issue = await getFolderPlacementIssue({ em, ...scope, folderId, parentFolderId })\n if (issue) throw new CrudHttpError(400, { error: 'documents.folders.error.invalidPlacement' })\n}\n\nfunction applyFolderSnapshot(\n folder: DocumentFolder,\n snapshot: FolderSnapshot,\n expectedUpdatedAt?: string,\n): void {\n folder.name = snapshot.name\n folder.parentFolderId = snapshot.parentFolderId\n folder.ownerUserId = snapshot.ownerUserId\n folder.deletedAt = snapshot.deletedAt ? new Date(snapshot.deletedAt) : null\n folder.updatedAt = resolveExactUndoVersion(folder.updatedAt, expectedUpdatedAt)\n}\n\nfunction buildFolderLog(\n actionLabel: string,\n input: DocumentsCommandScope,\n result: FolderCommandResult,\n redoInput?: FolderUpdateCommandInput | FolderDeleteCommandInput,\n) {\n return {\n actionLabel,\n resourceKind: DOCUMENTS_ENTITY_IDS.documentFolder,\n resourceId: result.id,\n tenantId: input.tenantId,\n organizationId: input.organizationId,\n snapshotBefore: result.before,\n snapshotAfter: result.after,\n payload: {\n undo: { before: result.before, after: result.after } satisfies FolderUndoPayload,\n ...(redoInput ? { __redoInput: redoInput } : {}),\n },\n }\n}\n\nconst createFolderCommand: CommandHandler<FolderCreateCommandInput, FolderCommandResult> = {\n id: 'documents.folder.create',\n async execute(rawInput, ctx) {\n const input = folderCreateCommandSchema.parse(rawInput)\n const scope = resolveDocumentsCommandScope(ctx, input)\n const actorUserId = resolveDocumentsCommandActor(ctx)\n const em = resolveDocumentsCommandEntityManager(ctx)\n let folder!: DocumentFolder\n let before: FolderSnapshot | null = null\n await withAtomicFlush(em, [async () => {\n await acquireFolderHierarchyMutationLock(em, scope)\n const existing = await loadLockedFolder(em, input.folderId, scope, true)\n const features = await resolveDocumentsCommandFeatures(ctx, scope)\n assertCommandFeature(features, 'documents.edit')\n before = snapshotFolder(existing)\n if (existing && !existing.deletedAt) {\n throw new CrudHttpError(409, { error: 'Record changed by another user' })\n }\n await assertOrganizationFolderCapacity(em, scope)\n await assertWritableParent(em, input.parentFolderId ?? null, scope, actorUserId, features)\n await assertValidPlacement(em, scope, null, input.parentFolderId ?? null)\n folder = existing ?? em.create(DocumentFolder, {\n id: input.folderId,\n ...scope,\n name: input.name,\n parentFolderId: input.parentFolderId ?? null,\n ownerUserId: actorUserId,\n })\n if (!existing) em.persist(folder)\n folder.name = input.name\n folder.parentFolderId = input.parentFolderId ?? null\n folder.ownerUserId = actorUserId\n folder.deletedAt = null\n if (existing) folder.updatedAt = nextDocumentVersion(folder.updatedAt)\n }], { transaction: true, label: 'documents.folder.create' })\n return {\n id: folder.id,\n updatedAt: folder.updatedAt.toISOString(),\n before,\n after: snapshotFolder(folder)!,\n }\n },\n async buildLog({ input, result }) {\n const { translate } = await resolveTranslations()\n return buildFolderLog(\n translate('documents.audit.folderCreated', 'Create folder'),\n input,\n result,\n )\n },\n async undo({ logEntry, ctx }) {\n const undo = extractUndoPayload<FolderUndoPayload>(logEntry)\n if (!undo?.after) return\n const input = folderCreateCommandSchema.parse(readCommandRedoInput(logEntry))\n const scope = resolveDocumentsCommandScope(ctx, input)\n const actorUserId = resolveDocumentsCommandActor(ctx)\n const em = resolveDocumentsCommandEntityManager(ctx)\n await withAtomicFlush(em, [async () => {\n await acquireFolderHierarchyMutationLock(em, scope)\n const folder = await loadLockedFolder(em, input.folderId, scope, true)\n const features = await resolveDocumentsCommandFeatures(ctx, scope)\n assertCommandFeature(features, 'documents.edit')\n await assertFolderOwnerOrManager(undo.after!.ownerUserId, actorUserId, features)\n assertVersionedSnapshot(folder, undo.after, DOCUMENTS_ENTITY_IDS.documentFolder)\n if (await hasActiveFolderContents({ em, ...scope, folderId: input.folderId })) {\n throw new CrudHttpError(409, { error: 'Record changed by another user' })\n }\n if (undo.before && folder) applyFolderSnapshot(folder, undo.before)\n else if (folder) {\n const now = nextDocumentVersion(folder.updatedAt)\n folder.deletedAt = now\n folder.updatedAt = now\n }\n }], { transaction: true, label: 'documents.folder.create.undo' })\n },\n}\n\nconst updateFolderCommand: CommandHandler<FolderUpdateCommandInput, FolderCommandResult> = {\n id: 'documents.folder.update',\n async execute(rawInput, ctx) {\n const input = folderUpdateCommandSchema.parse(rawInput)\n const scope = resolveDocumentsCommandScope(ctx, input)\n const actorUserId = resolveDocumentsCommandActor(ctx)\n const em = resolveDocumentsCommandEntityManager(ctx)\n let folder!: DocumentFolder\n let before!: FolderSnapshot\n await withAtomicFlush(em, [async () => {\n await acquireFolderHierarchyMutationLock(em, scope)\n const loaded = await loadLockedFolder(\n em,\n input.id,\n scope,\n input.redoExpectation !== undefined,\n )\n if (!loaded) throw new CrudHttpError(404, { error: 'documents.folders.notFound' })\n folder = loaded\n const features = await resolveDocumentsCommandFeatures(ctx, scope)\n assertCommandFeature(features, 'documents.edit')\n await assertFolderOwnerOrManager(folder.ownerUserId, actorUserId, features)\n if (input.redoExpectation) {\n assertFolderStateMatches(folder, input.redoExpectation.folder)\n } else {\n await enforceCommandOptimisticLockWithGuards(ctx.container, {\n resourceKind: DOCUMENTS_ENTITY_IDS.documentFolder,\n resourceId: folder.id,\n current: folder.updatedAt,\n request: ctx.request ?? null,\n })\n }\n before = snapshotFolder(folder)!\n if (Object.prototype.hasOwnProperty.call(input, 'parentFolderId')) {\n await assertWritableParent(em, input.parentFolderId ?? null, scope, actorUserId, features)\n await assertValidPlacement(em, scope, folder.id, input.parentFolderId ?? null)\n }\n if (input.name !== undefined) folder.name = input.name\n if (Object.prototype.hasOwnProperty.call(input, 'parentFolderId')) {\n folder.parentFolderId = input.parentFolderId ?? null\n }\n folder.updatedAt = nextDocumentVersion(folder.updatedAt)\n }], { transaction: true, label: 'documents.folder.update' })\n return {\n id: folder.id,\n updatedAt: folder.updatedAt.toISOString(),\n before,\n after: snapshotFolder(folder)!,\n }\n },\n async buildLog({ input, result }) {\n const { translate } = await resolveTranslations()\n if (!result.before) throw new Error('[internal] folder update produced no before snapshot')\n const redoInput: FolderUpdateCommandInput = {\n ...input,\n redoExpectation: buildFolderUpdateRedoExpectation(result.before, result.after),\n }\n return buildFolderLog(\n translate('documents.audit.folderUpdated', 'Update folder'),\n input,\n result,\n redoInput,\n )\n },\n async undo({ logEntry, ctx }) {\n const undo = extractUndoPayload<FolderUndoPayload>(logEntry)\n if (!undo?.before || !undo.after) return\n const before = undo.before\n const after = undo.after\n const input = folderUpdateCommandSchema.parse(readCommandRedoInput(logEntry))\n const scope = resolveDocumentsCommandScope(ctx, input)\n const actorUserId = resolveDocumentsCommandActor(ctx)\n const em = resolveDocumentsCommandEntityManager(ctx)\n await withAtomicFlush(em, [async () => {\n await acquireFolderHierarchyMutationLock(em, scope)\n const folder = await loadLockedFolder(em, input.id, scope)\n if (!folder) throw new CrudHttpError(404, { error: 'documents.folders.notFound' })\n const features = await resolveDocumentsCommandFeatures(ctx, scope)\n assertCommandFeature(features, 'documents.edit')\n await assertFolderOwnerOrManager(folder.ownerUserId, actorUserId, features)\n assertVersionedSnapshot(folder, after, DOCUMENTS_ENTITY_IDS.documentFolder)\n await assertWritableParent(em, before.parentFolderId, scope, actorUserId, features)\n await assertValidPlacement(em, scope, folder.id, before.parentFolderId)\n applyFolderSnapshot(\n folder,\n before,\n input.redoExpectation?.folder.updatedAt,\n )\n }], { transaction: true, label: 'documents.folder.update.undo' })\n },\n}\n\nconst deleteFolderCommand: CommandHandler<FolderDeleteCommandInput, FolderCommandResult> = {\n id: 'documents.folder.delete',\n async execute(rawInput, ctx) {\n const input = folderDeleteCommandSchema.parse(rawInput)\n const scope = resolveDocumentsCommandScope(ctx, input)\n const actorUserId = resolveDocumentsCommandActor(ctx)\n const em = resolveDocumentsCommandEntityManager(ctx)\n let folder!: DocumentFolder\n let before!: FolderSnapshot\n await withAtomicFlush(em, [async () => {\n await acquireFolderHierarchyMutationLock(em, scope)\n const loaded = await loadLockedFolder(\n em,\n input.id,\n scope,\n input.redoExpectation !== undefined,\n )\n if (!loaded) throw new CrudHttpError(404, { error: 'documents.folders.notFound' })\n folder = loaded\n const features = await resolveDocumentsCommandFeatures(ctx, scope)\n assertCommandFeature(features, 'documents.edit')\n await assertFolderOwnerOrManager(folder.ownerUserId, actorUserId, features)\n if (input.redoExpectation) {\n assertFolderStateMatches(folder, input.redoExpectation.folder)\n } else {\n await enforceCommandOptimisticLockWithGuards(ctx.container, {\n resourceKind: DOCUMENTS_ENTITY_IDS.documentFolder,\n resourceId: folder.id,\n current: folder.updatedAt,\n request: ctx.request ?? null,\n })\n }\n before = snapshotFolder(folder)!\n if (await hasActiveFolderContents({ em, ...scope, folderId: folder.id })) {\n throw new CrudHttpError(409, { error: 'documents.folders.error.delete' })\n }\n const now = nextDocumentVersion(folder.updatedAt)\n folder.deletedAt = now\n folder.updatedAt = now\n }], { transaction: true, label: 'documents.folder.delete' })\n return {\n id: folder.id,\n updatedAt: folder.updatedAt.toISOString(),\n before,\n after: snapshotFolder(folder)!,\n }\n },\n async buildLog({ input, result }) {\n const { translate } = await resolveTranslations()\n if (!result.before) throw new Error('[internal] folder delete produced no before snapshot')\n const redoInput: FolderDeleteCommandInput = {\n ...input,\n redoExpectation: buildFolderDeleteRedoExpectation(result.before, result.after),\n }\n return buildFolderLog(\n translate('documents.audit.folderDeleted', 'Delete folder'),\n input,\n result,\n redoInput,\n )\n },\n async undo({ logEntry, ctx }) {\n const undo = extractUndoPayload<FolderUndoPayload>(logEntry)\n if (!undo?.before || !undo.after) return\n const input = folderDeleteCommandSchema.parse(readCommandRedoInput(logEntry))\n const scope = resolveDocumentsCommandScope(ctx, input)\n const actorUserId = resolveDocumentsCommandActor(ctx)\n const em = resolveDocumentsCommandEntityManager(ctx)\n await withAtomicFlush(em, [async () => {\n await acquireFolderHierarchyMutationLock(em, scope)\n const folder = await loadLockedFolder(em, input.id, scope, true)\n const features = await resolveDocumentsCommandFeatures(ctx, scope)\n assertCommandFeature(features, 'documents.edit')\n await assertFolderOwnerOrManager(undo.before!.ownerUserId, actorUserId, features)\n assertVersionedSnapshot(folder, undo.after, DOCUMENTS_ENTITY_IDS.documentFolder)\n await assertOrganizationFolderCapacity(em, scope)\n await assertWritableParent(em, undo.before!.parentFolderId, scope, actorUserId, features)\n await assertValidPlacement(em, scope, input.id, undo.before!.parentFolderId)\n if (folder) {\n applyFolderSnapshot(\n folder,\n undo.before!,\n input.redoExpectation?.folder.updatedAt,\n )\n }\n }], { transaction: true, label: 'documents.folder.delete.undo' })\n },\n}\n\nregisterCommand(createFolderCommand)\nregisterCommand(updateFolderCommand)\nregisterCommand(deleteFolderCommand)\n\nexport { createFolderCommand, updateFolderCommand, deleteFolderCommand }\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-mercato/documents",
|
|
3
|
-
"version": "0.10.1-develop.
|
|
3
|
+
"version": "0.10.1-develop.7982.1.df20d84e85",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -75,8 +75,8 @@
|
|
|
75
75
|
"@hocuspocus/server": "^4.4.0",
|
|
76
76
|
"@hocuspocus/transformer": "^4.3.0",
|
|
77
77
|
"@mikro-orm/core": "^7.1.14",
|
|
78
|
-
"@open-mercato/events": "0.10.1-develop.
|
|
79
|
-
"@open-mercato/ui": "0.10.1-develop.
|
|
78
|
+
"@open-mercato/events": "0.10.1-develop.7982.1.df20d84e85",
|
|
79
|
+
"@open-mercato/ui": "0.10.1-develop.7982.1.df20d84e85",
|
|
80
80
|
"@tiptap/core": "3.32.0",
|
|
81
81
|
"@tiptap/extension-bubble-menu": "3.32.0",
|
|
82
82
|
"@tiptap/extension-collaboration": "3.32.0",
|
|
@@ -112,13 +112,13 @@
|
|
|
112
112
|
},
|
|
113
113
|
"peerDependencies": {
|
|
114
114
|
"@mikro-orm/postgresql": "^7.0.14",
|
|
115
|
-
"@open-mercato/shared": "0.10.1-develop.
|
|
115
|
+
"@open-mercato/shared": "0.10.1-develop.7982.1.df20d84e85",
|
|
116
116
|
"react": "^19.0.0",
|
|
117
117
|
"react-dom": "^19.0.0"
|
|
118
118
|
},
|
|
119
119
|
"devDependencies": {
|
|
120
|
-
"@open-mercato/core": "0.10.1-develop.
|
|
121
|
-
"@open-mercato/shared": "0.10.1-develop.
|
|
120
|
+
"@open-mercato/core": "0.10.1-develop.7982.1.df20d84e85",
|
|
121
|
+
"@open-mercato/shared": "0.10.1-develop.7982.1.df20d84e85",
|
|
122
122
|
"@types/jest": "^30.0.0",
|
|
123
123
|
"@types/pg": "^8.23.1",
|
|
124
124
|
"@types/react": "^19.2.18",
|
|
@@ -257,9 +257,6 @@ const createFolderCommand: CommandHandler<FolderCreateCommandInput, FolderComman
|
|
|
257
257
|
if (existing && !existing.deletedAt) {
|
|
258
258
|
throw new CrudHttpError(409, { error: 'Record changed by another user' })
|
|
259
259
|
}
|
|
260
|
-
// Reviving a soft-deleted row adds an active folder just like a fresh
|
|
261
|
-
// insert, so both paths answer to the same organization-wide cap. Undo
|
|
262
|
-
// stays exempt: it only restores state the organization already held.
|
|
263
260
|
await assertOrganizationFolderCapacity(em, scope)
|
|
264
261
|
await assertWritableParent(em, input.parentFolderId ?? null, scope, actorUserId, features)
|
|
265
262
|
await assertValidPlacement(em, scope, null, input.parentFolderId ?? null)
|
|
@@ -486,6 +483,7 @@ const deleteFolderCommand: CommandHandler<FolderDeleteCommandInput, FolderComman
|
|
|
486
483
|
assertCommandFeature(features, 'documents.edit')
|
|
487
484
|
await assertFolderOwnerOrManager(undo.before!.ownerUserId, actorUserId, features)
|
|
488
485
|
assertVersionedSnapshot(folder, undo.after, DOCUMENTS_ENTITY_IDS.documentFolder)
|
|
486
|
+
await assertOrganizationFolderCapacity(em, scope)
|
|
489
487
|
await assertWritableParent(em, undo.before!.parentFolderId, scope, actorUserId, features)
|
|
490
488
|
await assertValidPlacement(em, scope, input.id, undo.before!.parentFolderId)
|
|
491
489
|
if (folder) {
|