Compare commits

...
10 Commits
19 changed files with 606 additions and 542 deletions
+1 -1
View File
@@ -29,7 +29,7 @@ jobs:
if [[ "${GITHUB_REF_NAME}" == *"-"* ]]; then if [[ "${GITHUB_REF_NAME}" == *"-"* ]]; then
DIST_TAG=rc DIST_TAG=rc
fi fi
pnpm publish --filter cryptgeon --tag "${DIST_TAG}" pnpm publish --filter cryptgeon --tag "${DIST_TAG}" --no-git-checks
env: env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+3
View File
@@ -34,6 +34,9 @@ jobs:
- name: Shared tests - name: Shared tests
run: pnpm --filter @cryptgeon/shared test run: pnpm --filter @cryptgeon/shared test
- name: Frontend type check
run: pnpm --filter @cryptgeon/web check
- name: Run your tests - name: Run your tests
run: pnpm test run: pnpm test
+1 -1
View File
@@ -115,7 +115,7 @@ services:
- /data - /data
app: app:
image: cupcakearmy/cryptgeon:latest image: cupcakearmy/cryptgeon:v3
depends_on: depends_on:
- cache - cache
environment: environment:
+1 -1
View File
@@ -103,7 +103,7 @@ services:
- /data - /data
app: app:
image: cupcakearmy/cryptgeon:latest image: cupcakearmy/cryptgeon:v3
depends_on: depends_on:
- cache - cache
environment: environment:
+2 -2
View File
@@ -91,7 +91,7 @@ services:
- /data - /data
app: app:
image: cupcakearmy/cryptgeon:latest image: cupcakearmy/cryptgeon:v3
depends_on: depends_on:
- cache - cache
environment: environment:
@@ -131,7 +131,7 @@ services:
- /data - /data
app: app:
image: cupcakearmy/cryptgeon:latest image: cupcakearmy/cryptgeon:v3
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
- cache - cache
+2 -2
View File
@@ -11,7 +11,7 @@ services:
- /data - /data
app: app:
image: cupcakearmy/cryptgeon:latest image: cupcakearmy/cryptgeon:v3
depends_on: depends_on:
- cache - cache
environment: environment:
@@ -26,4 +26,4 @@ services:
# interval: 1m # interval: 1m
# timeout: 3s # timeout: 3s
# retries: 2 # retries: 2
# start_period: 5s # start_period: 5s
-2
View File
@@ -2,11 +2,9 @@
## Todo ## Todo
- Localize i18n readmes: `README_ES.md`, `README_zh-CN.md` still reference `REDIS` / `/api/v1`-era endpoint names — align to `CACHE` / `/healthz` (also sweep `CONTRIBUTING.md`, `examples/*`, postman collection).
- Add remaining shared tooling to the pnpm catalog (`vite`, `tsdown`). - Add remaining shared tooling to the pnpm catalog (`vite`, `tsdown`).
- Move formatting, linting and type-checking + git hooks onto `vite-plus` (oxlint, oxfmt, vitest). - Move formatting, linting and type-checking + git hooks onto `vite-plus` (oxlint, oxfmt, vitest).
- Re-add CSP (`Content-Security-Policy`) wired into the axum router (was in `csp.rs`, removed as unused). - Re-add CSP (`Content-Security-Policy`) wired into the axum router (was in `csp.rs`, removed as unused).
- Move all CLI deps to `devDependencies` — they bundle into the single output file anyway.
## Unified payload (drop the text/file union) ## Unified payload (drop the text/file union)
+1 -1
View File
@@ -12,7 +12,7 @@ services:
- /data - /data
app: app:
image: cupcakearmy/cryptgeon:latest image: cupcakearmy/cryptgeon:v3
depends_on: depends_on:
- cache - cache
+1 -1
View File
@@ -116,7 +116,7 @@ services:
- /data - /data
app: app:
image: cupcakearmy/cryptgeon:latest image: cupcakearmy/cryptgeon:v3
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
- cache - cache
+2 -2
View File
@@ -26,7 +26,7 @@ services:
- /data - /data
app: app:
image: cupcakearmy/cryptgeon:latest image: cupcakearmy/cryptgeon:v3
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
- cache - cache
@@ -70,7 +70,7 @@ services:
- /data - /data
cryptgeon: cryptgeon:
image: cupcakearmy/cryptgeon image: cupcakearmy/cryptgeon:v3
depends_on: depends_on:
- cache - cache
labels: labels:
+1 -1
View File
@@ -252,7 +252,7 @@ dependencies = [
[[package]] [[package]]
name = "cryptgeon" name = "cryptgeon"
version = "3.0.0-rc.0" version = "3.0.0-rc.3"
dependencies = [ dependencies = [
"axum", "axum",
"bs62", "bs62",
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "cryptgeon" name = "cryptgeon"
version = "3.0.0-rc.0" version = "3.0.0-rc.3"
authors = ["cupcakearmy <hi@nicco.io>"] authors = ["cupcakearmy <hi@nicco.io>"]
edition = "2024" edition = "2024"
rust-version = "1.95" rust-version = "1.95"
+8 -8
View File
@@ -1,6 +1,6 @@
{ {
"name": "cryptgeon", "name": "cryptgeon",
"version": "3.0.0-rc.0", "version": "3.0.0-rc.3",
"homepage": "https://github.com/cupcakearmy/cryptgeon", "homepage": "https://github.com/cupcakearmy/cryptgeon",
"repository": { "repository": {
"type": "git", "type": "git",
@@ -21,19 +21,19 @@
"scripts": { "scripts": {
"build": "vp pack", "build": "vp pack",
"dev": "vp pack --watch", "dev": "vp pack --watch",
"prepublishOnly": "run-s build" "prepublishOnly": "pnpm run build"
}, },
"devDependencies": { "devDependencies": {
"@commander-js/extra-typings": "^15.0.0",
"@cryptgeon/shared": "workspace:*", "@cryptgeon/shared": "workspace:*",
"@msgpack/msgpack": "^3.1.3", "@msgpack/msgpack": "^3.1.3",
"@commander-js/extra-typings": "^12.1.0",
"@tsconfig/strictest": "catalog:", "@tsconfig/strictest": "catalog:",
"@types/inquirer": "^9.0.9", "@types/inquirer": "^9.0.10",
"@types/node": "^22.15.3", "@types/node": "^22.20.1",
"commander": "^12.1.0", "commander": "^15.0.0",
"inquirer": "^9.3.8", "inquirer": "^14.2.1",
"mime": "^4.1.0", "mime": "^4.1.0",
"pretty-bytes": "^6.1.1", "pretty-bytes": "^7.1.3",
"typescript": "catalog:", "typescript": "catalog:",
"vite-plus": "catalog:" "vite-plus": "catalog:"
}, },
+8 -7
View File
@@ -13,21 +13,22 @@
"type": "module", "type": "module",
"devDependencies": { "devDependencies": {
"@sveltejs/adapter-static": "^3.0.10", "@sveltejs/adapter-static": "^3.0.10",
"@sveltejs/kit": "^2.61.1", "@sveltejs/kit": "^2.70.3",
"@sveltejs/vite-plugin-svelte": "^7.1.2", "@sveltejs/vite-plugin-svelte": "^7.3.0",
"@zerodevx/svelte-toast": "^0.9.6", "@zerodevx/svelte-toast": "^0.9.6",
"license-checker-rseidelsohn": "^5.0.1", "license-checker-rseidelsohn": "^5.0.1",
"svelte": "^5.55.9", "svelte": "^5.57.0",
"svelte-check": "^4.4.8", "svelte-check": "^4.7.6",
"svelte-intl-precompile": "^0.12.3", "svelte-intl-precompile": "^0.12.3",
"tslib": "^2.8.1", "tslib": "^2.8.1",
"typescript": "^6.0.3", "typescript": "^6.0.3",
"vite": "^8.0.14" "vite": "^8.2.2"
}, },
"dependencies": { "dependencies": {
"@cryptgeon/shared": "workspace:*", "@cryptgeon/shared": "workspace:*",
"@fontsource/fira-mono": "^5.2.7", "@fontsource/fira-mono": "^5.3.0",
"pretty-bytes": "^7.1.0", "comlink": "^4.4.2",
"pretty-bytes": "^7.1.3",
"uqr": "^0.1.3" "uqr": "^0.1.3"
} }
} }
+23 -8
View File
@@ -1,12 +1,15 @@
<script lang="ts"> <script lang="ts">
import { import {
bytesToHex,
create as apiCreate, create as apiCreate,
bytesToHex,
packContent, packContent,
type ServerNote type FileDTO,
type NoteInput,
type ServerNote,
} from '@cryptgeon/shared' } from '@cryptgeon/shared'
import { t } from 'svelte-intl-precompile' import { t } from 'svelte-intl-precompile'
import { blur } from 'svelte/transition' import { blur } from 'svelte/transition'
import { transfer } from 'comlink'
import { status } from '$lib/stores/status' import { status } from '$lib/stores/status'
import { notify } from '$lib/toast' import { notify } from '$lib/toast'
@@ -15,10 +18,12 @@
import FileUpload from '$lib/ui/FileUpload.svelte' import FileUpload from '$lib/ui/FileUpload.svelte'
import Loader from '$lib/ui/Loader.svelte' import Loader from '$lib/ui/Loader.svelte'
import MaxSize from '$lib/ui/MaxSize.svelte' import MaxSize from '$lib/ui/MaxSize.svelte'
import PastedFilesPreview from '$lib/ui/PastedFilesPreview.svelte'
import Result, { type NoteResult } from '$lib/ui/NoteResult.svelte' import Result, { type NoteResult } from '$lib/ui/NoteResult.svelte'
import PastedFilesPreview from '$lib/ui/PastedFilesPreview.svelte'
import Switch from '$lib/ui/Switch.svelte' import Switch from '$lib/ui/Switch.svelte'
import TextArea from '$lib/ui/TextArea.svelte' import TextArea from '$lib/ui/TextArea.svelte'
import { createWorker } from '$lib/worker'
import { onMount } from 'svelte'
let note: { views: number; expiration: number } = $state({ views: 1, expiration: 60 }) let note: { views: number; expiration: number } = $state({ views: 1, expiration: 60 })
let files: FileDTO[] = $state([]) let files: FileDTO[] = $state([])
@@ -53,6 +58,8 @@
if (!isFile) textContent = '' if (!isFile) textContent = ''
}) })
const worker = createWorker()
async function handlePaste(e: ClipboardEvent) { async function handlePaste(e: ClipboardEvent) {
const data = e.clipboardData const data = e.clipboardData
if (!data) return if (!data) return
@@ -123,13 +130,21 @@
throw new EmptyContentError() throw new EmptyContentError()
} }
const payload = packContent( const noteInput: NoteInput = isFile
isFile ? { type: 'files', files } : { type: 'text', text: textContent }, ? transfer(
customPassword || undefined {
) type: 'files',
files: $state.snapshot(files),
},
files.map((f) => f.data.buffer)
)
: { type: 'text', text: textContent }
const payload = await worker.pack(noteInput, customPassword || undefined)
const serverNote: ServerNote = { const serverNote: ServerNote = {
meta: { meta: {
...(timeExpiration ? { expiration: parseInt(note.expiration as any) } : { views: parseInt(note.views as any) }), ...(timeExpiration
? { expiration: parseInt(note.expiration as any) }
: { views: parseInt(note.views as any) }),
extra: payload.extra, extra: payload.extra,
}, },
data: payload.data, data: payload.data,
+14
View File
@@ -0,0 +1,14 @@
import { wrap } from 'comlink'
import CryptWorker from './worker?worker'
import type { packContent, unpackContent } from '@cryptgeon/shared'
export function createWorker() {
const worker = new CryptWorker()
return wrap<WorkerConract>(worker)
}
export type WorkerConract = {
pack: typeof packContent
unpack: typeof unpackContent
}
@@ -0,0 +1,19 @@
import type { WorkerConract } from '$lib/worker'
import { packContent, unpackContent } from '@cryptgeon/shared'
import { expose, transfer } from 'comlink'
const contract: WorkerConract = {
pack(input, password) {
const content = packContent(input, password)
return transfer(content, [content.data.buffer, content.extra.buffer, content.key.buffer])
},
unpack(data, key) {
const content = unpackContent(data, key)
return transfer(
content,
typeof content.data === 'string' ? [] : content.data.map((f) => f.data.buffer)
)
},
}
expose(contract)
@@ -1,5 +1,13 @@
<script lang="ts"> <script lang="ts">
import { deriveKey, hexToBytes, decode, info, get as apiGet, unpackContent, type FileDTO } from '@cryptgeon/shared' import {
deriveKey,
hexToBytes,
decode,
info,
get as apiGet,
unpackContent,
type FileDTO,
} from '@cryptgeon/shared'
import { onMount } from 'svelte' import { onMount } from 'svelte'
import { t } from 'svelte-intl-precompile' import { t } from 'svelte-intl-precompile'
@@ -8,6 +16,7 @@
import ShowNote, { type DecryptedNote } from '$lib/ui/ShowNote.svelte' import ShowNote, { type DecryptedNote } from '$lib/ui/ShowNote.svelte'
import TextInput from '$lib/ui/TextInput.svelte' import TextInput from '$lib/ui/TextInput.svelte'
import type { PageData } from './$types' import type { PageData } from './$types'
import { createWorker } from '$lib/worker'
interface Props { interface Props {
data: PageData data: PageData
@@ -44,6 +53,8 @@
} }
}) })
const worker = createWorker()
async function show(e: SubmitEvent) { async function show(e: SubmitEvent) {
e.preventDefault() e.preventDefault()
try { try {
@@ -69,7 +80,7 @@
key = hexToBytes(password!) key = hexToBytes(password!)
} }
const content = unpackContent(serverNote.data, key) const content = await worker.unpack(serverNote.data, key)
switch (content.type) { switch (content.type) {
case 'text': case 'text':
@@ -78,16 +89,16 @@
contents: content.data, contents: content.data,
} }
break break
case 'files': case 'files':
const files = (content.data as any[]).map((f: any) => ({ const files = (content.data as any[]).map((f: any) => ({
...f, ...f,
data: f.data instanceof Uint8Array ? f.data : new Uint8Array(f.data as any), data: f.data instanceof Uint8Array ? f.data : new Uint8Array(f.data as any),
})) }))
note = { note = {
meta: { type: 'file' }, meta: { type: 'file' },
contents: files, contents: files,
} }
break break
default: default:
error = $t('show.errors.unsupported_type') error = $t('show.errors.unsupported_type')
return return
@@ -144,4 +155,4 @@ break
flex-direction: column; flex-direction: column;
gap: 1rem; gap: 1rem;
} }
</style> </style>
+494 -491
View File
File diff suppressed because it is too large Load Diff