Linted code.
This commit is contained in:
1 parent
d12600348f
commit
eae420a5a4
8 files changed
+200
-214
No files matched your search
+9
-4
@@ -1,5 +1,10 @@
|
||||
export { Buffer, StringReader } from "https://deno.land/std@0.191.0/io/mod.ts";
|
||||
export { readAll, readerFromIterable, readableStreamFromReader, readerFromStreamReader, iterateReader, TextLineStream } from "https://deno.land/std@0.191.0/streams/mod.ts";
|
||||
export { Buffer, StringReader } from 'https://deno.land/std@0.191.0/io/mod.ts';
|
||||
export {
|
||||
iterateReader,
|
||||
readableStreamFromReader,
|
||||
readAll,
|
||||
readerFromIterable,
|
||||
readerFromStreamReader,
|
||||
TextLineStream,
|
||||
} from 'https://deno.land/std@0.191.0/streams/mod.ts';
|
||||
export { Application, Context, Router } from 'https://deno.land/x/oak/mod.ts';
|
||||
|
||||
|
||||
+11
-15
@@ -1,15 +1,13 @@
|
||||
import { Context, Router } from "./deps.ts";
|
||||
import { FileService } from "./services/mod.ts";
|
||||
import { readerFromStreamReader } from "./deps.ts";
|
||||
import { asyncIterableToArray } from "./utils.ts";
|
||||
|
||||
import { Context, Router } from './deps.ts';
|
||||
import { FileService } from './services/mod.ts';
|
||||
import { readerFromStreamReader } from './deps.ts';
|
||||
import { asyncIterableToArray } from './utils.ts';
|
||||
|
||||
type Handler = (ctx: Context) => void;
|
||||
|
||||
|
||||
function listFileHandlerFactory(fileService: FileService): Handler {
|
||||
return async (ctx: Context) => {
|
||||
ctx.response.type = "application/json";
|
||||
ctx.response.type = 'application/json';
|
||||
ctx.response.body = await asyncIterableToArray(fileService.list());
|
||||
};
|
||||
}
|
||||
@@ -20,8 +18,8 @@ function createFileHandlerFactory(fileService: FileService): Handler {
|
||||
ctx.response.body = 'This is a post';
|
||||
const path = untypedCtx.request.url.searchParams.get('path');
|
||||
|
||||
const reqBody = await ctx.request.body({ type: "stream" }).value;
|
||||
const reader = readerFromStreamReader(reqBody.getReader())
|
||||
const reqBody = await ctx.request.body({ type: 'stream' }).value;
|
||||
const reader = readerFromStreamReader(reqBody.getReader());
|
||||
await fileService.createFromReader(path, reader);
|
||||
};
|
||||
}
|
||||
@@ -31,22 +29,21 @@ function getFileHandlerFactory(fileService: FileService): Handler {
|
||||
const untypedCtx: any = ctx;
|
||||
const fileId = untypedCtx.params.path;
|
||||
const reader = await fileService.getContentAsReader(fileId);
|
||||
if(reader == null){
|
||||
if (reader == null) {
|
||||
ctx.response.status = 404;
|
||||
return;
|
||||
}
|
||||
ctx.response.status = 200;
|
||||
ctx.response.body = reader;
|
||||
ctx.response.body = reader;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function deleteFileHandlerFactory(fileService: FileService): Handler {
|
||||
return async (ctx: Context) => {
|
||||
const untypedCtx: any = ctx;
|
||||
const path = untypedCtx.params.path;
|
||||
const isDeleted = await fileService.deleteByPath(path);
|
||||
if(!isDeleted){
|
||||
if (!isDeleted) {
|
||||
ctx.response.status = 404;
|
||||
return;
|
||||
}
|
||||
@@ -54,7 +51,6 @@ function deleteFileHandlerFactory(fileService: FileService): Handler {
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
export function buildAPI(router: Router, fileService: FileService): Router {
|
||||
router.get('/files', listFileHandlerFactory(fileService));
|
||||
router.get('/files/:path', getFileHandlerFactory(fileService));
|
||||
@@ -62,4 +58,4 @@ export function buildAPI(router: Router, fileService: FileService): Router {
|
||||
router.post('/files', createFileHandlerFactory(fileService));
|
||||
|
||||
return router;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
import { Application, Router } from './deps.ts';
|
||||
import { buildAPI } from './restapi.ts';
|
||||
import { DenoKVFileService } from "./services/mod.ts";
|
||||
import { DenoKVFileService } from './services/mod.ts';
|
||||
|
||||
async function main(){
|
||||
async function main() {
|
||||
const app = new Application();
|
||||
const kv = await Deno.openKv();
|
||||
const fileService = new DenoKVFileService(kv);
|
||||
|
||||
+27
-34
@@ -1,9 +1,8 @@
|
||||
import { readAll, readerFromIterable, iterateReader } from "../deps.ts";
|
||||
import { Buffer, StringReader } from "../deps.ts";
|
||||
import {FileService, FileMetaData, BlobService} from './interfaces.ts';
|
||||
|
||||
import { readerFromStreamReader, readableStreamFromReader } from "https://deno.land/std@0.191.0/streams/mod.ts";
|
||||
import { iterateReader, readAll, readerFromIterable } from '../deps.ts';
|
||||
import { Buffer, StringReader } from '../deps.ts';
|
||||
import { BlobService, FileMetaData, FileService } from './interfaces.ts';
|
||||
|
||||
import { readableStreamFromReader, readerFromStreamReader } from 'https://deno.land/std@0.191.0/streams/mod.ts';
|
||||
|
||||
interface SerializedFile {
|
||||
id: string;
|
||||
@@ -12,7 +11,6 @@ interface SerializedFile {
|
||||
compression: string;
|
||||
}
|
||||
|
||||
|
||||
interface SerializedFilePathIndex {
|
||||
fileId: string;
|
||||
}
|
||||
@@ -27,12 +25,12 @@ export class DenoKVBlobService implements BlobService {
|
||||
}
|
||||
|
||||
private async sha1(msgUint8: Uint8Array): Promise<string> {
|
||||
const hashBuffer = await crypto.subtle.digest("SHA-1", msgUint8);
|
||||
const hashBuffer = await crypto.subtle.digest('SHA-1', msgUint8);
|
||||
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
||||
return hashArray
|
||||
.map((b) => b.toString(16).padStart(2, "0"))
|
||||
.join(""); // convert bytes to hex string
|
||||
}
|
||||
.map((b) => b.toString(16).padStart(2, '0'))
|
||||
.join(''); // convert bytes to hex string
|
||||
}
|
||||
|
||||
private *splitText(content: Uint8Array): Generator<Uint8Array> {
|
||||
let blobCount = 0;
|
||||
@@ -51,10 +49,10 @@ export class DenoKVBlobService implements BlobService {
|
||||
}
|
||||
|
||||
private async unsafePersistBlob(mainIndex: string, index: number, content: Uint8Array): Promise<void> {
|
||||
if(content.length > this.blobSize){
|
||||
if (content.length > this.blobSize) {
|
||||
throw new Error('Persisted a too large blob');
|
||||
}
|
||||
|
||||
|
||||
const blob_id = await this.sha1(content);
|
||||
await this.kv.set(['blob_index', mainIndex, index], blob_id);
|
||||
await this.kv.set(['blob', blob_id], content);
|
||||
@@ -71,10 +69,10 @@ export class DenoKVBlobService implements BlobService {
|
||||
return size;
|
||||
}
|
||||
|
||||
async persistReader(index: string, content: Deno.Reader): Promise<number>{
|
||||
async persistReader(index: string, content: Deno.Reader): Promise<number> {
|
||||
let i = 0;
|
||||
let size = 0;
|
||||
for await (const chunk of iterateReader(content, {bufSize: this.blobSize})){
|
||||
for await (const chunk of iterateReader(content, { bufSize: this.blobSize })) {
|
||||
await this.unsafePersistBlob(index, i, chunk);
|
||||
size += chunk.length;
|
||||
i++;
|
||||
@@ -100,11 +98,11 @@ export class DenoKVBlobService implements BlobService {
|
||||
return await readAll(this.getBlob(index));
|
||||
}
|
||||
|
||||
getBlob(index: string): Deno.Reader{
|
||||
getBlob(index: string): Deno.Reader {
|
||||
return readerFromIterable(this.iterBlob(index));
|
||||
}
|
||||
|
||||
private async *iterRawBlobs(index: string): AsyncIterable<Uint8Array>{
|
||||
private async *iterRawBlobs(index: string): AsyncIterable<Uint8Array> {
|
||||
const prefix = ['blob_index', index];
|
||||
for await (const itm of this.kv.list<string>({ prefix })) {
|
||||
const foo = await this.kv.get<Uint8Array>(['blob', itm.value]);
|
||||
@@ -127,8 +125,7 @@ export class DenoKVBlobService implements BlobService {
|
||||
return ret;
|
||||
}
|
||||
|
||||
streamBlob(index: string): Deno.Reader{
|
||||
|
||||
streamBlob(index: string): Deno.Reader {
|
||||
return readerFromIterable(this.iterRawBlobs(index));
|
||||
}
|
||||
}
|
||||
@@ -146,29 +143,29 @@ export class DenoKVFileService implements FileService {
|
||||
path: string,
|
||||
content: string | Uint8Array,
|
||||
): Promise<FileMetaData> {
|
||||
if (content instanceof Uint8Array){
|
||||
if (content instanceof Uint8Array) {
|
||||
return this.createFromReader(path, new Buffer(content));
|
||||
}
|
||||
return this.createFromReader(path, new StringReader(content));
|
||||
}
|
||||
|
||||
async createFromReader(path: string, content: Deno.Reader): Promise<FileMetaData>{
|
||||
async createFromReader(path: string, content: Deno.Reader): Promise<FileMetaData> {
|
||||
const newId = crypto.randomUUID();
|
||||
|
||||
const compressedContent = readableStreamFromReader(content).pipeThrough(new CompressionStream('gzip')).getReader()
|
||||
const compressedContent = readableStreamFromReader(content).pipeThrough(new CompressionStream('gzip'))
|
||||
.getReader();
|
||||
const size = await this.blobService.persistReader(newId, readerFromStreamReader(compressedContent));
|
||||
const serializedFile: SerializedFile = {
|
||||
id: newId,
|
||||
path,
|
||||
contentSize: size,
|
||||
compression: 'gzip'
|
||||
compression: 'gzip',
|
||||
};
|
||||
const idx: SerializedFilePathIndex = { fileId: newId };
|
||||
await this.kv.set(['file', newId], serializedFile);
|
||||
await this.kv.set(['file_index_path', path], idx);
|
||||
|
||||
return { id: newId, path, contentSize: size };
|
||||
|
||||
return { id: newId, path, contentSize: size };
|
||||
}
|
||||
|
||||
async *list(): AsyncIterable<FileMetaData> {
|
||||
@@ -206,21 +203,19 @@ export class DenoKVFileService implements FileService {
|
||||
.delete(idx.key)
|
||||
.commit();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private async getSerializedFile(fileId: string): Promise<SerializedFile | null>{
|
||||
private async getSerializedFile(fileId: string): Promise<SerializedFile | null> {
|
||||
const ret = await this.kv.get<SerializedFile>(['file', fileId]);
|
||||
return ret.value
|
||||
return ret.value;
|
||||
}
|
||||
|
||||
private decompressContent(serializedFile: SerializedFile, content: Deno.Reader): Deno.Reader {
|
||||
if(serializedFile.compression == 'gzip'){
|
||||
if (serializedFile.compression == 'gzip') {
|
||||
const ret = readableStreamFromReader(content).pipeThrough(new DecompressionStream('gzip')).getReader();
|
||||
return readerFromStreamReader(ret);
|
||||
|
||||
}
|
||||
return content;
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
async getRawContentByPath(path: string): Promise<Uint8Array | null> {
|
||||
@@ -228,7 +223,6 @@ export class DenoKVFileService implements FileService {
|
||||
return ret === null ? null : readAll(ret);
|
||||
}
|
||||
|
||||
|
||||
async getContentAsReader(path: string): Promise<Deno.Reader | null> {
|
||||
const idx = await this.kv.get<SerializedFilePathIndex>([
|
||||
'file_index_path',
|
||||
@@ -238,11 +232,10 @@ export class DenoKVFileService implements FileService {
|
||||
return null;
|
||||
}
|
||||
const ser = await this.kv.get<SerializedFile>(['file', idx.value.fileId]);
|
||||
if(ser.value === null){
|
||||
if (ser.value === null) {
|
||||
return null;
|
||||
}
|
||||
return this.decompressContent(ser.value, this.blobService.getBlob(idx.value.fileId));
|
||||
|
||||
}
|
||||
|
||||
async getMetaDataByID(id: string): Promise<FileMetaData | null> {
|
||||
|
||||
@@ -4,24 +4,22 @@ export interface FileMetaData {
|
||||
contentSize: number;
|
||||
}
|
||||
|
||||
|
||||
export interface FileService {
|
||||
|
||||
list(): AsyncIterable<FileMetaData>;
|
||||
|
||||
createFromFullContent(
|
||||
path: string,
|
||||
content: string | Uint8Array,
|
||||
): Promise<FileMetaData>;
|
||||
|
||||
|
||||
createFromReader(path: string, content: Deno.Reader): Promise<FileMetaData>;
|
||||
|
||||
|
||||
getRawContentByPath(path: string): Promise<Uint8Array | null>;
|
||||
|
||||
getContentAsReader(path: string): Promise<Deno.Reader | null>;
|
||||
|
||||
getMetaDataByID(id: string): Promise<FileMetaData | null>;
|
||||
|
||||
|
||||
renameById(id: string, newPath: string): Promise<FileMetaData | null>;
|
||||
|
||||
renameByPath(
|
||||
@@ -32,7 +30,6 @@ export interface FileService {
|
||||
deleteByPath(path: string): Promise<boolean>;
|
||||
}
|
||||
|
||||
|
||||
export interface BlobService {
|
||||
persistBlob(index: string, content: Uint8Array): Promise<number>;
|
||||
persistReader(index: string, content: Deno.Reader): Promise<number>;
|
||||
@@ -40,4 +37,4 @@ export interface BlobService {
|
||||
getBlob(index: string): Deno.Reader;
|
||||
getNumberOfBlobs(index: string): Promise<number>;
|
||||
streamBlob(index: string): Deno.Reader;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
export * from './interfaces.ts';
|
||||
export {DenoKVBlobService, DenoKVFileService} from './denokv.ts';
|
||||
export { DenoKVBlobService, DenoKVFileService } from './denokv.ts';
|
||||
Reference in new issue
Block a user