Skip to content

Commit

Permalink
feat: cherry pick changes from uploads-v2 demo (#43)
Browse files Browse the repository at this point in the history
* chore(ucanto): export more bindings

* chore(ucanto): split server options

* chore(ucanto): remove prepare scripts

* feat(ucanto): make derived capabilities providable

* chore: add .env to gitignore

* feat(ucanto): handle capability optionals

* chore(ucanto): drop @ from package name

* chore: update readme to reflect current state

* fix: typo in readme
  • Loading branch information
Gozala authored Jun 20, 2022
1 parent 0ec460e commit 4308fd2
Show file tree
Hide file tree
Showing 20 changed files with 289 additions and 247 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ dist
.nyc_output
tmp
node_modules
.env
418 changes: 223 additions & 195 deletions Readme.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "@ucanto",
"name": "ucanto",
"private": true,
"type": "module",
"workspaces": [
Expand Down
1 change: 0 additions & 1 deletion packages/authority/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
},
"homepage": "https://github.com/web3-storage/ucanto",
"scripts": {
"prepare": "tsc --build",
"test:web": "playwright-test test/**/*.spec.js --cov && nyc report",
"test:node": "c8 --check-coverage --branches 100 --functions 100 --lines 100 mocha test/**/*.spec.js",
"test": "npm run test:node",
Expand Down
1 change: 0 additions & 1 deletion packages/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
},
"homepage": "https://github.com/web3-storage/ucanto",
"scripts": {
"prepare": "tsc --build",
"test:web": "playwright-test test/**/*.spec.js --cov && nyc report",
"test:node": "c8 --check-coverage --branches 100 --functions 100 --lines 100 mocha test/**/*.spec.js",
"test": "npm run test:node",
Expand Down
4 changes: 2 additions & 2 deletions packages/client/test/services/account.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ const associate = (accounts, from, to, proof, create) => {
// account and link all them together.
if (!fromAccount && !toAccount) {
if (create) {
const account = the(`did:cid:${proof}`)
const account = the(`did:ipld:${proof}`)
accounts.set(to, { account, proof })
accounts.set(from, { account, proof })
} else {
Expand All @@ -105,7 +105,7 @@ const associate = (accounts, from, to, proof, create) => {
} else if (fromAccount) {
accounts.set(to, { account: fromAccount, proof })
} else if (fromAccount !== toAccount) {
const account = the(`did:cid:${proof}`)
const account = the(`did:ipld:${proof}`)
accounts.set(toAccount, { account, proof })
accounts.set(fromAccount, { account, proof })
}
Expand Down
1 change: 0 additions & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
},
"homepage": "https://github.com/web3-storage/ucanto",
"scripts": {
"prepare": "tsc --build",
"test:web": "playwright-test test/*.spec.js --cov && nyc report",
"test:node": "c8 --check-coverage --branches 100 --functions 100 --lines 100 mocha test/*.spec.js",
"test": "npm run test:node",
Expand Down
1 change: 0 additions & 1 deletion packages/interface/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
},
"homepage": "https://github.com/web3-storage/ucanto",
"scripts": {
"prepare": "tsc --build",
"typecheck": "tsc --build"
},
"dependencies": {
Expand Down
35 changes: 19 additions & 16 deletions packages/interface/src/capability.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ export type InvalidCapability = UnknownCapability | MalformedCapability
export interface DerivedMatch<T, M extends Match>
extends Match<T, M | DerivedMatch<T, M>> {}

export interface DeriveSelector<M extends Match, T> {
to: MatchSelector<DirectMatch<T>>
export interface DeriveSelector<M extends Match, T extends ParsedCapability> {
to: TheCapabilityParser<DirectMatch<T>>
derives: Derives<T, M["value"]>
}

Expand Down Expand Up @@ -125,15 +125,12 @@ export interface View<M extends Match> extends Matcher<M>, Selector<M> {
*/
derive<T extends ParsedCapability>(
options: DeriveSelector<M, T>
): CapabilityParser<DerivedMatch<T, M>>
): TheCapabilityParser<DerivedMatch<T, M>>
}

export interface TheCapabilityParser<
A extends Ability = Ability,
C extends Caveats = Caveats,
M extends CapabilityMatch<A, C> = CapabilityMatch<A, C>
> extends CapabilityParser<M> {
can: A
export interface TheCapabilityParser<M extends Match<ParsedCapability>>
extends CapabilityParser<M> {
readonly can: M["value"]["can"]
}

export interface CapabilityParser<M extends Match = Match> extends View<M> {
Expand Down Expand Up @@ -236,14 +233,20 @@ export interface ParsedCapability<
caveats: C
}

export type InferCaveats<C> = {
[Key in keyof C]: C[Key] extends Decoder<unknown, infer T, infer _>
? T
: C[Key] extends Parser<unknown, infer T, infer _X>
export type InferCaveats<C> = InferRequiredCaveats<C> & InferOptionalCaveats<C>

export type InferOptionalCaveats<C> = {
[Key in keyof C as C[Key] extends Decoder<any, infer _ | undefined, any>
? Key
: never]?: C[Key] extends Decoder<unknown, infer T | undefined, infer _>
? T
: // : C[Key] extends (input: unknown) => infer T
// ? Exclude<T, Failure>
never
: never
}

export type InferRequiredCaveats<C> = {
[Key in keyof C as C[Key] extends Decoder<any, infer _ | undefined, any>
? never
: Key]: C[Key] extends Decoder<unknown, infer T, infer _> ? T : never
}

export interface Descriptor<A extends Ability, C extends Caveats> {
Expand Down
20 changes: 14 additions & 6 deletions packages/interface/src/lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,9 @@ export interface ServiceMethod<
O,
X extends { error: true }
> {
(input: Invocation<I>, context: InvocationContext): Await<Result<O, X>>
(input: Invocation<I>, context: InvocationContext): Await<
Result<O, X | InvocationError>
>
}

export type InvocationError =
Expand Down Expand Up @@ -309,7 +311,7 @@ export interface ConnectionView<T> extends Connection<T> {
): Await<InferServiceInvocations<I, T>>
}

export interface Server<T> {
export interface TranpsortOptions {
/**
* Request decoder which is will be used by a server to decode HTTP Request
* into an invocation `Batch` that will be executed using a `service`.
Expand All @@ -321,27 +323,33 @@ export interface Server<T> {
* request.
*/
readonly encoder: Transport.ResponseEncoder
}

export interface ValidatorOptions {
/**
* Takes authority parser that can be used to turn an `UCAN.Identity`
* into `Ucanto.Authority`.
*/
readonly authority?: AuthorityParser

readonly canIssue?: CanIssue["canIssue"]
readonly my?: InvocationContext["my"]
readonly resolve?: InvocationContext["resolve"]
}

export interface ServerOptions extends TranpsortOptions, ValidatorOptions {
/**
* Service DID which will be used to verify that received invocation
* audience matches it.
*/
readonly id: Identity
}

export interface Server<T> extends ServerOptions {
/**
* Actual service providing capability handlers.
*/
readonly service: T

readonly canIssue?: CanIssue["canIssue"]
readonly my?: InvocationContext["my"]
readonly resolve?: InvocationContext["resolve"]
}

export interface ServerView<T> extends Server<T>, Transport.Channel<T> {
Expand Down
1 change: 0 additions & 1 deletion packages/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
},
"homepage": "https://github.com/web3-storage/ucanto",
"scripts": {
"prepare": "tsc --build",
"test:web": "playwright-test test/**/*.spec.js --cov && nyc report",
"test:node": "c8 --check-coverage --branches 100 --functions 100 --lines 100 mocha test/**/*.spec.js",
"test": "npm run test:node",
Expand Down
2 changes: 1 addition & 1 deletion packages/server/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export interface ProviderContext<
C extends API.Caveats = API.Caveats
> {
capability: API.ParsedCapability<A, API.InferCaveats<C>>
invocation: API.Invocation<API.Capability<A, R>>
invocation: API.Invocation<API.Capability<A, R> & API.InferCaveats<C>>

context: API.InvocationContext
}
6 changes: 3 additions & 3 deletions packages/server/src/handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ import { access } from "@ucanto/validator"
* @template {API.Caveats} C
* @template {API.Resource} R
* @template {unknown} U
* @param {API.TheCapabilityParser<A, C>} capability
* @param {API.TheCapabilityParser<API.CapabilityMatch<A, C>>} capability
* @param {(input:API.ProviderContext<A, R, C>) => API.Await<U>} handler
* @returns {API.ServiceMethod<API.Capability<A, R>, Exclude<U, {error:true}>, Exclude<U, Exclude<U, {error:true}>>|API.InvocationError>}
* @returns {API.ServiceMethod<API.Capability<A, R> & API.InferCaveats<C>, Exclude<U, {error:true}>, Exclude<U, Exclude<U, {error:true}>>>}
*/

export const provide =
(capability, handler) =>
/**
* @param {API.Invocation<API.Capability<A, R>>} invocation
* @param {API.Invocation<API.Capability<A, R> & API.InferCaveats<C>>} invocation
* @param {API.InvocationContext} options
* @return {Promise<API.Result<Exclude<U, {error:true}>, Exclude<U, Exclude<U, {error:true}>>|API.InvocationError>>}
*/
Expand Down
5 changes: 2 additions & 3 deletions packages/server/src/lib.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export * from "./server.js"
export * from "./handler.js"
// @ts-ignore
export * from "./api.js"

export { InvocationError } from "./server.js"
export * from "./handler.js"
10 changes: 8 additions & 2 deletions packages/server/src/server.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import * as API from "@ucanto/interface"
export * from "@ucanto/interface"
import { InvalidAudience, UnavailableProof } from "@ucanto/validator"
import { InvalidAudience } from "@ucanto/validator"
import { Authority } from "@ucanto/authority"
export { capability, URI, Link, Failure } from "@ucanto/validator"
export {
capability,
URI,
Link,
Failure,
MalformedCapability,
} from "@ucanto/validator"

/**
* Creates a connection to a service.
Expand Down
6 changes: 3 additions & 3 deletions packages/server/test/service/access.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const registerCapability = Server.capability({

const linkCapability = Server.capability({
can: "identity/link",
with: Server.URI.match({ protocol: "mailto:" }),
with: Server.URI,
derives: (claimed, delegated) =>
claimed.uri.href === delegated.uri.href ||
new Server.Failure(
Expand Down Expand Up @@ -96,7 +96,7 @@ const associate = (accounts, from, to, proof, create) => {
// account and link all them together.
if (!fromAccount && !toAccount) {
if (create) {
const account = /** @type {API.DID} */ (`did:cid:${proof}`)
const account = /** @type {API.DID} */ (`did:ipld:${proof}`)
accounts.set(to, { account, proof })
accounts.set(from, { account, proof })
} else {
Expand All @@ -107,7 +107,7 @@ const associate = (accounts, from, to, proof, create) => {
} else if (fromAccount) {
accounts.set(to, { account: fromAccount, proof })
} else if (fromAccount !== toAccount) {
const account = /** @type {API.DID} */ (`did:cid:${proof}`)
const account = /** @type {API.DID} */ (`did:ipld:${proof}`)
accounts.set(toAccount, { account, proof })
accounts.set(fromAccount, { account, proof })
}
Expand Down
1 change: 0 additions & 1 deletion packages/transport/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
},
"homepage": "https://github.com/web3-storage/ucanto",
"scripts": {
"prepare": "tsc --build",
"test:web": "playwright-test test/**/*.spec.js --cov && nyc report",
"test:node": "c8 --check-coverage --branches 100 --functions 100 --lines 100 mocha test/**/*.spec.js",
"test": "npm run test:node",
Expand Down
1 change: 0 additions & 1 deletion packages/validator/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
},
"homepage": "https://github.com/web3-storage/ucanto",
"scripts": {
"prepare": "tsc --build",
"test:web": "playwright-test test/**/*.spec.js --cov && nyc report",
"test:node": "c8 --check-coverage --branches 90 --functions 80 --lines 90 mocha test/**/*.spec.js",
"test": "npm run test:node",
Expand Down
17 changes: 10 additions & 7 deletions packages/validator/src/capability.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import {

/**
* @template {API.Ability} A
* @template {API.Caveats} C
* @template {API.Caveats} [C={}]
* @param {API.Descriptor<A, C>} descriptor
* @returns {API.TheCapabilityParser<A, C, API.CapabilityMatch<A, C>>}
* @returns {API.TheCapabilityParser<API.CapabilityMatch<A, C>>}
*/
export const capability = descriptor => new Capability(descriptor)

Expand All @@ -35,7 +35,7 @@ export const and = (...selectors) => new And(selectors)
* @template {API.Match} M
* @template {API.ParsedCapability} T
* @param {API.DeriveSelector<M, T> & { from: API.MatchSelector<M> }} options
* @returns {API.CapabilityParser<API.DerivedMatch<T, M>>}
* @returns {API.TheCapabilityParser<API.DerivedMatch<T, M>>}
*/
export const derive = ({ from, to, derives }) => new Derive(from, to, derives)

Expand All @@ -62,7 +62,7 @@ class View {
/**
* @template {API.ParsedCapability} U
* @param {API.DeriveSelector<M, U>} options
* @returns {API.CapabilityParser<API.DerivedMatch<U, M>>}
* @returns {API.TheCapabilityParser<API.DerivedMatch<U, M>>}
*/
derive({ derives, to }) {
return derive({ derives, to, from: this })
Expand Down Expand Up @@ -97,7 +97,7 @@ class Unit extends View {
/**
* @template {API.Ability} A
* @template {API.Caveats} C
* @implements {API.TheCapabilityParser<A, C, API.CapabilityMatch<A, C>>}
* @implements {API.TheCapabilityParser<API.CapabilityMatch<A, C>>}
* @extends {Unit<API.CapabilityMatch<A, C>>}
*/
class Capability extends Unit {
Expand Down Expand Up @@ -220,14 +220,14 @@ class And extends View {
/**
* @template {API.ParsedCapability} T
* @template {API.Match} M
* @implements {API.CapabilityParser<API.DerivedMatch<T, M>>}
* @implements {API.TheCapabilityParser<API.DerivedMatch<T, M>>}
* @extends {Unit<API.DerivedMatch<T, M>>}
*/

class Derive extends Unit {
/**
* @param {API.MatchSelector<M>} from
* @param {API.MatchSelector<API.DirectMatch<T>>} to
* @param {API.TheCapabilityParser<API.DirectMatch<T>>} to
* @param {API.Derives<T, M['value']>} derives
*/
constructor(from, to, derives) {
Expand All @@ -236,6 +236,9 @@ class Derive extends Unit {
this.to = to
this.derives = derives
}
get can() {
return this.to.can
}
/**
* @param {API.Source} capability
* @returns {API.MatchResult<API.DerivedMatch<T, M>>}
Expand Down
3 changes: 2 additions & 1 deletion packages/validator/src/lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import {
InvalidSignature,
DelegationError,
Failure,
MalformedCapability,
li,
} from "./error.js"

export { Failure, UnavailableProof }
export { Failure, UnavailableProof, MalformedCapability }

export { capability } from "./capability.js"

Expand Down

0 comments on commit 4308fd2

Please sign in to comment.