Skip to content

Commit

Permalink
Merge pull request #22 from edrys-org/feat/kv
Browse files Browse the repository at this point in the history
Feat/kv
  • Loading branch information
andre-dietrich authored Aug 30, 2023
2 parents 653e651 + a2c7f90 commit 8c998d0
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 50 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ client:
cd client && npm run generate && rm -rf ../dist/static && cp -r dist ../dist/static

deno:
deno bundle server/app.ts dist/app.js
deno bundle --unstable server/app.ts dist/app.js

run:
deno run -A dist/app.js --address localhost:8000 --serve-path dist/static --secret 182761552627328716
2 changes: 1 addition & 1 deletion docs/Deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ These for example include Gmail, SendGrid, Mailgun, or AWS SES.
Edrys does not use a database, instead it stores data either directly to file or
uses an S3-compatible API.

- `data-engine`: either `file` (default) or `s3`
- `data-engine`: either `file` (default), `memory` (for testing), `s3` or `kv`

For file:

Expand Down
2 changes: 1 addition & 1 deletion docs/deployment/DenoLand.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Minimal steps to reproduce:
6. And "Add Env Varibles":

1. `EDRYS_SERVE_PATH`: `dist/static`
2. `EDRYS_DATA_ENGINE`: `memory` for basic testing, otherwise use `s3` in combination with S3-settings from section [Deployment](../Deployment.md#data-storage)
2. `EDRYS_DATA_ENGINE`: `memory` for basic testing, otherwise use `s3` in combination with S3-settings from section [Deployment](../Deployment.md#data-storage) or `kv`
3. `EDRYS_SECRET`: `random-value-secret`

7. Click on "Link"
Expand Down
141 changes: 94 additions & 47 deletions server/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,49 @@ import * as env from './env.ts'

export let ready = false
let s3c: s3.S3Client
let kv: any

const inMemoryStorage: Record<string, string> = {}

/**
* Init data storage
*/
if (env.data_engine == 's3') {
if (
env.data_s3_endpoint == '' ||
env.data_s3_port == 0 ||
env.data_s3_region == '' ||
env.data_s3_access_key == '' ||
env.data_s3_secret_key == '' ||
env.data_s3_bucket == ''
) {
throw new Error('Invalid Data S3 config')
switch (env.data_engine) {
case 's3': {
if (
env.data_s3_endpoint == '' ||
env.data_s3_port == 0 ||
env.data_s3_region == '' ||
env.data_s3_access_key == '' ||
env.data_s3_secret_key == '' ||
env.data_s3_bucket == ''
) {
throw new Error('Invalid Data S3 config')
}

s3c = new s3.S3Client({
endPoint: env.data_s3_endpoint,
port: env.data_s3_port,
useSSL: env.data_s3_use_ssl,
region: env.data_s3_region,
accessKey: env.data_s3_access_key,
secretKey: env.data_s3_secret_key,
bucket: env.data_s3_bucket,
pathStyle: true,
})

break
}

s3c = new s3.S3Client({
endPoint: env.data_s3_endpoint,
port: env.data_s3_port,
useSSL: env.data_s3_use_ssl,
region: env.data_s3_region,
accessKey: env.data_s3_access_key,
secretKey: env.data_s3_secret_key,
bucket: env.data_s3_bucket,
pathStyle: true,
})
} else if (env.data_engine == 'file') {
await fs.ensureDir(env.data_file_path)
case 'kv': {
kv = await Deno.openKv()
break
}

case 'file': {
await fs.ensureDir(env.data_file_path)
break
}
}

ready = true
Expand All @@ -49,19 +62,36 @@ export async function read(
): Promise<Record<string, unknown>> {
const path = `${env.data_file_path}/${folder}/${file}.json`

if (env.data_engine == 's3') {
const res = await s3c.getObject(path)
if (res.status == 200) {
return res.json()
} else {
switch (env.data_engine) {
case 's3': {
const res = await s3c.getObject(path)
if (res.status == 200) {
return res.json()
}
throw new Error(`S3 Error (${res.status})`)
}
} else if (env.data_engine == 'file') {
await fs.ensureDir(`${env.data_file_path}/${folder}`)
return JSON.parse(await Deno.readTextFile(path))
} else {
if (path in inMemoryStorage) return JSON.parse(inMemoryStorage[path])
else throw new Error(`Not found: ${path}`)

case 'kv': {
const res = await kv.get([path])

if (res.versionstamp !== null) {
return JSON.parse(res.value.text)
}

throw new Error(`KV Error (${res})`)
}

case 'file': {
await fs.ensureDir(`${env.data_file_path}/${folder}`)
return JSON.parse(await Deno.readTextFile(path))
}

default: {
if (path in inMemoryStorage) {
return JSON.parse(inMemoryStorage[path])
}
throw new Error(`Not found: ${path}`)
}
}
}

Expand All @@ -81,24 +111,41 @@ export async function write(

const path = `${env.data_file_path}/${folder}/${file}.json`

if (env.data_engine == 's3') {
if (text == undefined) {
return await s3c.deleteObject(path)
switch (env.data_engine) {
case 's3': {
if (text == undefined) {
return await s3c.deleteObject(path)
}

await s3c.putObject(path, text)
break
}

await s3c.putObject(path, text)
} else if (env.data_engine == 'file') {
await fs.ensureDir(`${env.data_file_path}/${folder}`)
if (text == undefined) {
return await Deno.remove(path)
case 'kv': {
if (text == undefined) {
return await kv.delete([path])
}

await kv.set([path], { text })
break
}

await Deno.writeTextFile(path, text)
} else {
if (text == undefined) {
delete inMemoryStorage[path]
} else {
inMemoryStorage[path] = text
case 'file': {
await fs.ensureDir(`${env.data_file_path}/${folder}`)
if (text == undefined) {
return await Deno.remove(path)
}

await Deno.writeTextFile(path, text)
break
}

default: {
if (text == undefined) {
delete inMemoryStorage[path]
} else {
inMemoryStorage[path] = text
}
}
}
}
Expand Down

1 comment on commit 8c998d0

@deno-deploy
Copy link

@deno-deploy deno-deploy bot commented on 8c998d0 Aug 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Failed to deploy:

Module not found "file:///src/dist/app.js".

Please sign in to comment.