mirror of
https://github.com/wassname/talk.git
synced 2026-07-13 05:17:42 +08:00
feat: asset url query
This commit is contained in:
+100
-30
@@ -1,10 +1,10 @@
|
||||
import dotize from "dotize";
|
||||
import { defaults } from "lodash";
|
||||
import { Db } from "mongodb";
|
||||
import uuid from "uuid";
|
||||
|
||||
import { Omit } from "talk-common/types";
|
||||
import { TenantResource } from "talk-server/models/tenant";
|
||||
import uuid from "uuid";
|
||||
import Query from "./query";
|
||||
|
||||
function collection(db: Db) {
|
||||
return db.collection<Readonly<Asset>>("assets");
|
||||
@@ -27,48 +27,103 @@ export interface Asset extends TenantResource {
|
||||
created_at: Date;
|
||||
}
|
||||
|
||||
export type CreateAssetInput = Pick<Asset, "id" | "url">;
|
||||
export interface UpsertAssetInput {
|
||||
id?: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
export async function createAsset(
|
||||
export async function upsertAsset(
|
||||
db: Db,
|
||||
tenantID: string,
|
||||
input: CreateAssetInput
|
||||
{ id, url }: UpsertAssetInput
|
||||
) {
|
||||
const now = new Date();
|
||||
|
||||
// Construct the filter.
|
||||
const query = new Query<Asset>(collection(db)).where({
|
||||
tenant_id: tenantID,
|
||||
});
|
||||
if (input.id) {
|
||||
query.where({ id: input.id });
|
||||
} else {
|
||||
query.where({ url: input.url });
|
||||
}
|
||||
// TODO: verify that the url for the given Asset is whitelisted by the tenant.
|
||||
|
||||
// Craft the update object.
|
||||
// Create the asset, optionally sourcing the id from the input, additionally
|
||||
// porting in the tenant_id.
|
||||
const update: { $setOnInsert: Asset } = {
|
||||
$setOnInsert: defaults(input, {
|
||||
id: uuid.v4(),
|
||||
tenant_id: tenantID,
|
||||
created_at: now,
|
||||
}),
|
||||
$setOnInsert: defaults(
|
||||
{
|
||||
url,
|
||||
tenant_id: tenantID,
|
||||
created_at: now,
|
||||
},
|
||||
{ id },
|
||||
{
|
||||
id: uuid.v4(),
|
||||
}
|
||||
),
|
||||
};
|
||||
|
||||
// Perform the upsert operation.
|
||||
const result = await collection(db).findOneAndUpdate(query.filter, update, {
|
||||
// Create the object if it doesn't already exist.
|
||||
upsert: true,
|
||||
// False to return the updated document instead of the original
|
||||
// document.
|
||||
returnOriginal: false,
|
||||
});
|
||||
// Perform the find and update operation to try and find and or create the
|
||||
// asset.
|
||||
const { value: asset } = await collection(db).findOneAndUpdate(
|
||||
{ url },
|
||||
update,
|
||||
{
|
||||
// Create the object if it doesn't already exist.
|
||||
upsert: true,
|
||||
|
||||
return result.value || null;
|
||||
// False to return the updated document instead of the original
|
||||
// document.
|
||||
returnOriginal: false,
|
||||
}
|
||||
);
|
||||
if (!asset) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!asset.scraped) {
|
||||
// TODO: create scrape job to collect asset metadata
|
||||
}
|
||||
|
||||
return asset;
|
||||
}
|
||||
|
||||
export interface FindOrCreateAssetInput {
|
||||
id?: string;
|
||||
url?: string;
|
||||
}
|
||||
|
||||
export async function findOrCreateAsset(
|
||||
db: Db,
|
||||
tenantID: string,
|
||||
{ id, url }: FindOrCreateAssetInput
|
||||
) {
|
||||
if (id) {
|
||||
if (url) {
|
||||
// The URL was specified, this is an upsert operation.
|
||||
return upsertAsset(db, tenantID, {
|
||||
id,
|
||||
url,
|
||||
});
|
||||
}
|
||||
|
||||
// The URL was not specified, this is a lookup operation.
|
||||
return retrieveAsset(db, tenantID, id);
|
||||
}
|
||||
|
||||
// The ID was not specified, this is an upsert operation. Check to see that
|
||||
// the URL exists.
|
||||
if (!url) {
|
||||
throw new Error("cannot upsert an asset without the url");
|
||||
}
|
||||
|
||||
return upsertAsset(db, tenantID, { url });
|
||||
}
|
||||
|
||||
export async function retrieveAssetByURL(
|
||||
db: Db,
|
||||
tenantID: string,
|
||||
url: string
|
||||
) {
|
||||
return collection(db).findOne({ url, tenant_id: tenantID });
|
||||
}
|
||||
|
||||
export async function retrieveAsset(db: Db, tenantID: string, id: string) {
|
||||
return await collection(db).findOne({ id, tenant_id: tenantID });
|
||||
return collection(db).findOne({ id, tenant_id: tenantID });
|
||||
}
|
||||
|
||||
export async function retrieveManyAssets(
|
||||
@@ -86,6 +141,21 @@ export async function retrieveManyAssets(
|
||||
return ids.map(id => assets.find(asset => asset.id === id) || null);
|
||||
}
|
||||
|
||||
export async function retrieveManyAssetsByURL(
|
||||
db: Db,
|
||||
tenantID: string,
|
||||
urls: string[]
|
||||
) {
|
||||
const cursor = await collection(db).find({
|
||||
url: { $in: urls },
|
||||
tenant_id: tenantID,
|
||||
});
|
||||
|
||||
const assets = await cursor.toArray();
|
||||
|
||||
return urls.map(url => assets.find(asset => asset.url === url) || null);
|
||||
}
|
||||
|
||||
export type UpdateAssetInput = Omit<
|
||||
Partial<Asset>,
|
||||
"id" | "tenant_id" | "url" | "created_at"
|
||||
|
||||
Reference in New Issue
Block a user