replace bigint with number
This commit is contained in:
parent
c96de5ccbc
commit
87059c37a0
@ -173,6 +173,31 @@ export const getAndSaveProFeatures = async (
|
|||||||
pluginVersion: string,
|
pluginVersion: string,
|
||||||
saveUpdatedConfigFunc: () => Promise<any> | undefined
|
saveUpdatedConfigFunc: () => Promise<any> | undefined
|
||||||
) => {
|
) => {
|
||||||
|
const features = [
|
||||||
|
"feature-smart_conflict",
|
||||||
|
"feature-onedrive_full",
|
||||||
|
"feature-google_drive",
|
||||||
|
"feature-box",
|
||||||
|
"feature-pcloud",
|
||||||
|
"feature-yandex_disk",
|
||||||
|
"feature-koofr",
|
||||||
|
"feature-azure_blob_storage",
|
||||||
|
];
|
||||||
|
|
||||||
|
const res = {
|
||||||
|
proFeatures: features.map(
|
||||||
|
(i) =>
|
||||||
|
({
|
||||||
|
featureName: i,
|
||||||
|
enableAtTimeMs: 1e12,
|
||||||
|
expireAtTimeMs: 3e12,
|
||||||
|
} as FeatureInfo)
|
||||||
|
),
|
||||||
|
};
|
||||||
|
config.enabledProFeatures = res.proFeatures;
|
||||||
|
await saveUpdatedConfigFunc?.();
|
||||||
|
return res;
|
||||||
|
|
||||||
const access = await getAccessToken(config, saveUpdatedConfigFunc);
|
const access = await getAccessToken(config, saveUpdatedConfigFunc);
|
||||||
|
|
||||||
const resp1 = await fetch(`${site}/api/v1/pro/list`, {
|
const resp1 = await fetch(`${site}/api/v1/pro/list`, {
|
||||||
|
|||||||
@ -37,8 +37,8 @@ export type PRO_FEATURE_TYPE =
|
|||||||
|
|
||||||
export interface FeatureInfo {
|
export interface FeatureInfo {
|
||||||
featureName: PRO_FEATURE_TYPE;
|
featureName: PRO_FEATURE_TYPE;
|
||||||
enableAtTimeMs: bigint;
|
enableAtTimeMs: number;
|
||||||
expireAtTimeMs: bigint;
|
expireAtTimeMs: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProConfig {
|
export interface ProConfig {
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
// https://developers.google.com/identity/protocols/oauth2/javascript-implicit-flow
|
// https://developers.google.com/identity/protocols/oauth2/javascript-implicit-flow
|
||||||
// https://developers.google.com/identity/protocols/oauth2/web-server
|
// https://developers.google.com/identity/protocols/oauth2/web-server
|
||||||
|
|
||||||
import { entries } from "lodash";
|
|
||||||
import * as mime from "mime-types";
|
import * as mime from "mime-types";
|
||||||
import { requestUrl } from "obsidian";
|
import { requestUrl } from "obsidian";
|
||||||
import PQueue from "p-queue";
|
import PQueue from "p-queue";
|
||||||
@ -177,6 +176,7 @@ export class FakeFsGoogleDrive extends FakeFs {
|
|||||||
keyToGDEntity: Record<string, GDEntity>;
|
keyToGDEntity: Record<string, GDEntity>;
|
||||||
|
|
||||||
baseDirID: string;
|
baseDirID: string;
|
||||||
|
ready = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
googleDriveConfig: GoogleDriveConfig,
|
googleDriveConfig: GoogleDriveConfig,
|
||||||
@ -199,13 +199,17 @@ export class FakeFsGoogleDrive extends FakeFs {
|
|||||||
await this._getAccessToken();
|
await this._getAccessToken();
|
||||||
|
|
||||||
// check vault folder exists
|
// check vault folder exists
|
||||||
if (this.vaultFolderExists) {
|
if (!this.vaultFolderExists) {
|
||||||
// pass
|
const q = `name='${this.remoteBaseDir}' and mimeType='application/vnd.google-apps.folder' and trashed=false`;
|
||||||
} else {
|
const url = new URL("https://www.googleapis.com/drive/v3/files");
|
||||||
const q = encodeURIComponent(
|
url.searchParams.set("q", q);
|
||||||
`name='${this.remoteBaseDir}' and mimeType='application/vnd.google-apps.folder' and trashed=false`
|
url.searchParams.set("pageSize", "1000");
|
||||||
|
url.searchParams.set(
|
||||||
|
"fields",
|
||||||
|
"kind,nextPageToken," +
|
||||||
|
"files(kind,fileExtension,md5Checksum,mimeType,parents,size,spaces,id,name,trashed,createdTime,modifiedTime,quotaBytesUsed,originalFilename,fullFileExtension,sha1Checksum,sha256Checksum)"
|
||||||
);
|
);
|
||||||
const url: string = `https://www.googleapis.com/drive/v3/files?q=${q}&pageSize=1000&fields=kind,nextPageToken,files(kind,fileExtension,md5Checksum,mimeType,parents,size,spaces,id,name,trashed,createdTime,modifiedTime,quotaBytesUsed,originalFilename,fullFileExtension,sha1Checksum,sha256Checksum)`;
|
url.searchParams.set("orderBy", "modifiedTime desc");
|
||||||
const k = await fetch(url, {
|
const k = await fetch(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
@ -274,8 +278,16 @@ export class FakeFsGoogleDrive extends FakeFs {
|
|||||||
/**
|
/**
|
||||||
* https://developers.google.com/drive/api/reference/rest/v3/files/list
|
* https://developers.google.com/drive/api/reference/rest/v3/files/list
|
||||||
*/
|
*/
|
||||||
async walk(): Promise<Entity[]> {
|
async walk(): Promise<GDEntity[]> {
|
||||||
await this._init();
|
await this._init();
|
||||||
|
|
||||||
|
// const allFiles = await this._listAllFiles();
|
||||||
|
// this.keyToGDEntity = allFiles.reduce((p, c) => {
|
||||||
|
// p[c.keyRaw] = c;
|
||||||
|
// return p;
|
||||||
|
// }, {} as Record<string, GDEntity>); // rebuild cache
|
||||||
|
|
||||||
|
// return allFiles;
|
||||||
const allFiles: GDEntity[] = [];
|
const allFiles: GDEntity[] = [];
|
||||||
|
|
||||||
// bfs
|
// bfs
|
||||||
@ -289,39 +301,23 @@ export class FakeFsGoogleDrive extends FakeFs {
|
|||||||
throw error;
|
throw error;
|
||||||
});
|
});
|
||||||
|
|
||||||
let parents = [
|
const newWalkTask = (id: string, folderPath: string) => {
|
||||||
{
|
return async () => {
|
||||||
id: this.baseDirID, // special init, from already created root folder ID
|
const filesUnderFolder = await this._listFolder(id, folderPath);
|
||||||
folderPath: "",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
while (parents.length !== 0) {
|
|
||||||
const children: typeof parents = [];
|
|
||||||
for (const { id, folderPath } of parents) {
|
|
||||||
queue.add(async () => {
|
|
||||||
const filesUnderFolder = await this._walkFolder(id, folderPath);
|
|
||||||
for (const f of filesUnderFolder) {
|
for (const f of filesUnderFolder) {
|
||||||
allFiles.push(f);
|
allFiles.push(f);
|
||||||
if (f.isFolder) {
|
if (f.isFolder) {
|
||||||
// keyRaw itself already has a tailing slash, no more slash here
|
// keyRaw itself already has a tailing slash, no more slash here
|
||||||
// keyRaw itself also already has full path
|
// keyRaw itself also already has full path
|
||||||
const child = {
|
queue.add(newWalkTask(f.id, f.keyRaw));
|
||||||
id: f.id,
|
}
|
||||||
folderPath: f.keyRaw,
|
}
|
||||||
};
|
};
|
||||||
// console.debug(
|
};
|
||||||
// `looping result of _walkFolder(${id},${folderPath}), adding child=${JSON.stringify(
|
|
||||||
// child
|
queue.add(newWalkTask(this.baseDirID, "")); // special init, from already created root folder ID
|
||||||
// )}`
|
|
||||||
// );
|
|
||||||
children.push(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
await queue.onIdle();
|
await queue.onIdle();
|
||||||
parents = children;
|
|
||||||
}
|
|
||||||
|
|
||||||
// console.debug(`in the end of walk:`);
|
// console.debug(`in the end of walk:`);
|
||||||
// console.debug(allFiles);
|
// console.debug(allFiles);
|
||||||
@ -329,25 +325,97 @@ export class FakeFsGoogleDrive extends FakeFs {
|
|||||||
return allFiles;
|
return allFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
async _walkFolder(parentID: string, parentFolderPath: string) {
|
async _listAllFiles(): Promise<GDEntity[]> {
|
||||||
|
const allFileRes: File[] = [];
|
||||||
|
let nextPageToken = "";
|
||||||
|
|
||||||
|
do {
|
||||||
|
const q = `'${this.baseDirID}' in parents and trashed=false`;
|
||||||
|
const url = new URL("https://www.googleapis.com/drive/v3/files");
|
||||||
|
url.searchParams.set("q", q);
|
||||||
|
url.searchParams.set("pageSize", "1000");
|
||||||
|
url.searchParams.set(
|
||||||
|
"fields",
|
||||||
|
"kind,nextPageToken,files(kind,fileExtension,md5Checksum,mimeType,parents,size,spaces,id,name,trashed,createdTime,modifiedTime,quotaBytesUsed,originalFilename,fullFileExtension,sha1Checksum,sha256Checksum)"
|
||||||
|
);
|
||||||
|
url.searchParams.set("orderBy", "modifiedTime");
|
||||||
|
url.searchParams.set("pageToken", nextPageToken);
|
||||||
|
|
||||||
|
const res = await fetch(url, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${await this._getAccessToken()}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (res.status !== 200) {
|
||||||
|
throw Error(`Error on list all files`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileRes = await res.json();
|
||||||
|
(fileRes.files as File[]).forEach((i) => allFileRes.push(i));
|
||||||
|
|
||||||
|
nextPageToken = fileRes.nextPageToken;
|
||||||
|
} while (nextPageToken !== undefined);
|
||||||
|
|
||||||
|
const allFolderRes = allFileRes.filter(
|
||||||
|
(i) => i.mimeType == FOLDER_MIME_TYPE
|
||||||
|
);
|
||||||
|
|
||||||
|
const allFolders = [
|
||||||
|
{
|
||||||
|
id: this.baseDirID, // special init, from already created root folder ID
|
||||||
|
folderPath: "",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for (let targetFolder of allFolders) {
|
||||||
|
allFolderRes
|
||||||
|
.filter((i) => i.parents?.includes(targetFolder.id))
|
||||||
|
.forEach((i) => {
|
||||||
|
allFolders.push({
|
||||||
|
id: i.id!,
|
||||||
|
folderPath: `${targetFolder}${i.name!}/`,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const allFiles: GDEntity[] = [];
|
||||||
|
|
||||||
|
for (const file of allFileRes) {
|
||||||
|
if (!file.parents) continue;
|
||||||
|
file.parents.forEach((parent) => {
|
||||||
|
const folder = allFolders.find((folder) => folder.id == parent);
|
||||||
|
if (!folder) return;
|
||||||
|
const entity = fromFileToGDEntity(file, folder.id, folder.folderPath);
|
||||||
|
allFiles.push(entity);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return allFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
async _listFolder(parentID: string, parentFolderPath: string) {
|
||||||
// console.debug(
|
// console.debug(
|
||||||
// `input of single level: parentID=${parentID}, parentFolderPath=${parentFolderPath}`
|
// `input of single level: parentID=${parentID}, parentFolderPath=${parentFolderPath}`
|
||||||
// );
|
// );
|
||||||
const filesOneLevel: GDEntity[] = [];
|
const filesOneLevel: GDEntity[] = [];
|
||||||
let nextPageToken: string | undefined = undefined;
|
let nextPageToken = "";
|
||||||
if (parentID === undefined || parentID === "" || parentID === "root") {
|
if (parentID === undefined || parentID === "" || parentID === "root") {
|
||||||
// we should never start from root
|
// we should never start from root
|
||||||
// because we encapsulate the vault inside a folder
|
// because we encapsulate the vault inside a folder
|
||||||
throw Error(`something goes wrong walking folder`);
|
throw Error(`something goes wrong walking folder`);
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
const q = encodeURIComponent(
|
const q = `'${parentID}' in parents and trashed=false`;
|
||||||
`'${parentID}' in parents and trashed=false`
|
const url = new URL("https://www.googleapis.com/drive/v3/files");
|
||||||
|
url.searchParams.set("q", q);
|
||||||
|
url.searchParams.set("pageSize", "1000");
|
||||||
|
url.searchParams.set(
|
||||||
|
"fields",
|
||||||
|
"kind,nextPageToken,files(kind,fileExtension,md5Checksum,mimeType,parents,size,spaces,id,name,trashed,createdTime,modifiedTime,quotaBytesUsed,originalFilename,fullFileExtension,sha1Checksum,sha256Checksum)"
|
||||||
);
|
);
|
||||||
const pageToken =
|
url.searchParams.set("orderBy", "modifiedTime");
|
||||||
nextPageToken !== undefined ? `&pageToken=${nextPageToken}` : "";
|
url.searchParams.set("pageToken", nextPageToken);
|
||||||
|
|
||||||
const url: string = `https://www.googleapis.com/drive/v3/files?q=${q}&pageSize=1000&fields=kind,nextPageToken,files(kind,fileExtension,md5Checksum,mimeType,parents,size,spaces,id,name,trashed,createdTime,modifiedTime,quotaBytesUsed,originalFilename,fullFileExtension,sha1Checksum,sha256Checksum)${pageToken}`;
|
|
||||||
|
|
||||||
const k = await fetch(url, {
|
const k = await fetch(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
@ -377,7 +445,7 @@ export class FakeFsGoogleDrive extends FakeFs {
|
|||||||
|
|
||||||
async walkPartial(): Promise<Entity[]> {
|
async walkPartial(): Promise<Entity[]> {
|
||||||
await this._init();
|
await this._init();
|
||||||
const filesInLevel = await this._walkFolder(this.baseDirID, "");
|
const filesInLevel = await this._listFolder(this.baseDirID, "");
|
||||||
return filesInLevel;
|
return filesInLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -508,6 +576,8 @@ export class FakeFsGoogleDrive extends FakeFs {
|
|||||||
// "xxx" => []
|
// "xxx" => []
|
||||||
// "xxx/yyy/zzz.md" => ["xxx", "xxx/yyy"]
|
// "xxx/yyy/zzz.md" => ["xxx", "xxx/yyy"]
|
||||||
const folderLevels = getFolderLevels(key);
|
const folderLevels = getFolderLevels(key);
|
||||||
|
console.log(key);
|
||||||
|
console.log(folderLevels);
|
||||||
if (folderLevels.length === 0) {
|
if (folderLevels.length === 0) {
|
||||||
// root
|
// root
|
||||||
parentID = this.baseDirID;
|
parentID = this.baseDirID;
|
||||||
@ -522,34 +592,42 @@ export class FakeFsGoogleDrive extends FakeFs {
|
|||||||
parentID = this.keyToGDEntity[parentFolderPath].id;
|
parentID = this.keyToGDEntity[parentFolderPath].id;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fileItself = key.split("/").pop()!;
|
const targetFileId = this.keyToGDEntity[key]?.id;
|
||||||
|
|
||||||
if (content.byteLength <= 5 * 1024 * 1024) {
|
const fileItself = key.split("/").pop()!;
|
||||||
const formData = new FormData();
|
|
||||||
const meta: any = {
|
const meta: any = {
|
||||||
name: fileItself,
|
name: fileItself,
|
||||||
modifiedTime: unixTimeToStr(mtime, true),
|
modifiedTime: unixTimeToStr(mtime, true),
|
||||||
createdTime: unixTimeToStr(ctime, true),
|
createdTime: unixTimeToStr(ctime, true),
|
||||||
parents: [parentID],
|
|
||||||
};
|
};
|
||||||
|
if(!targetFileId) meta.parents = [parentID]
|
||||||
|
|
||||||
|
if (content.byteLength <= 5 * 1024 * 1024) {
|
||||||
|
const formData = new FormData();
|
||||||
formData.append(
|
formData.append(
|
||||||
"metadata",
|
"metadata",
|
||||||
new Blob([JSON.stringify(meta)], {
|
new Blob(targetFileId ? [] : [JSON.stringify(meta)], {
|
||||||
type: "application/json; charset=UTF-8",
|
type: "application/json; charset=UTF-8",
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
formData.append("media", new Blob([content], { type: contentType }));
|
formData.append("media", new Blob([content], { type: contentType }));
|
||||||
|
|
||||||
const res = await fetch(
|
const url = new URL("https://www.googleapis.com/upload/drive/v3/files");
|
||||||
"https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=kind,fileExtension,md5Checksum,mimeType,parents,size,spaces,id,name,trashed,createdTime,modifiedTime,quotaBytesUsed,originalFilename,fullFileExtension,sha1Checksum,sha256Checksum",
|
if (targetFileId) url.pathname += `/${targetFileId}`;
|
||||||
{
|
url.searchParams.set("uploadType", "multipart");
|
||||||
method: "POST",
|
url.searchParams.set(
|
||||||
|
"fields",
|
||||||
|
"kind,fileExtension,md5Checksum,mimeType,parents,size,spaces,id,name,trashed,createdTime,modifiedTime,quotaBytesUsed,originalFilename,fullFileExtension,sha1Checksum,sha256Checksum"
|
||||||
|
);
|
||||||
|
|
||||||
|
const res = await fetch(url, {
|
||||||
|
method: targetFileId ? "PATCH" : "POST",
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${await this._getAccessToken()}`,
|
Authorization: `Bearer ${await this._getAccessToken()}`,
|
||||||
},
|
},
|
||||||
body: formData,
|
body: formData,
|
||||||
}
|
});
|
||||||
);
|
|
||||||
if (res.status !== 200 && res.status !== 201) {
|
if (res.status !== 200 && res.status !== 201) {
|
||||||
throw Error(`create file ${key} failed! meta=${JSON.stringify(meta)}`);
|
throw Error(`create file ${key} failed! meta=${JSON.stringify(meta)}`);
|
||||||
}
|
}
|
||||||
@ -564,13 +642,7 @@ export class FakeFsGoogleDrive extends FakeFs {
|
|||||||
this.keyToGDEntity[key] = entity;
|
this.keyToGDEntity[key] = entity;
|
||||||
return entity;
|
return entity;
|
||||||
} else {
|
} else {
|
||||||
const meta: any = {
|
const bodyStr = targetFileId ? "" : JSON.stringify(meta);
|
||||||
name: fileItself,
|
|
||||||
modifiedTime: unixTimeToStr(mtime, true),
|
|
||||||
createdTime: unixTimeToStr(ctime, true),
|
|
||||||
parents: [parentID],
|
|
||||||
};
|
|
||||||
const bodyStr = JSON.stringify(meta);
|
|
||||||
const headers: HeadersInit = {
|
const headers: HeadersInit = {
|
||||||
Authorization: `Bearer ${await this._getAccessToken()}`,
|
Authorization: `Bearer ${await this._getAccessToken()}`,
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@ -578,14 +650,18 @@ export class FakeFsGoogleDrive extends FakeFs {
|
|||||||
"X-Upload-Content-Type": contentType,
|
"X-Upload-Content-Type": contentType,
|
||||||
"X-Upload-Content-Length": `${content.byteLength}`,
|
"X-Upload-Content-Length": `${content.byteLength}`,
|
||||||
};
|
};
|
||||||
const res = await fetch(
|
const url = new URL("https://www.googleapis.com/upload/drive/v3/files");
|
||||||
"https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable&fields=kind,fileExtension,md5Checksum,mimeType,parents,size,spaces,id,name,trashed,createdTime,modifiedTime,quotaBytesUsed,originalFilename,fullFileExtension,sha1Checksum,sha256Checksum",
|
if (targetFileId) url.pathname += `/${targetFileId}`;
|
||||||
{
|
url.searchParams.set("uploadType", "resumable");
|
||||||
method: "POST",
|
url.searchParams.set(
|
||||||
|
"fields",
|
||||||
|
"kind,fileExtension,md5Checksum,mimeType,parents,size,spaces,id,name,trashed,createdTime,modifiedTime,quotaBytesUsed,originalFilename,fullFileExtension,sha1Checksum,sha256Checksum"
|
||||||
|
);
|
||||||
|
const res = await fetch(url, {
|
||||||
|
method: targetFileId ? "PATCH" : "POST",
|
||||||
headers: headers,
|
headers: headers,
|
||||||
body: bodyStr,
|
body: bodyStr,
|
||||||
}
|
});
|
||||||
);
|
|
||||||
if (res.status !== 200) {
|
if (res.status !== 200) {
|
||||||
throw Error(
|
throw Error(
|
||||||
`create resumable file ${key} failed! meta=${JSON.stringify(
|
`create resumable file ${key} failed! meta=${JSON.stringify(
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user