@pai/files-mongo
MongoDB GridFS-backed FileProvider implementation.
Package: @pai/files-mongo
GridFS-backed FileProvider for persistent MongoDB deployments. It stores
attachment bytes in a GridFS bucket and stores PAI scope metadata in the GridFS
file document under metadata.pai.
Use it when your deployment already uses MongoDB for durable application state and you want attachments to live beside that data rather than on local disk.
import { createMongoFileProvider } from "@pai/files-mongo";
export const files = createMongoFileProvider({
url: process.env.MONGO_URL!,
bucketName: "pai_files",
});Inject an existing Mongo database when the host application already owns the connection lifecycle:
import { createMongoFileProvider } from "@pai/files-mongo";
export const files = createMongoFileProvider({
db: mongoose.connection.db,
bucketName: "fs",
});Options
type MongoFileProviderOptions =
| {
url: string;
dbName?: string;
bucketName?: string;
chunkSizeBytes?: number;
generateId?: () => ObjectId | string;
parseId?: (fileId: string) => ObjectId | string;
stringifyId?: (id: ObjectId | string) => string;
beforeSave?: FileProviderBeforeSaveHook;
maxFileBytes?: number | false;
metadata?: (input: SaveFileInput) => Document | Promise<Document | undefined>;
fileDocument?: (context: MongoFileDocumentContext) => Document | Promise<Document | undefined>;
isReadable?: (context: MongoFileAccessContext) => boolean | Promise<boolean>;
}
| {
db: MongoFileProviderDatabase;
bucket?: MongoGridFsBucket;
bucketName?: string;
chunkSizeBytes?: number;
generateId?: () => ObjectId | string;
parseId?: (fileId: string) => ObjectId | string;
stringifyId?: (id: ObjectId | string) => string;
beforeSave?: FileProviderBeforeSaveHook;
maxFileBytes?: number | false;
metadata?: (input: SaveFileInput) => Document | Promise<Document | undefined>;
fileDocument?: (context: MongoFileDocumentContext) => Document | Promise<Document | undefined>;
isReadable?: (context: MongoFileAccessContext) => boolean | Promise<boolean>;
};bucketName defaults to "pai_files". Pass "fs" to use the conventional
legacy GridFS bucket collections fs.files and fs.chunks.
beforeSave runs before GridFS upload. Use it for synchronous file validation
or normalization, such as virus scanning before bytes are persisted.
When set, maxFileBytes rejects oversized saves while bytes are streamed into GridFS.
fileDocument lets host applications merge top-level fields into the GridFS
file document after upload. Use it for application-owned metadata such as owner,
organization, scan status, or ACL data. The provider-owned metadata.pai
namespace is always restored after this hook and cannot be overridden.
isReadable lets host applications hide files that exist in GridFS but should
not be exposed through PAI yet, such as files still awaiting malware scanning.
The same gate applies to list, so an enumerated page never exposes a file that
head or read would hide.
Listing And Indexes
list({ scopeKey, userKey?, threadId?, limit, pageToken? }) returns
newest-first file metadata from one exact scope. userKey selects immutable
creator provenance under metadata.pai.userKey; it is not an authorization
rule. threadId selects the origin association under
metadata.pai.threadId; transcripts remain the source of truth for every
thread that references a file.
initialize() creates compound indexes for the four portable query shapes:
{ "metadata.pai.scopeKey": 1, uploadDate: -1, _id: -1 }
{
"metadata.pai.scopeKey": 1,
"metadata.pai.threadId": 1,
uploadDate: -1,
_id: -1,
}
{
"metadata.pai.scopeKey": 1,
"metadata.pai.userKey": 1,
uploadDate: -1,
_id: -1,
}
{
"metadata.pai.scopeKey": 1,
"metadata.pai.userKey": 1,
"metadata.pai.threadId": 1,
uploadDate: -1,
_id: -1,
}Conformance
createMongoFileProvider passes the full @pai/files/test conformance suite:
import { createFileProviderConformanceSuite } from "@pai/files/test";
import { createMongoFileProvider } from "@pai/files-mongo";
createFileProviderConformanceSuite({
name: "createMongoFileProvider",
createProvider: () =>
createMongoFileProvider({
url: process.env.MONGO_URL!,
dbName: "pai",
bucketName: "pai_files_test",
}),
});