Skip to content

Commit b400a08

Browse files
committed
fix: app id shortcut batch
1 parent b99d7be commit b400a08

2 files changed

Lines changed: 101 additions & 4 deletions

File tree

extensions/fsv2/src/controllers/FSController.ts

Lines changed: 100 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ import type {
3737

3838
const { Controller, ExtensionController, HttpError, Post } = extension.import('extensionController');
3939
const { Context } = extension.import('core');
40+
const getApp = extension.import('core').util.helpers.get_app as (
41+
query: { uid: string },
42+
) => Promise<{ id?: unknown } | null>;
4043
class UploadProgressTracker implements UploadProgressTrackerLike {
4144
total = 0;
4245
progress = 0;
@@ -84,6 +87,7 @@ export class FSController extends ExtensionController {
8487
const storageAllowanceMax = this.#getStorageAllowanceMaxOverride(req);
8588
const requestBody = this.#withGuiMetadata(req.body, req.body);
8689
requestBody.fileMetadata = this.#normalizeFileMetadataPath(req, requestBody.fileMetadata, requestBody);
90+
requestBody.fileMetadata = await this.#resolveAssociatedAppMetadata(requestBody.fileMetadata, requestBody);
8791
await this.#assertWriteAccess(req, requestBody.fileMetadata, {
8892
pathAlreadyNormalized: true,
8993
});
@@ -116,16 +120,22 @@ export class FSController extends ExtensionController {
116120
async startBatchWrites (req: Request<RouteParams, null, SignedWriteRequest[]>, res: Response<SignedWriteResponse[]>) {
117121
const userId = this.#getActorUserId(req);
118122
const storageAllowanceMax = this.#getStorageAllowanceMaxOverride(req);
123+
const appUidLookupCache = new Map<string, Promise<number | null>>();
119124
const requests = Array.isArray(req.body)
120-
? req.body.map((requestBody) => {
125+
? await Promise.all(req.body.map(async (requestBody) => {
121126
const normalizedRequestBody = this.#withGuiMetadata(requestBody, req.body);
122127
normalizedRequestBody.fileMetadata = this.#normalizeFileMetadataPath(
123128
req,
124129
normalizedRequestBody.fileMetadata,
125130
normalizedRequestBody,
126131
);
132+
normalizedRequestBody.fileMetadata = await this.#resolveAssociatedAppMetadata(
133+
normalizedRequestBody.fileMetadata,
134+
normalizedRequestBody,
135+
appUidLookupCache,
136+
);
127137
return normalizedRequestBody;
128-
})
138+
}))
129139
: [];
130140
await this.#assertBatchWriteAccess(
131141
req,
@@ -260,6 +270,7 @@ export class FSController extends ExtensionController {
260270
const storageAllowanceMax = this.#getStorageAllowanceMaxOverride(req);
261271
const requestBody = this.#withGuiMetadata(req.body, req.body);
262272
requestBody.fileMetadata = this.#normalizeFileMetadataPath(req, requestBody.fileMetadata, requestBody);
273+
requestBody.fileMetadata = await this.#resolveAssociatedAppMetadata(requestBody.fileMetadata, requestBody);
263274
await this.#assertWriteAccess(req, requestBody.fileMetadata, {
264275
pathAlreadyNormalized: true,
265276
});
@@ -285,6 +296,7 @@ export class FSController extends ExtensionController {
285296
const userId = this.#getActorUserId(req);
286297
const storageAllowanceMax = this.#getStorageAllowanceMaxOverride(req);
287298
const requestMode = this.#resolveBatchWriteRequestMode(req);
299+
const appUidLookupCache = new Map<string, Promise<number | null>>();
288300
if ( requestMode === 'multipart' ) {
289301
let parsedManifest: ParsedMultipartBatchManifest | null = null;
290302
let preparedBatch: PreparedBatchWrite | null = null;
@@ -341,6 +353,17 @@ export class FSController extends ExtensionController {
341353
if ( ! parsedManifest ) {
342354
throw new HttpError(400, 'Batch write manifest is missing');
343355
}
356+
parsedManifest = {
357+
...parsedManifest,
358+
items: await Promise.all(parsedManifest.items.map(async (item) => ({
359+
...item,
360+
fileMetadata: await this.#resolveAssociatedAppMetadata(
361+
item.fileMetadata,
362+
item,
363+
appUidLookupCache,
364+
),
365+
}))),
366+
};
344367
const activeManifestItems = parsedManifest.items
345368
.filter((item) => !parsedManifest?.ignoredItemIndexes?.has(item.index));
346369

@@ -490,15 +513,20 @@ export class FSController extends ExtensionController {
490513
}
491514

492515
const requests = Array.isArray(req.body)
493-
? req.body.map((requestBody) => {
516+
? await Promise.all(req.body.map(async (requestBody) => {
494517
const normalizedRequestBody = this.#withGuiMetadata(requestBody, req.body);
495518
normalizedRequestBody.fileMetadata = this.#normalizeFileMetadataPath(
496519
req,
497520
normalizedRequestBody.fileMetadata,
498521
normalizedRequestBody,
499522
);
523+
normalizedRequestBody.fileMetadata = await this.#resolveAssociatedAppMetadata(
524+
normalizedRequestBody.fileMetadata,
525+
normalizedRequestBody,
526+
appUidLookupCache,
527+
);
500528
return normalizedRequestBody;
501-
})
529+
}))
502530
: [];
503531
const filteredRequests = requests.filter((requestBody) => {
504532
return !this.#shouldIgnoreUploadPath(requestBody.fileMetadata.path);
@@ -796,9 +824,77 @@ export class FSController extends ExtensionController {
796824
normalizedFileMetadata.bucketRegion = bucketRegion;
797825
}
798826

827+
const associatedAppId = this.#toNumber(this.#firstDefined(
828+
metadataRecord.associatedAppId,
829+
metadataRecord.associated_app_id,
830+
fallbackRecord.associatedAppId,
831+
fallbackRecord.associated_app_id,
832+
));
833+
if ( associatedAppId !== undefined ) {
834+
normalizedFileMetadata.associatedAppId = associatedAppId;
835+
}
836+
799837
return normalizedFileMetadata as unknown as FSEntryWriteInput;
800838
}
801839

840+
async #resolveAssociatedAppMetadata (
841+
fileMetadata: FSEntryWriteInput,
842+
fallbackSource?: unknown,
843+
appUidLookupCache?: Map<string, Promise<number | null>>,
844+
): Promise<FSEntryWriteInput> {
845+
const metadataRecord = this.#toObjectRecord(fileMetadata);
846+
const fallbackRecord = this.#toObjectRecord(fallbackSource);
847+
848+
const associatedAppId = this.#toNumber(this.#firstDefined(
849+
metadataRecord.associatedAppId,
850+
metadataRecord.associated_app_id,
851+
fallbackRecord.associatedAppId,
852+
fallbackRecord.associated_app_id,
853+
));
854+
if ( associatedAppId !== undefined ) {
855+
return {
856+
...fileMetadata,
857+
associatedAppId,
858+
};
859+
}
860+
861+
const appUid = this.#firstDefined(
862+
metadataRecord.appUID,
863+
metadataRecord.appUid,
864+
metadataRecord.app_uid,
865+
fallbackRecord.appUID,
866+
fallbackRecord.appUid,
867+
fallbackRecord.app_uid,
868+
);
869+
if ( typeof appUid !== 'string' || appUid.trim().length === 0 ) {
870+
return fileMetadata;
871+
}
872+
873+
const normalizedAppUid = appUid.trim();
874+
const lookupPromise = (() => {
875+
const cachedLookup = appUidLookupCache?.get(normalizedAppUid);
876+
if ( cachedLookup ) {
877+
return cachedLookup;
878+
}
879+
880+
const createdLookupPromise = (async () => {
881+
const app = await getApp({ uid: normalizedAppUid });
882+
return this.#toNumber(app?.id) ?? null;
883+
})();
884+
appUidLookupCache?.set(normalizedAppUid, createdLookupPromise);
885+
return createdLookupPromise;
886+
})();
887+
888+
const resolvedAppId = await lookupPromise;
889+
if ( resolvedAppId === null ) {
890+
return fileMetadata;
891+
}
892+
return {
893+
...fileMetadata,
894+
associatedAppId: resolvedAppId,
895+
};
896+
}
897+
802898
#toStorageCapacityCandidate (value: unknown): number | undefined {
803899
const capacity = Number(value);
804900
if ( !Number.isFinite(capacity) || capacity < 0 ) {

src/puter-js/src/modules/FileSystem/operations/upload.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,7 @@ const upload = async function (items, dirPath, options = {}) {
718718
overwrite: overwriteEnabled,
719719
dedupeName: options.dedupeName ?? true,
720720
createMissingParents: shouldCreateMissingParents,
721+
app_uid: options.appUID,
721722
};
722723

723724
return {

0 commit comments

Comments
 (0)