Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@oasislabs/parcel

Package Overview
Dependencies
Maintainers
77
Versions
38
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@oasislabs/parcel - npm Package Compare versions

Comparing version 0.1.7 to 0.1.8

lib/conditions.d.ts

76

lib/app.d.ts
import type { Except, Opaque } from 'type-fest';
import { Consent } from './consent.js';
import type { ConsentCreateParams, ConsentId } from './consent.js';
import type { HttpClient } from './http.js';
import type { IdentityId, IdentityTokenVerifierCreate } from './identity.js';
import type { Model, Page, PageParams, PODModel, ResourceId, WritableExcluding } from './model.js';
export declare type AppId = Opaque<ResourceId>;
export declare type PODApp = PODModel & {
import { Permission } from './permission.js';
import type { PermissionCreateParams, PermissionId } from './permission.js';
export declare type AppId = Opaque<ResourceId, 'AppId'>;
export declare type PODApp = Readonly<PODModel & {
acceptanceText?: string;

@@ -31,43 +31,43 @@ admins: ResourceId[];

trusted: boolean;
};
}>;
export declare class App implements Model {
private readonly client;
id: AppId;
createdAt: Date;
readonly id: AppId;
readonly createdAt: Date;
/** The Identity that created the app. */
owner: IdentityId;
admins: IdentityId[];
readonly owner: IdentityId;
readonly admins: IdentityId[];
/** Identities that can view participation of the app and modify un-privileged fields. */
collaborators: IdentityId[];
/** Whether this app has been published. Consents may not be modified after publishing, */
published: boolean;
readonly collaborators: IdentityId[];
/** Whether this app has been published. Permissions may not be modified after publishing, */
readonly published: boolean;
/** If `true`, only invited Identities may participate in the app. */
inviteOnly: boolean;
readonly inviteOnly: boolean;
/** Identities invited to participate in this app. */
invites: IdentityId[];
readonly invites: IdentityId[];
/** The set of identities that are currently authorizing this app. */
participants: IdentityId[];
readonly participants: IdentityId[];
/** Allow non-admin users to upload datasets. */
allowUserUploads: boolean;
name: string;
readonly allowUserUploads: boolean;
readonly name: string;
/** The name of the app publisher's organization. */
organization: string;
shortDescription: string;
readonly organization: string;
readonly shortDescription: string;
/** The app publisher's homepage URL. */
homepageUrl: string;
readonly homepageUrl: string;
/** A URL pointing to (or containing) the app's logo. */
logoUrl: string;
readonly logoUrl: string;
/** The privacy policy presented to the user when joining the app. */
privacyPolicy: string;
readonly privacyPolicy: string;
/** The terms and conditions presented to the user when joining the app. */
termsAndConditions: string;
readonly termsAndConditions: string;
/** Text shown to the user when viewing the app's invite page. */
invitationText?: string;
readonly invitationText?: string;
/** Text shown to the user after accepting the app's invitation. */
acceptanceText?: string;
readonly acceptanceText?: string;
/** Text shown to the user after rejecting the app's invitation. */
rejectionText?: string;
extendedDescription?: string;
readonly rejectionText?: string;
readonly extendedDescription?: string;
/** The app's branding color in RGB hex format (e.g. `#ff4212`). */
brandingColor?: string;
readonly brandingColor?: string;
/**

@@ -77,4 +77,4 @@ * Text describing the category of the app (e.g., health, finance) that can

*/
category?: string;
trusted: boolean;
readonly category?: string;
readonly trusted: boolean;
constructor(client: HttpClient, pod: PODApp);

@@ -84,15 +84,15 @@ update(params: AppUpdateParams): Promise<App>;

/**
* Creates a new consent that this app will request from users. The new consent
* will be added to `this.consents`.
* Creates a new permission that this app will request from users. The new permission
* will be added to `this.permissions`.
*/
createConsent(params: ConsentCreateParams): Promise<Consent>;
createPermission(params: PermissionCreateParams): Promise<Permission>;
/**
* Returns the consents associated with this app.
* Returns the permissions associated with this app.
*/
listConsents(): Promise<Page<Consent>>;
listPermissions(filter?: PageParams): Promise<Page<Permission>>;
/**
* Deletes a consent from this app, revoking any access made by granting consent.
* will be removed from `this.consents`.
* Deletes a permission from this app, revoking any access made by granting permission.
* will be removed from `this.permissions`.
*/
deleteConsent(consentId: ConsentId): Promise<void>;
deletePermission(permissionId: PermissionId): Promise<void>;
}

@@ -99,0 +99,0 @@ export declare namespace AppImpl {

@@ -1,2 +0,3 @@

import { ConsentImpl } from './consent.js';
import { makePage } from './model.js';
import { PermissionImpl } from './permission.js';
export class App {

@@ -38,20 +39,20 @@ constructor(client, pod) {

/**
* Creates a new consent that this app will request from users. The new consent
* will be added to `this.consents`.
* Creates a new permission that this app will request from users. The new permission
* will be added to `this.permissions`.
*/
async createConsent(params) {
return ConsentImpl.create(this.client, this.id, params);
async createPermission(params) {
return PermissionImpl.create(this.client, this.id, params);
}
/**
* Returns the consents associated with this app.
* Returns the permissions associated with this app.
*/
async listConsents() {
return ConsentImpl.list(this.client, this.id);
async listPermissions(filter) {
return PermissionImpl.list(this.client, this.id, filter);
}
/**
* Deletes a consent from this app, revoking any access made by granting consent.
* will be removed from `this.consents`.
* Deletes a permission from this app, revoking any access made by granting permission.
* will be removed from `this.permissions`.
*/
async deleteConsent(consentId) {
return ConsentImpl.delete_(this.client, this.id, consentId);
async deletePermission(permissionId) {
return PermissionImpl.delete_(this.client, this.id, permissionId);
}

@@ -62,7 +63,9 @@ }

async function create(client, params) {
return client.create(APPS_EP, params).then((podApp) => new App(client, podApp));
const podApp = await client.create(APPS_EP, params);
return new App(client, podApp);
}
AppImpl.create = create;
async function get(client, id) {
return client.get(endpointForId(id)).then((podApp) => new App(client, podApp));
const podApp = await client.get(endpointForId(id));
return new App(client, podApp);
}

@@ -72,13 +75,8 @@ AppImpl.get = get;

const podPage = await client.get(APPS_EP, filter);
const results = podPage.results.map((podApp) => new App(client, podApp));
return {
results,
nextPageToken: podPage.nextPageToken,
};
return makePage(App, podPage, client);
}
AppImpl.list = list;
async function update(client, id, params) {
return client
.update(endpointForId(id), params)
.then((podApp) => new App(client, podApp));
const podApp = await client.update(endpointForId(id), params);
return new App(client, podApp);
}

@@ -85,0 +83,0 @@ AppImpl.update = update;

@@ -7,4 +7,4 @@ import type { Except, Opaque } from 'type-fest';

import type { PublicJWK } from './token.js';
export declare type ClientId = Opaque<ResourceId>;
export declare type PODClient = PODModel & {
export declare type ClientId = Opaque<ResourceId, 'ClientId'>;
export declare type PODClient = Readonly<PODModel & {
creator: ResourceId;

@@ -19,16 +19,16 @@ appId: ResourceId;

isScript: boolean;
};
}>;
export declare class Client implements Model {
private readonly client;
id: ClientId;
createdAt: Date;
creator: IdentityId;
appId: AppId;
name: string;
redirectUris: string[];
postLogoutRedirectUris: string[];
publicKeys: PublicJWK[];
canHoldSecrets: boolean;
canActOnBehalfOfUsers: boolean;
isScript: boolean;
readonly id: ClientId;
readonly createdAt: Date;
readonly creator: IdentityId;
readonly appId: AppId;
readonly name: string;
readonly redirectUris: string[];
readonly postLogoutRedirectUris: string[];
readonly publicKeys: PublicJWK[];
readonly canHoldSecrets: boolean;
readonly canActOnBehalfOfUsers: boolean;
readonly isScript: boolean;
constructor(client: HttpClient, pod: PODClient);

@@ -35,0 +35,0 @@ update(params: ClientUpdateParams): Promise<Client>;

@@ -28,11 +28,9 @@ import { endpointForId as endpointForApp } from './app.js';

async function create(client, appId, params) {
return client
.create(endpointForCollection(appId), params)
.then((podClient) => new Client(client, podClient));
const podClient = await client.create(endpointForCollection(appId), params);
return new Client(client, podClient);
}
ClientImpl.create = create;
async function get(client, appId, clientId) {
return client
.get(endpointForId(appId, clientId))
.then((podClient) => new Client(client, podClient));
const podClient = await client.get(endpointForId(appId, clientId));
return new Client(client, podClient);
}

@@ -50,5 +48,4 @@ ClientImpl.get = get;

async function update(client, appId, clientId, params) {
return client
.update(endpointForId(appId, clientId), params)
.then((podClient) => new Client(client, podClient));
const podClient = await client.update(endpointForId(appId, clientId), params);
return new Client(client, podClient);
}

@@ -55,0 +52,0 @@ ClientImpl.update = update;

@@ -5,4 +5,5 @@ import type { Opaque } from 'type-fest';

import type { IdentityId } from './identity.js';
import type { Page, PageParams } from './model.js';
export declare type JobId = Opaque<string, 'JobId'>;
import type { Page, PageParams, PODModel } from './model.js';
import { ResourceId } from './model.js';
export declare type JobId = Opaque<ResourceId, 'JobId'>;
/**

@@ -96,5 +97,5 @@ * Input dataset for a compute job.

}
export declare type PODJob = {
readonly id: JobId;
readonly spec: JobSpec;
export declare type PODJob = Readonly<PODModel & {
id: JobId;
spec: JobSpec;
/**

@@ -105,4 +106,4 @@ * Most recently observed status of the pod. This data may not be up to

*/
readonly status: JobStatus;
};
status: JobStatus;
}>;
/**

@@ -112,6 +113,8 @@ * An existing, already-submitted job. The job might also be already completed.

export declare class Job {
private readonly client;
readonly id: JobId;
readonly createdAt: Date;
readonly spec: JobSpec;
readonly status: JobStatus;
constructor(pod: PODJob);
constructor(client: HttpClient, pod: PODJob);
}

@@ -118,0 +121,0 @@ export declare namespace ComputeImpl {

@@ -0,1 +1,2 @@

import { makePage } from './model.js';
export var JobPhase;

@@ -12,4 +13,6 @@ (function (JobPhase) {

export class Job {
constructor(pod) {
constructor(client, pod) {
this.client = client;
this.id = pod.id;
this.createdAt = new Date(pod.createdAt);
this.spec = pod.spec;

@@ -25,14 +28,14 @@ this.status = pod.status;

async function submitJob(client, spec) {
return client.post(JOBS_EP, spec).then((pod) => new Job(pod));
const pod = await client.post(JOBS_EP, spec);
return new Job(client, pod);
}
ComputeImpl.submitJob = submitJob;
async function listJobs(client, filter = {}) {
return client.get(JOBS_EP, filter).then((podPage) => ({
results: podPage.results.map((podJob) => new Job(podJob)),
nextPageToken: podPage.nextPageToken,
}));
const podPage = await client.get(JOBS_EP, filter);
return makePage(Job, podPage, client);
}
ComputeImpl.listJobs = listJobs;
async function getJob(client, jobId) {
return client.get(endpointForId(jobId)).then((pod) => new Job(pod));
const pod = await client.get(endpointForId(jobId));
return new Job(client, pod);
}

@@ -39,0 +42,0 @@ ComputeImpl.getJob = getJob;

@@ -7,4 +7,4 @@ import EventEmitter from 'eventemitter3';

import type { Model, Page, PageParams, PODModel, ResourceId, WritableExcluding } from './model.js';
export declare type DatasetId = Opaque<ResourceId>;
export declare type PODDataset = PODModel & {
export declare type DatasetId = Opaque<ResourceId, 'DatasetId'>;
export declare type PODDataset = Readonly<PODModel & {
id: ResourceId;

@@ -15,8 +15,8 @@ creator: ResourceId;

details: DatasetDetails;
};
export declare type PODAccessEvent = {
}>;
export declare type PODAccessEvent = Readonly<{
createdAt: string;
dataset: ResourceId;
accessor: ResourceId;
};
}>;
declare type DatasetDetails = {

@@ -28,9 +28,9 @@ title?: string;

private readonly client;
id: DatasetId;
createdAt: Date;
creator: IdentityId;
size: number;
owner: IdentityId;
readonly id: DatasetId;
readonly createdAt: Date;
readonly creator: IdentityId;
readonly size: number;
readonly owner: IdentityId;
/** Additional, optional information about the dataset. */
details: DatasetDetails;
readonly details: DatasetDetails;
constructor(client: HttpClient, pod: PODDataset);

@@ -37,0 +37,0 @@ /**

import EventEmitter from 'eventemitter3';
import FormData from 'form-data';
import { makePage } from './model.js';
export class Dataset {

@@ -35,5 +36,4 @@ constructor(client, pod) {

async function get(client, id) {
return client
.get(endpointForId(id))
.then((podDataset) => new Dataset(client, podDataset));
const podDataset = await client.get(endpointForId(id));
return new Dataset(client, podDataset);
}

@@ -54,7 +54,3 @@ DatasetImpl.get = get;

});
const results = podPage.results.map((podDataset) => new Dataset(client, podDataset));
return {
results,
nextPageToken: podPage.nextPageToken,
};
return makePage(Dataset, podPage, client);
}

@@ -93,5 +89,4 @@ DatasetImpl.list = list;

async function update(client, id, params) {
return client
.update(endpointForId(id), params)
.then((podDataset) => new Dataset(client, podDataset));
const podDataset = await client.update(endpointForId(id), params);
return new Dataset(client, podDataset);
}

@@ -148,2 +143,3 @@ DatasetImpl.update = update;

})
// eslint-disable-next-line promise/prefer-await-to-then
.then((podDataset) => {

@@ -150,0 +146,0 @@ this.emit('finish', new Dataset(client, podDataset));

import type { Opaque } from 'type-fest';
import type { ConsentId } from './consent.js';
import type { Constraints } from './filter.js';
import type { Conditions } from './conditions.js';
import type { HttpClient } from './http.js';
import type { IdentityId } from './identity.js';
import type { Model, Page, PageParams, PODModel, ResourceId } from './model.js';
export declare type GrantId = Opaque<ResourceId>;
export declare type PODGrant = PODModel & {
import type { PermissionId } from './permission.js';
export declare type GrantId = Opaque<ResourceId, 'GrantId'>;
export declare type PODGrant = Readonly<PODModel & {
granter: ResourceId;
grantee?: ResourceId;
consent?: ResourceId;
filter?: Constraints;
};
permission?: ResourceId;
conditions?: Conditions;
}>;
export declare type GrantCreateParams = {

@@ -19,19 +19,19 @@ /**

grantee: IdentityId | 'everyone';
/** A filter that gives permission to only matching Datasets. */
filter?: Constraints;
/** Conditoins that must be matched to recieve access to one or more Datasets. */
conditions?: Conditions;
};
export declare class Grant implements Model {
private readonly client;
id: GrantId;
createdAt: Date;
readonly id: GrantId;
readonly createdAt: Date;
/** The Identity from which permission is given. */
granter: IdentityId;
readonly granter: IdentityId;
/**
* The Identity to which permission is given or everyone,
*/
grantee: IdentityId | 'everyone';
/** A filter that gives permission to only matching Datasets. */
filter?: Constraints;
/** The Consent that created this Grant, if any. */
consent?: ConsentId;
readonly grantee: IdentityId | 'everyone';
/** Conditions that describe Datasets to be shared. */
readonly conditions?: Conditions;
/** The Permission that created this Grant, if any. */
readonly permission?: PermissionId;
constructor(client: HttpClient, pod: PODGrant);

@@ -38,0 +38,0 @@ delete(): Promise<void>;

@@ -0,1 +1,2 @@

import { makePage } from './model.js';
const GRANTS_EP = 'grants';

@@ -11,4 +12,4 @@ const endpointForId = (id) => `${GRANTS_EP}/${id}`;

this.grantee = (_a = pod.grantee) !== null && _a !== void 0 ? _a : 'everyone';
this.filter = pod.filter;
this.consent = pod.consent;
this.conditions = pod.conditions;
this.permission = pod.permission;
}

@@ -22,9 +23,9 @@ async delete() {

async function create(client, params) {
return client
.create(GRANTS_EP, params)
.then((podGrant) => new Grant(client, podGrant));
const podGrant = await client.create(GRANTS_EP, params);
return new Grant(client, podGrant);
}
GrantImpl.create = create;
async function get(client, id) {
return client.get(endpointForId(id)).then((podGrant) => new Grant(client, podGrant));
const podGrant = await client.get(endpointForId(id));
return new Grant(client, podGrant);
}

@@ -34,7 +35,3 @@ GrantImpl.get = get;

const podPage = await client.get(GRANTS_EP, filter);
const results = podPage.results.map((podGrant) => new Grant(client, podGrant));
return {
results,
nextPageToken: podPage.nextPageToken,
};
return makePage(Grant, podPage, client);
}

@@ -41,0 +38,0 @@ GrantImpl.list = list;

@@ -161,5 +161,4 @@ import AbortController from 'abort-controller';

async pipeTo(sink) {
var _a;
if ('getWriter' in sink) {
const body = (await this.makeRequest()).body;
const { body } = await this.makeRequest();
if (!body)

@@ -174,4 +173,4 @@ return;

}
const stream = await import('stream');
const Readable = (_a = stream.Readable) !== null && _a !== void 0 ? _a : stream.default.Readable; // Imported differently depending on i-dont-know-what :/
// eslint-disable-next-line node/no-unsupported-features/es-syntax
const { Readable } = await import('stream'); // This only happens in the browser.
return new Promise((resolve, reject) => {

@@ -206,3 +205,3 @@ Readable.from(this, { objectMode: false })

this.name = 'ApiError';
const context = request.context;
const { context } = request;
if (context) {

@@ -209,0 +208,0 @@ message = `error in ${context}: ${message}`;

import type { Opaque, SetOptional } from 'type-fest';
import type { AppId } from './app.js';
import { Consent } from './consent.js';
import type { ConsentId } from './consent.js';
import type { HttpClient } from './http.js';
import type { Model, Page, PageParams, PODModel, ResourceId, Writable } from './model.js';
import { Permission } from './permission.js';
import type { PermissionId } from './permission.js';
import type { IdentityTokenClaims, PublicJWK } from './token.js';
export declare type IdentityId = Opaque<ResourceId>;
export declare type PODIdentity = PODModel & IdentityCreateParams;
export declare type IdentityId = Opaque<ResourceId, 'IdentityId' | 'AppId'>;
export declare type PODIdentity = Readonly<PODModel & IdentityCreateParams>;
export declare class Identity implements Model {
private readonly client;
id: IdentityId;
createdAt: Date;
tokenVerifiers: IdentityTokenVerifier[];
readonly id: IdentityId;
readonly createdAt: Date;
readonly tokenVerifiers: IdentityTokenVerifier[];
constructor(client: HttpClient, pod: PODIdentity);
update(params: IdentityUpdateParams): Promise<Identity>;
delete(): Promise<void>;
grantConsent(id: ConsentId): Promise<void>;
/** Fetches consents to which this identity has consented. */
listGrantedConsents(filter?: ListGrantedConsentsFilter & PageParams): Promise<Page<Consent>>;
/** * Gets a granted consent by id. Useful for checking if a consent has been granted. */
getGrantedConsent(id: ConsentId): Promise<Consent>;
revokeConsent(id: ConsentId): Promise<void>;
grantPermission(id: PermissionId): Promise<void>;
/** Fetches permissions to which this identity has agreed. */
listGrantedPermissions(filter?: ListGrantedPermissionsFilter & PageParams): Promise<Page<Permission>>;
/** * Gets a granted permission by id. Useful for checking if a permission has been granted. */
getGrantedPermission(id: PermissionId): Promise<Permission>;
revokePermission(id: PermissionId): Promise<void>;
}

@@ -31,6 +31,6 @@ export declare namespace IdentityImpl {

function delete_(client: HttpClient, id: IdentityId): Promise<void>;
function grantConsent(client: HttpClient, identityId: IdentityId, consentId: ConsentId): Promise<void>;
function listGrantedConsents(client: HttpClient, identityId: IdentityId, filter?: ListGrantedConsentsFilter & PageParams): Promise<Page<Consent>>;
function getGrantedConsent(client: HttpClient, identityId: IdentityId, consentId: ConsentId): Promise<Consent>;
function revokeConsent(client: HttpClient, identityId: IdentityId, consentId: ConsentId): Promise<void>;
function grantPermission(client: HttpClient, identityId: IdentityId, permissionId: PermissionId): Promise<void>;
function listGrantedPermissions(client: HttpClient, identityId: IdentityId, filter?: ListGrantedPermissionsFilter & PageParams): Promise<Page<Permission>>;
function getGrantedPermission(client: HttpClient, identityId: IdentityId, permissionId: PermissionId): Promise<Permission>;
function revokePermission(client: HttpClient, identityId: IdentityId, permissionId: PermissionId): Promise<void>;
}

@@ -45,5 +45,5 @@ export declare type IdentityCreateParams = IdentityUpdateParams & {

export declare type IdentityTokenVerifierCreate = SetOptional<IdentityTokenVerifier, 'sub' | 'iss'>;
export declare type ListGrantedConsentsFilter = Partial<{
/** Only return consents granted to this app. */
export declare type ListGrantedPermissionsFilter = Partial<{
/** Only return permissions granted to this app. */
app: AppId;
}>;

@@ -1,8 +0,8 @@

import { Consent } from './consent.js';
import { setExpectedStatus } from './http.js';
import { Permission } from './permission.js';
const IDENTITIES_EP = 'identities';
const IDENTITIES_ME = `${IDENTITIES_EP}/me`;
const endpointForId = (id) => `${IDENTITIES_EP}/${id}`;
const endpointForConsents = (id) => `${endpointForId(id)}/consents`;
const endpointForConsent = (identityId, consentId) => `${endpointForConsents(identityId)}/${consentId}`;
const endpointForPermissions = (id) => `${endpointForId(id)}/permissions`;
const endpointForPermission = (identityId, permissionId) => `${endpointForPermissions(identityId)}/${permissionId}`;
export class Identity {

@@ -22,15 +22,15 @@ constructor(client, pod) {

}
async grantConsent(id) {
return IdentityImpl.grantConsent(this.client, this.id, id);
async grantPermission(id) {
return IdentityImpl.grantPermission(this.client, this.id, id);
}
/** Fetches consents to which this identity has consented. */
async listGrantedConsents(filter) {
return IdentityImpl.listGrantedConsents(this.client, this.id, filter);
/** Fetches permissions to which this identity has agreed. */
async listGrantedPermissions(filter) {
return IdentityImpl.listGrantedPermissions(this.client, this.id, filter);
}
/** * Gets a granted consent by id. Useful for checking if a consent has been granted. */
async getGrantedConsent(id) {
return IdentityImpl.getGrantedConsent(this.client, this.id, id);
/** * Gets a granted permission by id. Useful for checking if a permission has been granted. */
async getGrantedPermission(id) {
return IdentityImpl.getGrantedPermission(this.client, this.id, id);
}
async revokeConsent(id) {
return IdentityImpl.revokeConsent(this.client, this.id, id);
async revokePermission(id) {
return IdentityImpl.revokePermission(this.client, this.id, id);
}

@@ -41,23 +41,19 @@ }

async function create(client, params) {
return client
.create(IDENTITIES_EP, params)
.then((podIdentity) => new Identity(client, podIdentity));
const podIdentity = await client.create(IDENTITIES_EP, params);
return new Identity(client, podIdentity);
}
IdentityImpl.create = create;
async function current(client) {
return client
.get(IDENTITIES_ME)
.then((podIdentity) => new Identity(client, podIdentity));
const podIdentity = await client.get(IDENTITIES_ME);
return new Identity(client, podIdentity);
}
IdentityImpl.current = current;
async function get(client, id) {
return client
.get(endpointForId(id))
.then((podIdentity) => new Identity(client, podIdentity));
const podIdentity = await client.get(endpointForId(id));
return new Identity(client, podIdentity);
}
IdentityImpl.get = get;
async function update(client, id, params) {
return client
.update(endpointForId(id), params)
.then((podIdentity) => new Identity(client, podIdentity));
const podIdentity = await client.update(endpointForId(id), params);
return new Identity(client, podIdentity);
}

@@ -69,4 +65,4 @@ IdentityImpl.update = update;

IdentityImpl.delete_ = delete_;
async function grantConsent(client, identityId, consentId) {
await client.post(endpointForConsent(identityId, consentId), undefined, {
async function grantPermission(client, identityId, permissionId) {
await client.post(endpointForPermission(identityId, permissionId), undefined, {
hooks: {

@@ -77,6 +73,6 @@ beforeRequest: [setExpectedStatus(204)],

}
IdentityImpl.grantConsent = grantConsent;
async function listGrantedConsents(client, identityId, filter) {
const podPage = await client.get(endpointForConsents(identityId), filter);
const results = podPage.results.map((podConsent) => new Consent(client, podConsent));
IdentityImpl.grantPermission = grantPermission;
async function listGrantedPermissions(client, identityId, filter) {
const podPage = await client.get(endpointForPermissions(identityId), filter);
const results = podPage.results.map((podPermission) => new Permission(client, podPermission));
return {

@@ -87,14 +83,13 @@ results,

}
IdentityImpl.listGrantedConsents = listGrantedConsents;
async function getGrantedConsent(client, identityId, consentId) {
return client
.get(endpointForConsent(identityId, consentId))
.then((podConsent) => new Consent(client, podConsent));
IdentityImpl.listGrantedPermissions = listGrantedPermissions;
async function getGrantedPermission(client, identityId, permissionId) {
const podPermission = await client.get(endpointForPermission(identityId, permissionId));
return new Permission(client, podPermission);
}
IdentityImpl.getGrantedConsent = getGrantedConsent;
async function revokeConsent(client, identityId, consentId) {
await client.delete(endpointForConsent(identityId, consentId));
IdentityImpl.getGrantedPermission = getGrantedPermission;
async function revokePermission(client, identityId, permissionId) {
await client.delete(endpointForPermission(identityId, permissionId));
}
IdentityImpl.revokeConsent = revokeConsent;
IdentityImpl.revokePermission = revokePermission;
})(IdentityImpl || (IdentityImpl = {}));
//# sourceMappingURL=identity.js.map
import type { App, AppCreateParams, AppId, AppUpdateParams, ListAppsFilter } from './app.js';
import type { Client, ClientCreateParams, ClientId, ClientUpdateParams, ListClientsFilter } from './client.js';
import type { Consent, ConsentCreateParams, ConsentId } from './consent.js';
import type { AccessEvent, Dataset, DatasetId, DatasetUpdateParams, DatasetUploadParams, ListAccessLogFilter, ListDatasetsFilter, Storable, Upload } from './dataset.js';

@@ -13,4 +12,5 @@ import type { Job, JobId, JobSpec, JobStatus } from './compute.js';

import type { Page, PageParams } from './model.js';
import type { Permission, PermissionCreateParams, PermissionId } from './permission.js';
import type { ClientCredentials, PrivateJWK, PublicJWK, TokenSource } from './token.js';
export { AccessEvent, App, AppCreateParams, AppId, AppUpdateParams, Client, ClientCreateParams, ClientCredentials, ClientId, Consent, ConsentCreateParams, ConsentId, Dataset, DatasetId, DatasetUpdateParams, DatasetUploadParams, ApiError, Grant, GrantCreateParams, GrantId, Identity, IdentityCreateParams, IdentityId, IdentityUpdateParams, InputDatasetSpec, Job, JobId, JobPhase, JobSpec, JobStatus, OutputDataset, OutputDatasetSpec, Page, PageParams, PrivateJWK, PublicJWK, Storable, TokenSource, };
export { AccessEvent, App, AppCreateParams, AppId, AppUpdateParams, Client, ClientCreateParams, ClientCredentials, ClientId, Permission, PermissionCreateParams, PermissionId, Dataset, DatasetId, DatasetUpdateParams, DatasetUploadParams, ApiError, Grant, GrantCreateParams, GrantId, Identity, IdentityCreateParams, IdentityId, IdentityUpdateParams, InputDatasetSpec, Job, JobId, JobPhase, JobSpec, JobStatus, OutputDataset, OutputDatasetSpec, Page, PageParams, PrivateJWK, PublicJWK, Storable, TokenSource, };
export default class Parcel {

@@ -35,5 +35,5 @@ private currentIdentity?;

deleteApp(id: AppId): Promise<void>;
createConsent(appId: AppId, params: ConsentCreateParams): Promise<Consent>;
listConsents(appId: AppId, filter: PageParams): Promise<Page<Consent>>;
deleteConsent(appId: AppId, consentId: ConsentId): Promise<void>;
createPermission(appId: AppId, params: PermissionCreateParams): Promise<Permission>;
listPermissions(appId: AppId, filter: PageParams): Promise<Page<Permission>>;
deletePermission(appId: AppId, permissionId: PermissionId): Promise<void>;
createClient(appId: AppId, params: ClientCreateParams): Promise<Client>;

@@ -40,0 +40,0 @@ getClient(appId: AppId, clientId: ClientId): Promise<Client>;

import { AppImpl } from './app.js';
import { ClientImpl } from './client.js';
import { ConsentImpl } from './consent.js';
import { DatasetImpl } from './dataset.js';

@@ -9,2 +8,3 @@ import { ComputeImpl, JobPhase, } from './compute.js';

import { IdentityImpl } from './identity.js';
import { PermissionImpl } from './permission.js';
import { TokenProvider } from './token.js';

@@ -68,10 +68,10 @@ export { ApiError, JobPhase, };

}
async createConsent(appId, params) {
return ConsentImpl.create(this.client, appId, params);
async createPermission(appId, params) {
return PermissionImpl.create(this.client, appId, params);
}
async listConsents(appId, filter) {
return ConsentImpl.list(this.client, appId, filter);
async listPermissions(appId, filter) {
return PermissionImpl.list(this.client, appId, filter);
}
async deleteConsent(appId, consentId) {
return ConsentImpl.delete_(this.client, appId, consentId);
async deletePermission(appId, permissionId) {
return PermissionImpl.delete_(this.client, appId, permissionId);
}

@@ -78,0 +78,0 @@ async createClient(appId, params) {

import type { ConditionalExcept, Except, JsonValue } from 'type-fest';
import type { HttpClient } from './http.js';
export declare type ResourceId = string;

@@ -11,5 +12,5 @@ export interface PODModel {

/** The model's unique ID. */
id: ResourceId;
readonly id: ResourceId;
/** The number of seconds since the Unix epoch when this model was created */
createdAt: Date;
readonly createdAt: Date;
}

@@ -24,3 +25,6 @@ export declare type Writable<T extends Model> = WritableExcluding<T, never>;

pageSize: number;
nextPageToken: string;
pageToken: string;
}>;
export declare function makePage<Pod extends PODModel, M extends Model>(ModelTy: {
new (client: HttpClient, pod: Pod): M;
}, podPage: Page<Pod>, client: HttpClient): Page<M>;

@@ -1,2 +0,9 @@

export {};
export function makePage(
// eslint-disable-next-line @typescript-eslint/prefer-function-type
ModelTy, podPage, client) {
return {
results: podPage.results.map((podModel) => new ModelTy(client, podModel)),
nextPageToken: podPage.nextPageToken,
};
}
//# sourceMappingURL=model.js.map
import type { ResponsePromise } from 'ky';
import type { Except } from 'type-fest';
import type { IdentityId } from './identity.js';
import './polyfill.js';

@@ -31,10 +32,8 @@ export declare const PARCEL_RUNTIME_AUD = "https://api.oasislabs.com/parcel";

* The identity provider's OAuth token retrieval endpoint.
* If left undefined, the access token will be self-signed with the `clientId`
* as the issuer.
*/
tokenEndpoint: string;
tokenEndpoint?: string;
/**
* The audience to use when using provider's OAuth token retrieval endpoint.
*/
audience: string;
audience?: string;
/**

@@ -44,3 +43,3 @@ * A list of scopes that will be requested from the identity provider, which

*/
scopes: string[];
scopes?: string[];
};

@@ -53,6 +52,6 @@ /** A `TokenProvider` that obtains a new token by re-authenticating to the issuer. */

private readonly scopes;
private readonly privateKey;
private readonly privateKeyPEM;
private readonly keyId;
private readonly clientAssertionLifetime;
constructor({ clientId, privateKey: privateJWK, scopes, tokenEndpoint, audience, }: RenewingTokenProviderParams);
constructor({ clientId, privateKey, scopes, tokenEndpoint, audience, }: RenewingTokenProviderParams);
protected renewToken(): Promise<Token>;

@@ -75,3 +74,3 @@ }

/** The `sub` and `iss` claims of the provided access token. */
principal: string;
principal: string | IdentityId;
/** The private key that will be used to sign the access token. */

@@ -93,7 +92,7 @@ privateKey: PrivateJWK;

private readonly principal;
private readonly privateKey;
private readonly privateKeyPEM;
private readonly keyId;
private readonly scopes;
private readonly tokenLifetime;
constructor({ principal, privateKey: privateJWK, scopes, tokenLifetime, }: SelfIssuedTokenProviderParams);
constructor({ principal, privateKey, scopes, tokenLifetime, }: SelfIssuedTokenProviderParams);
protected renewToken(): Promise<Token>;

@@ -100,0 +99,0 @@ }

import { KEYUTIL, KJUR } from 'jsrsasign';
import ky from 'ky';
import './polyfill.js'; // eslint-disable-line import/no-unassigned-import
const DEFAULT_TOKEN_ENDPOINT = 'https://auth.oasislabs.com/oauth/token';
export const PARCEL_RUNTIME_AUD = 'https://api.oasislabs.com/parcel'; // TODO(#326)

@@ -41,16 +42,19 @@ export class TokenProvider {

export class RenewingTokenProvider extends ExpiringTokenProvider {
constructor({ clientId, privateKey: privateJWK, scopes, tokenEndpoint, audience, }) {
constructor({ clientId, privateKey, scopes, tokenEndpoint, audience, }) {
super();
this.clientAssertionLifetime = 1 * 60 * 60; // 1 hour
const { privateKey, keyId } = jwkToPem(privateJWK);
this.privateKey = privateKey;
if (privateKey.kty !== 'EC') {
throw new Error('Private key should be an ECDSA key.');
}
const { privateKey: privateKeyPEM, keyId } = jwkToPem(privateKey);
this.privateKeyPEM = privateKeyPEM;
this.keyId = keyId;
this.clientId = clientId;
this.tokenEndpoint = tokenEndpoint;
this.audience = audience;
this.scopes = scopes;
this.tokenEndpoint = tokenEndpoint !== null && tokenEndpoint !== void 0 ? tokenEndpoint : DEFAULT_TOKEN_ENDPOINT;
this.audience = audience !== null && audience !== void 0 ? audience : PARCEL_RUNTIME_AUD;
this.scopes = scopes !== null && scopes !== void 0 ? scopes : ['parcel.temp_api', 'parcel.temp_storage'];
}
async renewToken() {
const clientAssertion = makeJWT({
privateKey: this.privateKey,
privateKey: this.privateKeyPEM,
keyId: this.keyId,

@@ -89,2 +93,3 @@ payload: {

res
// eslint-disable-next-line promise/prefer-await-to-then
.then(async (refreshResponse) => {

@@ -101,6 +106,6 @@ this.refreshToken = (await refreshResponse.clone().json()).refresh_token;

export class SelfIssuedTokenProvider extends ExpiringTokenProvider {
constructor({ principal, privateKey: privateJWK, scopes, tokenLifetime, }) {
constructor({ principal, privateKey, scopes, tokenLifetime, }) {
super();
const { privateKey, keyId } = jwkToPem(privateJWK);
this.privateKey = privateKey;
const { privateKey: privateKeyPEM, keyId } = jwkToPem(privateKey);
this.privateKeyPEM = privateKeyPEM;
this.keyId = keyId;

@@ -114,3 +119,3 @@ this.principal = principal;

const token = makeJWT({
privateKey: this.privateKey,
privateKey: this.privateKeyPEM,
keyId: this.keyId,

@@ -117,0 +122,0 @@ payload: {

{
"name": "@oasislabs/parcel",
"version": "0.1.7",
"version": "0.1.8",
"license": "Apache-2.0",

@@ -39,3 +39,3 @@ "author": "Oasis Labs <feedback@oasislabs.com>",

"^@oasislabs/parcel$": "<rootDir>/src/index",
"^\\./(app|client|compute|consent|dataset|filter|grant|http|identity|model|polyfill|token).js$": "<rootDir>/src/$1",
"^\\./(app|client|compute|condition|dataset|grant|http|identity|model|permission|polyfill|token).js$": "<rootDir>/src/$1",
"^@oasislabs/parcel/(.*)$": "<rootDir>/src/$1"

@@ -64,3 +64,2 @@ },

"@types/node": "^14.0.20",
"@types/node-fetch": "^2.5.8",
"@types/uuid": "^8.3.0",

@@ -91,3 +90,3 @@ "ajv": "^6.12.5",

"ky": "^0.26.0",
"node-fetch": "^2.6.1",
"node-fetch": "3.0.0-beta.9",
"param-case": "^3.0.3",

@@ -97,3 +96,6 @@ "type-fest": "^0.20.0",

},
"browserslist": ">2%"
"browserslist": ">2%",
"engines": {
"node": ">=14"
}
}
import type { Except, Opaque } from 'type-fest';
import { Consent, ConsentImpl } from './consent.js';
import type { ConsentCreateParams, ConsentId } from './consent.js';
import type { HttpClient } from './http.js';
import type { IdentityId, IdentityTokenVerifierCreate } from './identity.js';
import type { Model, Page, PageParams, PODModel, ResourceId, WritableExcluding } from './model.js';
import { makePage } from './model.js';
import { Permission, PermissionImpl } from './permission.js';
import type { PermissionCreateParams, PermissionId } from './permission.js';
export type AppId = Opaque<ResourceId>;
export type AppId = Opaque<ResourceId, 'AppId'>;
export type PODApp = PODModel & {
acceptanceText?: string;
admins: ResourceId[];
allowUserUploads: boolean;
brandingColor?: string;
category?: string;
collaborators: ResourceId[];
extendedDescription?: string;
homepageUrl: string;
invitationText?: string;
inviteOnly: boolean;
invites?: ResourceId[];
logoUrl: string;
name: string;
organization: string;
owner: ResourceId;
participants: ResourceId[];
published: boolean;
rejectionText?: string;
shortDescription: string;
termsAndConditions: string;
privacyPolicy: string;
trusted: boolean;
};
export type PODApp = Readonly<
PODModel & {
acceptanceText?: string;
admins: ResourceId[];
allowUserUploads: boolean;
brandingColor?: string;
category?: string;
collaborators: ResourceId[];
extendedDescription?: string;
homepageUrl: string;
invitationText?: string;
inviteOnly: boolean;
invites?: ResourceId[];
logoUrl: string;
name: string;
organization: string;
owner: ResourceId;
participants: ResourceId[];
published: boolean;
rejectionText?: string;
shortDescription: string;
termsAndConditions: string;
privacyPolicy: string;
trusted: boolean;
}
>;
export class App implements Model {
public id: AppId;
public createdAt: Date;
public readonly id: AppId;
public readonly createdAt: Date;
/** The Identity that created the app. */
public owner: IdentityId;
public admins: IdentityId[];
public readonly owner: IdentityId;
public readonly admins: IdentityId[];
/** Identities that can view participation of the app and modify un-privileged fields. */
public collaborators: IdentityId[];
public readonly collaborators: IdentityId[];
/** Whether this app has been published. Consents may not be modified after publishing, */
public published: boolean;
/** Whether this app has been published. Permissions may not be modified after publishing, */
public readonly published: boolean;
/** If `true`, only invited Identities may participate in the app. */
public inviteOnly: boolean;
public readonly inviteOnly: boolean;
/** Identities invited to participate in this app. */
public invites: IdentityId[];
public readonly invites: IdentityId[];
/** The set of identities that are currently authorizing this app. */
public participants: IdentityId[];
public readonly participants: IdentityId[];
/** Allow non-admin users to upload datasets. */
public allowUserUploads: boolean;
public readonly allowUserUploads: boolean;
public name: string;
public readonly name: string;
/** The name of the app publisher's organization. */
public organization: string;
public shortDescription: string;
public readonly organization: string;
public readonly shortDescription: string;
/** The app publisher's homepage URL. */
public homepageUrl: string;
public readonly homepageUrl: string;
/** A URL pointing to (or containing) the app's logo. */
public logoUrl: string;
public readonly logoUrl: string;
/** The privacy policy presented to the user when joining the app. */
public privacyPolicy: string;
public readonly privacyPolicy: string;
/** The terms and conditions presented to the user when joining the app. */
public termsAndConditions: string;
public readonly termsAndConditions: string;
/** Text shown to the user when viewing the app's invite page. */
public invitationText?: string;
public readonly invitationText?: string;
/** Text shown to the user after accepting the app's invitation. */
public acceptanceText?: string;
public readonly acceptanceText?: string;
/** Text shown to the user after rejecting the app's invitation. */
public rejectionText?: string;
public readonly rejectionText?: string;
public extendedDescription?: string;
public readonly extendedDescription?: string;
/** The app's branding color in RGB hex format (e.g. `#ff4212`). */
public brandingColor?: string;
public readonly brandingColor?: string;
/**

@@ -84,4 +87,4 @@ * Text describing the category of the app (e.g., health, finance) that can

*/
public category?: string;
public trusted: boolean;
public readonly category?: string;
public readonly trusted: boolean;

@@ -125,22 +128,22 @@ public constructor(private readonly client: HttpClient, pod: PODApp) {

/**
* Creates a new consent that this app will request from users. The new consent
* will be added to `this.consents`.
* Creates a new permission that this app will request from users. The new permission
* will be added to `this.permissions`.
*/
public async createConsent(params: ConsentCreateParams): Promise<Consent> {
return ConsentImpl.create(this.client, this.id, params);
public async createPermission(params: PermissionCreateParams): Promise<Permission> {
return PermissionImpl.create(this.client, this.id, params);
}
/**
* Returns the consents associated with this app.
* Returns the permissions associated with this app.
*/
public async listConsents(): Promise<Page<Consent>> {
return ConsentImpl.list(this.client, this.id);
public async listPermissions(filter?: PageParams): Promise<Page<Permission>> {
return PermissionImpl.list(this.client, this.id, filter);
}
/**
* Deletes a consent from this app, revoking any access made by granting consent.
* will be removed from `this.consents`.
* Deletes a permission from this app, revoking any access made by granting permission.
* will be removed from `this.permissions`.
*/
public async deleteConsent(consentId: ConsentId): Promise<void> {
return ConsentImpl.delete_(this.client, this.id, consentId);
public async deletePermission(permissionId: PermissionId): Promise<void> {
return PermissionImpl.delete_(this.client, this.id, permissionId);
}

@@ -151,7 +154,9 @@ }

export async function create(client: HttpClient, params: AppCreateParams): Promise<App> {
return client.create<PODApp>(APPS_EP, params).then((podApp) => new App(client, podApp));
const podApp = await client.create<PODApp>(APPS_EP, params);
return new App(client, podApp);
}
export async function get(client: HttpClient, id: AppId): Promise<App> {
return client.get<PODApp>(endpointForId(id)).then((podApp) => new App(client, podApp));
const podApp = await client.get<PODApp>(endpointForId(id));
return new App(client, podApp);
}

@@ -164,7 +169,3 @@

const podPage = await client.get<Page<PODApp>>(APPS_EP, filter);
const results = podPage.results.map((podApp) => new App(client, podApp));
return {
results,
nextPageToken: podPage.nextPageToken,
};
return makePage(App, podPage, client);
}

@@ -177,5 +178,4 @@

): Promise<App> {
return client
.update<PODApp>(endpointForId(id), params)
.then((podApp) => new App(client, podApp));
const podApp = await client.update<PODApp>(endpointForId(id), params);
return new App(client, podApp);
}

@@ -182,0 +182,0 @@

@@ -10,28 +10,30 @@ import type { Except, Opaque } from 'type-fest';

export type ClientId = Opaque<ResourceId>;
export type ClientId = Opaque<ResourceId, 'ClientId'>;
export type PODClient = PODModel & {
creator: ResourceId;
appId: ResourceId;
name: string;
redirectUris: string[];
postLogoutRedirectUris: string[];
publicKeys: PublicJWK[];
canHoldSecrets: boolean;
canActOnBehalfOfUsers: boolean;
isScript: boolean;
};
export type PODClient = Readonly<
PODModel & {
creator: ResourceId;
appId: ResourceId;
name: string;
redirectUris: string[];
postLogoutRedirectUris: string[];
publicKeys: PublicJWK[];
canHoldSecrets: boolean;
canActOnBehalfOfUsers: boolean;
isScript: boolean;
}
>;
export class Client implements Model {
public id: ClientId;
public createdAt: Date;
public creator: IdentityId;
public appId: AppId;
public name: string;
public redirectUris: string[];
public postLogoutRedirectUris: string[];
public publicKeys: PublicJWK[];
public canHoldSecrets: boolean;
public canActOnBehalfOfUsers: boolean;
public isScript: boolean;
public readonly id: ClientId;
public readonly createdAt: Date;
public readonly creator: IdentityId;
public readonly appId: AppId;
public readonly name: string;
public readonly redirectUris: string[];
public readonly postLogoutRedirectUris: string[];
public readonly publicKeys: PublicJWK[];
public readonly canHoldSecrets: boolean;
public readonly canActOnBehalfOfUsers: boolean;
public readonly isScript: boolean;

@@ -68,11 +70,9 @@ public constructor(private readonly client: HttpClient, pod: PODClient) {

): Promise<Client> {
return client
.create<PODClient>(endpointForCollection(appId), params)
.then((podClient) => new Client(client, podClient));
const podClient = await client.create<PODClient>(endpointForCollection(appId), params);
return new Client(client, podClient);
}
export async function get(client: HttpClient, appId: AppId, clientId: ClientId): Promise<Client> {
return client
.get<PODClient>(endpointForId(appId, clientId))
.then((podClient) => new Client(client, podClient));
const podClient = await client.get<PODClient>(endpointForId(appId, clientId));
return new Client(client, podClient);
}

@@ -99,5 +99,4 @@

): Promise<Client> {
return client
.update<PODClient>(endpointForId(appId, clientId), params)
.then((podClient) => new Client(client, podClient));
const podClient = await client.update<PODClient>(endpointForId(appId, clientId), params);
return new Client(client, podClient);
}

@@ -104,0 +103,0 @@

@@ -6,5 +6,6 @@ import type { Opaque } from 'type-fest';

import type { IdentityId } from './identity.js';
import type { Page, PageParams } from './model.js';
import type { Page, PageParams, PODModel } from './model.js';
import { makePage, ResourceId } from './model.js';
export type JobId = Opaque<string, 'JobId'>;
export type JobId = Opaque<ResourceId, 'JobId'>;

@@ -111,13 +112,15 @@ /**

export type PODJob = {
readonly id: JobId;
readonly spec: JobSpec;
export type PODJob = Readonly<
PODModel & {
id: JobId;
spec: JobSpec;
/**
* Most recently observed status of the pod. This data may not be up to
* date. The data type is a mostly subset of [Kubernetes'
* PodStatus](https://www.k8sref.io/docs/workloads/pod-v1/#podstatus).
*/
readonly status: JobStatus;
};
/**
* Most recently observed status of the pod. This data may not be up to
* date. The data type is a mostly subset of [Kubernetes'
* PodStatus](https://www.k8sref.io/docs/workloads/pod-v1/#podstatus).
*/
status: JobStatus;
}
>;

@@ -129,7 +132,9 @@ /**

public readonly id: JobId;
public readonly createdAt: Date;
public readonly spec: JobSpec;
public readonly status: JobStatus;
public constructor(pod: PODJob) {
public constructor(private readonly client: HttpClient, pod: PODJob) {
this.id = pod.id;
this.createdAt = new Date(pod.createdAt);
this.spec = pod.spec;

@@ -146,14 +151,14 @@ this.status = pod.status;

export async function submitJob(client: HttpClient, spec: JobSpec): Promise<Job> {
return client.post<PODJob>(JOBS_EP, spec).then((pod) => new Job(pod));
const pod = await client.post<PODJob>(JOBS_EP, spec);
return new Job(client, pod);
}
export async function listJobs(client: HttpClient, filter: PageParams = {}): Promise<Page<Job>> {
return client.get<Page<PODJob>>(JOBS_EP, filter).then((podPage) => ({
results: podPage.results.map((podJob) => new Job(podJob)),
nextPageToken: podPage.nextPageToken,
}));
const podPage = await client.get<Page<PODJob>>(JOBS_EP, filter);
return makePage(Job, podPage, client);
}
export async function getJob(client: HttpClient, jobId: JobId): Promise<Job> {
return client.get<PODJob>(endpointForId(jobId)).then((pod) => new Job(pod));
const pod = await client.get<PODJob>(endpointForId(jobId));
return new Job(client, pod);
}

@@ -160,0 +165,0 @@

@@ -9,18 +9,21 @@ import EventEmitter from 'eventemitter3';

import type { Model, Page, PageParams, PODModel, ResourceId, WritableExcluding } from './model.js';
import { makePage } from './model.js';
export type DatasetId = Opaque<ResourceId>;
export type DatasetId = Opaque<ResourceId, 'DatasetId'>;
export type PODDataset = PODModel & {
id: ResourceId;
creator: ResourceId;
owner: ResourceId;
size: number;
details: DatasetDetails;
};
export type PODDataset = Readonly<
PODModel & {
id: ResourceId;
creator: ResourceId;
owner: ResourceId;
size: number;
details: DatasetDetails;
}
>;
export type PODAccessEvent = {
export type PODAccessEvent = Readonly<{
createdAt: string;
dataset: ResourceId;
accessor: ResourceId;
};
}>;

@@ -30,10 +33,10 @@ type DatasetDetails = { title?: string; tags?: string[] };

export class Dataset implements Model {
public id: DatasetId;
public createdAt: Date;
public creator: IdentityId;
public size: number;
public owner: IdentityId;
public readonly id: DatasetId;
public readonly createdAt: Date;
public readonly creator: IdentityId;
public readonly size: number;
public readonly owner: IdentityId;
/** Additional, optional information about the dataset. */
public details: DatasetDetails;
public readonly details: DatasetDetails;

@@ -74,5 +77,4 @@ public constructor(private readonly client: HttpClient, pod: PODDataset) {

export async function get(client: HttpClient, id: DatasetId): Promise<Dataset> {
return client
.get<PODDataset>(endpointForId(id))
.then((podDataset) => new Dataset(client, podDataset));
const podDataset = await client.get<PODDataset>(endpointForId(id));
return new Dataset(client, podDataset);
}

@@ -96,7 +98,3 @@

});
const results = podPage.results.map((podDataset) => new Dataset(client, podDataset));
return {
results,
nextPageToken: podPage.nextPageToken,
};
return makePage(Dataset, podPage, client);
}

@@ -143,5 +141,4 @@

): Promise<Dataset> {
return client
.update<PODDataset>(endpointForId(id), params)
.then((podDataset) => new Dataset(client, podDataset));
const podDataset = await client.update<PODDataset>(endpointForId(id), params);
return new Dataset(client, podDataset);
}

@@ -235,2 +232,3 @@

})
// eslint-disable-next-line promise/prefer-await-to-then
.then((podDataset) => {

@@ -237,0 +235,0 @@ this.emit('finish', new Dataset(client, podDataset));

import type { Opaque } from 'type-fest';
import type { ConsentId } from './consent.js';
import type { Constraints } from './filter.js';
import type { Conditions } from './conditions.js';
import type { HttpClient } from './http.js';
import type { IdentityId } from './identity.js';
import type { Model, Page, PageParams, PODModel, ResourceId } from './model.js';
import { makePage } from './model.js';
import type { PermissionId } from './permission.js';
export type GrantId = Opaque<ResourceId>;
export type GrantId = Opaque<ResourceId, 'GrantId'>;
export type PODGrant = PODModel & {
granter: ResourceId;
grantee?: ResourceId;
consent?: ResourceId;
filter?: Constraints;
};
export type PODGrant = Readonly<
PODModel & {
granter: ResourceId;
grantee?: ResourceId;
permission?: ResourceId;
conditions?: Conditions;
}
>;

@@ -24,4 +27,4 @@ export type GrantCreateParams = {

/** A filter that gives permission to only matching Datasets. */
filter?: Constraints;
/** Conditoins that must be matched to recieve access to one or more Datasets. */
conditions?: Conditions;
};

@@ -33,14 +36,14 @@

export class Grant implements Model {
public id: GrantId;
public createdAt: Date;
public readonly id: GrantId;
public readonly createdAt: Date;
/** The Identity from which permission is given. */
public granter: IdentityId;
public readonly granter: IdentityId;
/**
* The Identity to which permission is given or everyone,
*/
public grantee: IdentityId | 'everyone';
/** A filter that gives permission to only matching Datasets. */
public filter?: Constraints;
/** The Consent that created this Grant, if any. */
public consent?: ConsentId;
public readonly grantee: IdentityId | 'everyone';
/** Conditions that describe Datasets to be shared. */
public readonly conditions?: Conditions;
/** The Permission that created this Grant, if any. */
public readonly permission?: PermissionId;

@@ -52,4 +55,4 @@ public constructor(private readonly client: HttpClient, pod: PODGrant) {

this.grantee = (pod.grantee as IdentityId) ?? 'everyone';
this.filter = pod.filter;
this.consent = pod.consent as ConsentId;
this.conditions = pod.conditions;
this.permission = pod.permission as PermissionId;
}

@@ -64,9 +67,9 @@

export async function create(client: HttpClient, params: GrantCreateParams): Promise<Grant> {
return client
.create<PODGrant>(GRANTS_EP, params)
.then((podGrant) => new Grant(client, podGrant));
const podGrant = await client.create<PODGrant>(GRANTS_EP, params);
return new Grant(client, podGrant);
}
export async function get(client: HttpClient, id: GrantId): Promise<Grant> {
return client.get<PODGrant>(endpointForId(id)).then((podGrant) => new Grant(client, podGrant));
const podGrant = await client.get<PODGrant>(endpointForId(id));
return new Grant(client, podGrant);
}

@@ -79,7 +82,3 @@

const podPage = await client.get<Page<PODGrant>>(GRANTS_EP, filter);
const results = podPage.results.map((podGrant) => new Grant(client, podGrant));
return {
results,
nextPageToken: podPage.nextPageToken,
};
return makePage(Grant, podPage, client);
}

@@ -86,0 +85,0 @@

@@ -5,8 +5,3 @@ import type { WriteStream } from 'fs';

import FormData from 'form-data';
import type {
BeforeRequestHook,
NormalizedOptions,
Options as KyOptions,
ResponsePromise,
} from 'ky';
import type { BeforeRequestHook, NormalizedOptions, Options as KyOptions } from 'ky';
import ky from 'ky';

@@ -178,3 +173,3 @@ import { paramCase } from 'param-case';

export class Download implements AsyncIterable<Uint8Array> {
private res?: ResponsePromise;
private res?: Promise<Response>;
private readonly abortController: AbortController;

@@ -219,3 +214,3 @@

if ('getWriter' in sink) {
const body = (await this.makeRequest()).body;
const { body } = await this.makeRequest();
if (!body) return;

@@ -231,4 +226,4 @@ if (body.pipeTo) {

const stream = await import('stream');
const Readable = stream.Readable ?? stream.default.Readable; // Imported differently depending on i-dont-know-what :/
// eslint-disable-next-line node/no-unsupported-features/es-syntax
const { Readable } = await import('stream'); // This only happens in the browser.
return new Promise((resolve, reject) => {

@@ -248,3 +243,3 @@ Readable.from(this, { objectMode: false })

// This funciton returns double promise to make both xo and TS happy. V8 doesn't care.
private async makeRequest(): Promise<ResponsePromise> {
private async makeRequest(): Promise<Response> {
if (!this.res) {

@@ -275,3 +270,3 @@ this.res = this.client.get(this.endpoint, {

const context: string = (request as any).context;
const { context }: { context: string } = request as any;
if (context) {

@@ -278,0 +273,0 @@ message = `error in ${context}: ${message}`;

import type { Opaque, SetOptional } from 'type-fest';
import type { AppId } from './app.js';
import { Consent } from './consent.js';
import type { ConsentId, PODConsent } from './consent.js';
import type { HttpClient } from './http.js';
import { setExpectedStatus } from './http.js';
import type { Model, Page, PageParams, PODModel, ResourceId, Writable } from './model.js';
import { Permission } from './permission.js';
import type { PermissionId, PODPermission } from './permission.js';
import type { IdentityTokenClaims, PublicJWK } from './token.js';
export type IdentityId = Opaque<ResourceId>; // TODO: uniqueify with second arg
export type IdentityId = Opaque<ResourceId, 'IdentityId' | 'AppId'>;
export type PODIdentity = PODModel & IdentityCreateParams;
export type PODIdentity = Readonly<PODModel & IdentityCreateParams>;

@@ -18,10 +18,10 @@ const IDENTITIES_EP = 'identities';

const endpointForId = (id: IdentityId) => `${IDENTITIES_EP}/${id}`;
const endpointForConsents = (id: IdentityId) => `${endpointForId(id)}/consents`;
const endpointForConsent = (identityId: IdentityId, consentId: ConsentId) =>
`${endpointForConsents(identityId)}/${consentId}`;
const endpointForPermissions = (id: IdentityId) => `${endpointForId(id)}/permissions`;
const endpointForPermission = (identityId: IdentityId, permissionId: PermissionId) =>
`${endpointForPermissions(identityId)}/${permissionId}`;
export class Identity implements Model {
public id: IdentityId;
public createdAt: Date;
public tokenVerifiers: IdentityTokenVerifier[];
public readonly id: IdentityId;
public readonly createdAt: Date;
public readonly tokenVerifiers: IdentityTokenVerifier[];

@@ -43,20 +43,20 @@ public constructor(private readonly client: HttpClient, pod: PODIdentity) {

public async grantConsent(id: ConsentId): Promise<void> {
return IdentityImpl.grantConsent(this.client, this.id, id);
public async grantPermission(id: PermissionId): Promise<void> {
return IdentityImpl.grantPermission(this.client, this.id, id);
}
/** Fetches consents to which this identity has consented. */
public async listGrantedConsents(
filter?: ListGrantedConsentsFilter & PageParams,
): Promise<Page<Consent>> {
return IdentityImpl.listGrantedConsents(this.client, this.id, filter);
/** Fetches permissions to which this identity has agreed. */
public async listGrantedPermissions(
filter?: ListGrantedPermissionsFilter & PageParams,
): Promise<Page<Permission>> {
return IdentityImpl.listGrantedPermissions(this.client, this.id, filter);
}
/** * Gets a granted consent by id. Useful for checking if a consent has been granted. */
public async getGrantedConsent(id: ConsentId): Promise<Consent> {
return IdentityImpl.getGrantedConsent(this.client, this.id, id);
/** * Gets a granted permission by id. Useful for checking if a permission has been granted. */
public async getGrantedPermission(id: PermissionId): Promise<Permission> {
return IdentityImpl.getGrantedPermission(this.client, this.id, id);
}
public async revokeConsent(id: ConsentId): Promise<void> {
return IdentityImpl.revokeConsent(this.client, this.id, id);
public async revokePermission(id: PermissionId): Promise<void> {
return IdentityImpl.revokePermission(this.client, this.id, id);
}

@@ -70,17 +70,14 @@ }

): Promise<Identity> {
return client
.create<PODIdentity>(IDENTITIES_EP, params)
.then((podIdentity) => new Identity(client, podIdentity));
const podIdentity = await client.create<PODIdentity>(IDENTITIES_EP, params);
return new Identity(client, podIdentity);
}
export async function current(client: HttpClient): Promise<Identity> {
return client
.get<PODIdentity>(IDENTITIES_ME)
.then((podIdentity) => new Identity(client, podIdentity));
const podIdentity = await client.get<PODIdentity>(IDENTITIES_ME);
return new Identity(client, podIdentity);
}
export async function get(client: HttpClient, id: IdentityId): Promise<Identity> {
return client
.get<PODIdentity>(endpointForId(id))
.then((podIdentity) => new Identity(client, podIdentity));
const podIdentity = await client.get<PODIdentity>(endpointForId(id));
return new Identity(client, podIdentity);
}

@@ -93,5 +90,4 @@

): Promise<Identity> {
return client
.update<PODIdentity>(endpointForId(id), params)
.then((podIdentity) => new Identity(client, podIdentity));
const podIdentity = await client.update<PODIdentity>(endpointForId(id), params);
return new Identity(client, podIdentity);
}

@@ -103,8 +99,8 @@

export async function grantConsent(
export async function grantPermission(
client: HttpClient,
identityId: IdentityId,
consentId: ConsentId,
permissionId: PermissionId,
): Promise<void> {
await client.post(endpointForConsent(identityId, consentId), undefined, {
await client.post(endpointForPermission(identityId, permissionId), undefined, {
hooks: {

@@ -116,9 +112,12 @@ beforeRequest: [setExpectedStatus(204)],

export async function listGrantedConsents(
export async function listGrantedPermissions(
client: HttpClient,
identityId: IdentityId,
filter?: ListGrantedConsentsFilter & PageParams,
): Promise<Page<Consent>> {
const podPage = await client.get<Page<PODConsent>>(endpointForConsents(identityId), filter);
const results = podPage.results.map((podConsent) => new Consent(client, podConsent));
filter?: ListGrantedPermissionsFilter & PageParams,
): Promise<Page<Permission>> {
const podPage = await client.get<Page<PODPermission>>(
endpointForPermissions(identityId),
filter,
);
const results = podPage.results.map((podPermission) => new Permission(client, podPermission));
return {

@@ -130,18 +129,19 @@ results,

export async function getGrantedConsent(
export async function getGrantedPermission(
client: HttpClient,
identityId: IdentityId,
consentId: ConsentId,
): Promise<Consent> {
return client
.get<PODConsent>(endpointForConsent(identityId, consentId))
.then((podConsent) => new Consent(client, podConsent));
permissionId: PermissionId,
): Promise<Permission> {
const podPermission = await client.get<PODPermission>(
endpointForPermission(identityId, permissionId),
);
return new Permission(client, podPermission);
}
export async function revokeConsent(
export async function revokePermission(
client: HttpClient,
identityId: IdentityId,
consentId: ConsentId,
permissionId: PermissionId,
): Promise<void> {
await client.delete(endpointForConsent(identityId, consentId));
await client.delete(endpointForPermission(identityId, permissionId));
}

@@ -161,5 +161,5 @@ }

export type ListGrantedConsentsFilter = Partial<{
/** Only return consents granted to this app. */
export type ListGrantedPermissionsFilter = Partial<{
/** Only return permissions granted to this app. */
app: AppId;
}>;

@@ -11,4 +11,2 @@ import type { App, AppCreateParams, AppId, AppUpdateParams, ListAppsFilter } from './app.js';

import { ClientImpl } from './client.js';
import type { Consent, ConsentCreateParams, ConsentId } from './consent.js';
import { ConsentImpl } from './consent.js';
import type {

@@ -46,2 +44,4 @@ AccessEvent,

import type { Page, PageParams } from './model.js';
import type { Permission, PermissionCreateParams, PermissionId } from './permission.js';
import { PermissionImpl } from './permission.js';
import type { ClientCredentials, PrivateJWK, PublicJWK, TokenSource } from './token.js';

@@ -60,5 +60,5 @@ import { TokenProvider } from './token.js';

ClientId,
Consent,
ConsentCreateParams,
ConsentId,
Permission,
PermissionCreateParams,
PermissionId,
Dataset,

@@ -171,12 +171,12 @@ DatasetId,

public async createConsent(appId: AppId, params: ConsentCreateParams): Promise<Consent> {
return ConsentImpl.create(this.client, appId, params);
public async createPermission(appId: AppId, params: PermissionCreateParams): Promise<Permission> {
return PermissionImpl.create(this.client, appId, params);
}
public async listConsents(appId: AppId, filter: PageParams): Promise<Page<Consent>> {
return ConsentImpl.list(this.client, appId, filter);
public async listPermissions(appId: AppId, filter: PageParams): Promise<Page<Permission>> {
return PermissionImpl.list(this.client, appId, filter);
}
public async deleteConsent(appId: AppId, consentId: ConsentId): Promise<void> {
return ConsentImpl.delete_(this.client, appId, consentId);
public async deletePermission(appId: AppId, permissionId: PermissionId): Promise<void> {
return PermissionImpl.delete_(this.client, appId, permissionId);
}

@@ -183,0 +183,0 @@

import type { ConditionalExcept, Except, JsonValue } from 'type-fest';
export type ResourceId = string; // Format from runtime: `<resource>-<id>`
import type { HttpClient } from './http.js';
export type ResourceId = string;
export interface PODModel {

@@ -15,6 +17,6 @@ /** An undifferentiated model identifier. */

/** The model's unique ID. */
id: ResourceId;
readonly id: ResourceId;
/** The number of seconds since the Unix epoch when this model was created */
createdAt: Date;
readonly createdAt: Date;
}

@@ -35,3 +37,15 @@

pageSize: number;
nextPageToken: string;
pageToken: string;
}>;
export function makePage<Pod extends PODModel, M extends Model>(
// eslint-disable-next-line @typescript-eslint/prefer-function-type
ModelTy: { new (client: HttpClient, pod: Pod): M },
podPage: Page<Pod>,
client: HttpClient,
): Page<M> {
return {
results: podPage.results.map((podModel) => new ModelTy(client, podModel)),
nextPageToken: podPage.nextPageToken,
};
}

@@ -6,4 +6,6 @@ import { KEYUTIL, KJUR } from 'jsrsasign';

import type { IdentityId } from './identity.js';
import './polyfill.js'; // eslint-disable-line import/no-unassigned-import
const DEFAULT_TOKEN_ENDPOINT = 'https://auth.oasislabs.com/oauth/token';
export const PARCEL_RUNTIME_AUD = 'https://api.oasislabs.com/parcel'; // TODO(#326)

@@ -64,6 +66,4 @@

* The identity provider's OAuth token retrieval endpoint.
* If left undefined, the access token will be self-signed with the `clientId`
* as the issuer.
*/
tokenEndpoint: string;
tokenEndpoint?: string;

@@ -73,3 +73,3 @@ /**

*/
audience: string;
audience?: string;

@@ -80,3 +80,3 @@ /**

*/
scopes: string[];
scopes?: string[];
};

@@ -90,3 +90,3 @@

private readonly scopes: string[];
private readonly privateKey: string; // PKCS8-encoded
private readonly privateKeyPEM: string; // PEM is required by jsrsasign.
private readonly keyId: string;

@@ -98,3 +98,3 @@

clientId,
privateKey: privateJWK,
privateKey,
scopes,

@@ -106,10 +106,14 @@ tokenEndpoint,

const { privateKey, keyId } = jwkToPem(privateJWK);
this.privateKey = privateKey;
if (privateKey.kty !== 'EC') {
throw new Error('Private key should be an ECDSA key.');
}
const { privateKey: privateKeyPEM, keyId } = jwkToPem(privateKey);
this.privateKeyPEM = privateKeyPEM;
this.keyId = keyId;
this.clientId = clientId;
this.tokenEndpoint = tokenEndpoint;
this.audience = audience;
this.scopes = scopes;
this.tokenEndpoint = tokenEndpoint ?? DEFAULT_TOKEN_ENDPOINT;
this.audience = audience ?? PARCEL_RUNTIME_AUD;
this.scopes = scopes ?? ['parcel.temp_api', 'parcel.temp_storage'];
}

@@ -119,3 +123,3 @@

const clientAssertion = makeJWT({
privateKey: this.privateKey,
privateKey: this.privateKeyPEM,
keyId: this.keyId,

@@ -172,2 +176,3 @@ payload: {

res
// eslint-disable-next-line promise/prefer-await-to-then
.then(async (refreshResponse) => {

@@ -185,3 +190,3 @@ this.refreshToken = (await refreshResponse.clone().json()).refresh_token;

/** The `sub` and `iss` claims of the provided access token. */
principal: string;
principal: string | IdentityId;

@@ -207,3 +212,3 @@ /** The private key that will be used to sign the access token. */

private readonly principal: string;
private readonly privateKey: string;
private readonly privateKeyPEM: string; // PEM is required by jsrsasign.
private readonly keyId: string;

@@ -215,3 +220,3 @@ private readonly scopes: string[];

principal,
privateKey: privateJWK,
privateKey,
scopes,

@@ -222,4 +227,4 @@ tokenLifetime,

const { privateKey, keyId } = jwkToPem(privateJWK);
this.privateKey = privateKey;
const { privateKey: privateKeyPEM, keyId } = jwkToPem(privateKey);
this.privateKeyPEM = privateKeyPEM;
this.keyId = keyId;

@@ -235,3 +240,3 @@

const token = makeJWT({
privateKey: this.privateKey,
privateKey: this.privateKeyPEM,
keyId: this.keyId,

@@ -238,0 +243,0 @@ payload: {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc