Skip to content

Commit

Permalink
fix: make d1 spaces.metadata nullable and change to kysely (#284)
Browse files Browse the repository at this point in the history
- spaces.metadata is now nullable
- d1 tables are now typed
- moved from `workers-qb` to
[`kysely`](https://github.com/koskimas/kysely) with [d1
dialect](https://github.com/aidenwallis/kysely-d1)


closes #280
  • Loading branch information
hugomrdias authored Dec 13, 2022
1 parent 0f13a95 commit c8a9ce5
Show file tree
Hide file tree
Showing 23 changed files with 595 additions and 350 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
},
"dependencies": {
"depcheck": "^1.4.3",
"typedoc": "^0.23.21",
"typedoc": "^0.23.22",
"typedoc-plugin-missing-exports": "^1.0.0"
}
}
44 changes: 44 additions & 0 deletions packages/access-api/migrations/0003_space.metadata_can_be_null.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
-- Migration number: 0003 2022-12-12T18:58:30.339Z
ALTER TABLE spaces
RENAME TO _spaces_old;

CREATE TABLE
spaces (
did TEXT NOT NULL PRIMARY KEY,
product TEXT NOT NULL,
email TEXT NOT NULL,
agent TEXT NOT NULL,
inserted_at TEXT NOT NULL DEFAULT (strftime ('%Y-%m-%dT%H:%M:%fZ', 'now')),
updated_at TEXT NOT NULL DEFAULT (strftime ('%Y-%m-%dT%H:%M:%fZ', 'now')),
metadata JSON DEFAULT EMPTY,
invocation TEXT NOT NULL DEFAULT EMPTY,
delegation TEXT DEFAULT NULL,
UNIQUE (did)
);

INSERT INTO
spaces (
did,
product,
email,
agent,
inserted_at,
updated_at,
metadata,
invocation,
delegation
)
SELECT
did,
product,
email,
agent,
inserted_at,
updated_at,
metadata,
invocation,
delegation
FROM
_spaces_old;

DROP TABLE "_spaces_old";
11 changes: 6 additions & 5 deletions packages/access-api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@
"@web3-storage/access": "workspace:^",
"@web3-storage/capabilities": "workspace:^",
"@web3-storage/worker-utils": "0.4.3-dev",
"kysely": "^0.22.0",
"kysely-d1": "^0.0.6",
"p-retry": "^5.1.2",
"preact": "^10.11.3",
"preact-render-to-string": "^5.2.6",
"qrcode": "^1.5.1",
"toucan-js": "^2.7.0",
"workers-qb": "^0.1.2"
"toucan-js": "^2.7.0"
},
"devDependencies": {
"@cloudflare/workers-types": "^3.18.0",
Expand All @@ -41,17 +42,17 @@
"@types/assert": "^1.5.6",
"@types/git-rev-sync": "^2.0.0",
"@types/mocha": "^10.0.1",
"@types/node": "^18.11.12",
"@types/node": "^18.11.13",
"@types/qrcode": "^1.5.0",
"better-sqlite3": "8.0.1",
"buffer": "^6.0.3",
"dotenv": "^16.0.3",
"esbuild": "^0.16.3",
"esbuild": "^0.16.4",
"git-rev-sync": "^3.0.2",
"hd-scripts": "^3.0.2",
"is-subset": "^0.1.1",
"miniflare": "^2.11.0",
"mocha": "^10.1.0",
"mocha": "^10.2.0",
"p-wait-for": "^5.0.0",
"process": "^0.11.10",
"readable-stream": "^4.2.0",
Expand Down
16 changes: 10 additions & 6 deletions packages/access-api/src/bindings.d.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import type { Logging } from '@web3-storage/worker-utils/logging'
import type { SpaceTable } from '@web3-storage/access/types'
import type { Handler as _Handler } from '@web3-storage/worker-utils/router'
import type { Signer } from '@ucanto/interface'
import { Email } from './utils/email.js'
import { Spaces } from './kvs/spaces.js'
import { Validations } from './kvs/validations.js'
import { D1QB } from 'workers-qb'
import { Spaces } from './models/spaces.js'
import { Validations } from './models/validations.js'
import { loadConfig } from './config.js'

export {}
Expand Down Expand Up @@ -47,11 +46,10 @@ export interface RouteContext {
config: ReturnType<typeof loadConfig>
url: URL
email: Email
kvs: {
models: {
spaces: Spaces
validations: Validations
}
db: D1QB
}

export type Handler = _Handler<RouteContext>
Expand Down Expand Up @@ -84,6 +82,12 @@ export interface ModuleWorker {
scheduled?: ModuleWorker.CronHandler<Env>
}

// D1 types

export interface D1ErrorRaw extends Error {
cause: Error & { code: string }
}

export interface D1Schema {
spaces: SpaceTable
}
148 changes: 0 additions & 148 deletions packages/access-api/src/kvs/spaces.js

This file was deleted.

95 changes: 95 additions & 0 deletions packages/access-api/src/models/spaces.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// @ts-ignore
// eslint-disable-next-line no-unused-vars
import * as Ucanto from '@ucanto/interface'
import { delegationToString } from '@web3-storage/access/encoding'
import { Kysely } from 'kysely'
import { D1Dialect } from 'kysely-d1'
import { D1Error, SpacePlugin } from '../utils/d1.js'

const spacePlugin = new SpacePlugin()

/**
* Spaces
*/
export class Spaces {
/**
*
* @param {D1Database} d1
*/
constructor(d1) {
this.d1 = /** @type {Kysely<import('../bindings').D1Schema>} */ (
new Kysely({ dialect: new D1Dialect({ database: d1 }) })
)
}

/**
* @param {import('@web3-storage/capabilities/types').VoucherRedeem} capability
* @param {Ucanto.Invocation<import('@web3-storage/capabilities/types').VoucherRedeem>} invocation
* @param {Ucanto.Delegation<[import('@web3-storage/access/types').Top]> | undefined} delegation
*/
async create(capability, invocation, delegation) {
try {
const metadata =
/** @type {import('@web3-storage/access/types').SpaceTableMetadata | undefined} */ (
/** @type {unknown} */ (invocation.facts[0])
)
const result = await this.d1
.withPlugin(spacePlugin)
.insertInto('spaces')
.values({
agent: invocation.issuer.did(),
did: capability.nb.space,
email: capability.nb.identity.replace('mailto:', ''),
invocation: delegationToString(invocation),
product: capability.nb.product,
metadata,
delegation: !delegation ? undefined : delegationToString(delegation),
})
.returning('spaces.did')
.execute()
return { data: result }
} catch (error) {
return {
error: new D1Error(
/** @type {import('../bindings').D1ErrorRaw} */ (error)
),
}
}
}

/**
* Get space by DID
*
* @param {Ucanto.URI<"did:">} did
*/
async get(did) {
const space = await this.d1
.withPlugin(spacePlugin)
.selectFrom('spaces')
.selectAll()
.where('spaces.did', '=', did)
.executeTakeFirst()

if (space) {
return space
}
}

/**
* @param {Ucanto.URI<"mailto:">} email
*/
async getByEmail(email) {
const spaces = await this.d1
.withPlugin(spacePlugin)
.selectFrom('spaces')
.selectAll()
.where('spaces.email', '=', email.replace('mailto:', ''))
.execute()

if (spaces.length === 0) {
return
}

return spaces
}
}
File renamed without changes.
4 changes: 2 additions & 2 deletions packages/access-api/src/routes/validate-email.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export async function validateEmail(req, env) {
}
if (req.query && req.query.ucan) {
try {
const delegation = await env.kvs.validations.put(
const delegation = await env.models.validations.put(
/** @type {import('@web3-storage/access/src/types.js').EncodedDelegation<[import('@web3-storage/access/src/types.js').VoucherClaim]>} */ (
req.query.ucan
)
Expand Down Expand Up @@ -62,7 +62,7 @@ export async function validateEmail(req, env) {
*/
async function recover(req, env) {
try {
const delegation = await env.kvs.validations.put(
const delegation = await env.models.validations.put(
/** @type {import('@web3-storage/access/src/types.js').EncodedDelegation<[import('@web3-storage/access/src/types.js').SpaceRecover]>} */ (
req.query.ucan
)
Expand Down
Loading

0 comments on commit c8a9ce5

Please sign in to comment.