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

@oasislabs/parcel

Package Overview
Dependencies
Maintainers
18
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.8 to 0.1.9

src/condition.ts

26

package.json
{
"name": "@oasislabs/parcel",
"version": "0.1.8",
"version": "0.1.9",
"license": "Apache-2.0",

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

"test:cy": "start-test 'parcel serve test/cypress/fixtures/index.html -p 4444' 4444 'cypress run'",
"coverage": "jest --coverage && yarn test:cy",
"coverage": "jest --coverage test/unit && yarn test:cy",
"doc": "typedoc --options docs/typedoc.json",

@@ -40,3 +40,3 @@ "prepublishOnly": "yarn build"

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

@@ -61,2 +61,3 @@ },

"@cypress/code-coverage": "^3.8.1",
"@types/bs58": "^4.0.1",
"@types/jest": "^26.0.9",

@@ -66,5 +67,7 @@ "@types/jsonwebtoken": "^8.5.0",

"@types/node": "^14.0.20",
"@types/uuid": "^8.3.0",
"ajv": "^6.12.5",
"cypress": "^5.3.0",
"ajv": "^7.0.0",
"ajv-formats": "^1.5.1",
"bs58": "^4.0.1",
"cypress": "^6.0.0",
"eslint-config-xo-typescript": "^0.38.0",
"eslint-plugin-cypress": "^2.11.2",

@@ -82,4 +85,3 @@ "jest": "^26.2.2",

"typescript": "^4.1.3",
"uuid": "^8.3.0",
"xo": "^0.36.1"
"xo": "^0.38.0"
},

@@ -90,8 +92,8 @@ "dependencies": {

"eventemitter3": "^4.0.4",
"form-data": "^3.0.0",
"form-data": "^4.0.0",
"jsrsasign": "^10.0.0",
"ky": "^0.26.0",
"ky": "^0.27.0",
"node-fetch": "3.0.0-beta.9",
"param-case": "^3.0.3",
"type-fest": "^0.20.0",
"type-fest": "^0.21.0",
"web-streams-polyfill": "^3.0.1"

@@ -101,4 +103,4 @@ },

"engines": {
"node": ">=14"
"node": ">=14.8"
}
}

@@ -13,1 +13,9 @@ # @oasislabs/parcel

```
## Compute examples
The compute examples require node version ^14.8. Run the compute examples with
```sh
npm i
npm run start
```

@@ -57,3 +57,3 @@ import type { Except, Opaque } from 'type-fest';

public readonly participants: IdentityId[];
/** Allow non-admin users to upload datasets. */
/** Allow non-admin users to upload documents. */
public readonly allowUserUploads: boolean;

@@ -60,0 +60,0 @@

import type { Opaque } from 'type-fest';
import type { DatasetId } from './dataset.js';
import type { DocumentId } from './document.js';
import type { HttpClient } from './http.js';

@@ -12,14 +12,18 @@ import type { IdentityId } from './identity.js';

/**
* Input dataset for a compute job.
* Input document for a compute job.
*/
export declare type InputDatasetSpec = {
export declare type InputDocumentSpec = {
/** ID of the document to mount. */
id: DocumentId;
/** Path where the input document will be mounted inside the job. Interpreted relative to `/parcel/data/in`. */
mountPath: string;
id: DatasetId;
};
/**
* Specification for a compute job for outputting a dataset.
* Specification for a compute job for outputting a document.
*/
export declare type OutputDatasetSpec = {
export declare type OutputDocumentSpec = {
/** Path to the file that should be uploaded as an output document. Interpreted relative to `/parcel/data/out`. */
mountPath: string;
/** Owner to assign to the output document. */
owner?: IdentityId;

@@ -29,7 +33,7 @@ };

/**
* An output dataset produced in the context of running a job.
* An output document produced in the context of running a job.
*/
export declare type OutputDataset = {
export declare type OutputDocument = {
mountPath: string;
id: DatasetId;
id: DocumentId;
};

@@ -71,10 +75,14 @@

env?: Record<string, string>;
inputDatasets?: Array<{
mountPath: string;
id: DatasetId;
}>;
outputDatasets?: Array<{
mountPath: string;
owner: IdentityId;
}>;
/**
* Documents to download and mount into the job's container before `cmd` runs.
* If any of these documents do not exist or you do not have permission to access them, the job will fail.
*/
inputDocuments?: InputDocumentSpec[];
/**
* Files to be uploaded from the job's container as documents after `cmd` runs.
* Files that do not exist will be silently skipped; the job will not fail.
*/
outputDocuments?: OutputDocumentSpec[];
};

@@ -92,8 +100,8 @@

/**
* Datasets that were generated by the job and uploaded by the Parcel
* Documents that were generated by the job and uploaded by the Parcel
* Worker. For a pending or running job, this list will be empty. For a
* successfully completed job, each `outputDataset` entry from the job spec will
* successfully completed job, each `outputDocument` entry from the job spec will
* have a corresponding entry in this list.
*/
outputDatasets: OutputDataset[];
outputDocuments: OutputDocument[];

@@ -100,0 +108,0 @@ /**

import type { Opaque } from 'type-fest';
import type { Conditions } from './conditions.js';
import type { Condition } from './condition.js';
import type { HttpClient } from './http.js';

@@ -17,3 +17,5 @@ import type { IdentityId } from './identity.js';

permission?: ResourceId;
conditions?: Conditions;
condition?: Condition;
capabilities?: string;
delegating?: ResourceId;
}

@@ -28,4 +30,14 @@ >;

/** Conditoins that must be matched to recieve access to one or more Datasets. */
conditions?: Conditions;
/** The condition that must be matched to receive access to one or more Datasets. */
condition?: Condition;
/** The capabilities attached to this grant. The default is `read`. */
capabilities?: Capabilities | string;
/**
* The grant to extend by delegation. If you are the delegating grant's `grantee` is you,
* and it has the `extend` capability, then this grant will have the same `granter` as
* the delegating grant.
*/
delegating?: GrantId;
};

@@ -45,6 +57,10 @@

public readonly grantee: IdentityId | 'everyone';
/** Conditions that describe Datasets to be shared. */
public readonly conditions?: Conditions;
/** The Permission that created this Grant, if any. */
/** The condition that describes Documents to be shared. */
public readonly condition?: Condition;
/** The permission that created this Grant, if any. */
public readonly permission?: PermissionId;
/** The actions permissible to the grantee on targets selected by the conditions. */
public readonly capabilities?: Capabilities;
/** The grant that this grant extends by delegation. */
public readonly delegating?: GrantId;

@@ -56,4 +72,6 @@ public constructor(private readonly client: HttpClient, pod: PODGrant) {

this.grantee = (pod.grantee as IdentityId) ?? 'everyone';
this.conditions = pod.conditions;
this.condition = pod.condition;
this.permission = pod.permission as PermissionId;
this.capabilities = pod.capabilities ? parseCaps(pod.capabilities) : undefined;
this.delegating = pod.delegating as GrantId;
}

@@ -97,1 +115,55 @@

}>;
/**
* `Capabilities` is a collection of bit flags.
* To test if a cability is set, you can do something like
* ```
* const requiredCaps = (Capabilities.Read | Capabilities.Extend);
* caps & requiredCaps === requiredCaps;
* ```
*/
/* eslint-disable @typescript-eslint/prefer-literal-enum-member */
export enum Capabilities {
None = 0,
/** The ability to read/view the target. */
Read = 1 << 0, // eslint-disable-line unicorn/prefer-math-trunc
// /** The ability to write the target. */
// Write = 1 << 1,
/** The ability to delegate this grant's capabilities to someone else. */
Extend = 1 << 2,
}
/* eslint-enable @typescript-eslint/prefer-literal-enum-member */
export function parseCaps(strCaps?: string): Capabilities {
if (strCaps === undefined) return Capabilities.None;
let caps = Capabilities.None;
for (const strCap of strCaps.trim().split(/\s+/)) {
switch (strCap) {
case 'read':
caps |= Capabilities.Read;
break;
case 'extend':
caps |= Capabilities.Extend;
break;
case '':
break;
default:
throw new Error(`unknown capability "${strCap}"`);
}
}
return caps;
}
export function stringifyCaps(caps?: Capabilities): string {
if (caps === undefined) return '';
const capsStrs = [];
for (const [name, bit] of Object.entries(Capabilities)) {
if (typeof bit !== 'number') continue;
if ((caps & bit) !== 0) {
capsStrs.push(name.toLowerCase());
}
}
return capsStrs.join(' ');
}

@@ -14,3 +14,4 @@ import type { WriteStream } from 'fs';

const DEFAULT_API_URL = 'https://api.oasislabs.com/parcel/v1';
const DEFAULT_API_URL =
globalThis?.process?.env?.PARCEL_API_URL ?? 'https://api.oasislabs.com/parcel/v1';

@@ -165,3 +166,3 @@ export type Config = Partial<{

/**
* A `Download` is the result of calling `parcel.downloadDataset` or `dataset.download()`.
* A `Download` is the result of calling `parcel.downloadDocument` or `document.download()`.
*

@@ -246,3 +247,3 @@ * The downloaded data can be read using the Node `stream.Readable` interface, or by

hooks: {
beforeRequest: [attachContext('dataset download')],
beforeRequest: [attachContext('document download')],
},

@@ -249,0 +250,0 @@ });

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

AccessEvent,
Dataset,
DatasetId,
DatasetUpdateParams,
DatasetUploadParams,
Document,
DocumentId,
DocumentUpdateParams,
DocumentUploadParams,
ListAccessLogFilter,
ListDatasetsFilter,
ListDocumentsFilter,
Storable,
Upload,
} from './dataset.js';
import { DatasetImpl } from './dataset.js';
} from './document.js';
import { DocumentImpl } from './document.js';
import type { Job, JobId, JobSpec, JobStatus } from './compute.js';
import {
ComputeImpl,
InputDatasetSpec,
InputDocumentSpec,
JobPhase,
OutputDataset,
OutputDatasetSpec,
OutputDocument,
OutputDocumentSpec,
} from './compute.js';
import type { Grant, GrantCreateParams, GrantId } from './grant.js';
import type { Capabilities, Grant, GrantCreateParams, GrantId } from './grant.js';
import { GrantImpl, ListGrantsFilter } from './grant.js';

@@ -47,3 +47,3 @@ import type { Config as ClientConfig, Download } from './http.js';

import type { ClientCredentials, PrivateJWK, PublicJWK, TokenSource } from './token.js';
import { TokenProvider } from './token.js';
import { TokenProvider, PARCEL_RUNTIME_AUD } from './token.js';

@@ -56,2 +56,3 @@ export {

AppUpdateParams,
Capabilities,
Client,

@@ -64,6 +65,6 @@ ClientCreateParams,

PermissionId,
Dataset,
DatasetId,
DatasetUpdateParams,
DatasetUploadParams,
Document,
DocumentId,
DocumentUpdateParams,
DocumentUploadParams,
ApiError,

@@ -77,3 +78,3 @@ Grant,

IdentityUpdateParams,
InputDatasetSpec,
InputDocumentSpec,
Job,

@@ -84,4 +85,5 @@ JobId,

JobStatus,
OutputDataset,
OutputDatasetSpec,
OutputDocument,
OutputDocumentSpec,
PARCEL_RUNTIME_AUD,
Page,

@@ -123,31 +125,31 @@ PageParams,

public uploadDataset(data: Storable, params?: DatasetUploadParams): Upload {
return DatasetImpl.upload(this.client, data, params);
public uploadDocument(data: Storable, params?: DocumentUploadParams): Upload {
return DocumentImpl.upload(this.client, data, params);
}
public async getDataset(id: DatasetId): Promise<Dataset> {
return DatasetImpl.get(this.client, id);
public async getDocument(id: DocumentId): Promise<Document> {
return DocumentImpl.get(this.client, id);
}
public async listDatasets(filter?: ListDatasetsFilter & PageParams): Promise<Page<Dataset>> {
return DatasetImpl.list(this.client, filter);
public async listDocuments(filter?: ListDocumentsFilter & PageParams): Promise<Page<Document>> {
return DocumentImpl.list(this.client, filter);
}
public downloadDataset(id: DatasetId): Download {
return DatasetImpl.download(this.client, id);
public downloadDocument(id: DocumentId): Download {
return DocumentImpl.download(this.client, id);
}
public async getDatasetHistory(
id: DatasetId,
public async getDocumentHistory(
id: DocumentId,
filter?: ListAccessLogFilter & PageParams,
): Promise<Page<AccessEvent>> {
return DatasetImpl.history(this.client, id, filter);
return DocumentImpl.history(this.client, id, filter);
}
public async updateDataset(id: DatasetId, update: DatasetUpdateParams): Promise<Dataset> {
return DatasetImpl.update(this.client, id, update);
public async updateDocument(id: DocumentId, update: DocumentUpdateParams): Promise<Document> {
return DocumentImpl.update(this.client, id, update);
}
public async deleteDataset(id: DatasetId): Promise<void> {
return DatasetImpl.delete_(this.client, id);
public async deleteDocument(id: DocumentId): Promise<void> {
return DocumentImpl.delete_(this.client, id);
}

@@ -179,3 +181,3 @@

public async listPermissions(appId: AppId, filter: PageParams): Promise<Page<Permission>> {
public async listPermissions(appId: AppId, filter?: PageParams): Promise<Page<Permission>> {
return PermissionImpl.list(this.client, appId, filter);

@@ -182,0 +184,0 @@ }

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

import { endpointForId as endpointForApp } from './app.js';
import type { Conditions } from './conditions.js';
import type { Condition } from './condition.js';
import type { HttpClient } from './http.js';

@@ -114,7 +114,7 @@ import type { IdentityId } from './identity.js';

/** The symbolic grantee */
/** The symbolic grantee. */
grantee?: GranteeRef;
/** The Grant's conditions. @see `Grant.conditions`. */
conditions?: Conditions;
/** The Grant's condition. @see `Grant.condition`. */
condition?: Condition;
};

@@ -121,0 +121,0 @@

@@ -7,8 +7,4 @@ // The following code is inlined from `ky-universal` because it uses ES modules and

import fetch, { Headers, Request as RequestPF, Response as ResponsePF } from 'node-fetch';
import {
ReadableStream as ReadableStreamPF,
WritableStream as WritableStreamPF,
// @ts-expect-error: The package isn't ESM-compatible.
// eslint-disable-next-line import/extensions
} from 'web-streams-polyfill/dist/ponyfill.es2018.js';
// @ts-expect-error: The package isn't ESM-compatible.
import * as webStreams from 'web-streams-polyfill/dist/ponyfill.es2018.js';

@@ -23,7 +19,7 @@ globalThis.fetch =

globalThis.FormData = globalThis.FormData ?? FormData;
globalThis.ReadableStream = globalThis.ReadableStream ?? ReadableStreamPF;
globalThis.WritableStream = globalThis.WritableStream ?? WritableStreamPF;
globalThis.ReadableStream = globalThis.ReadableStream ?? webStreams.ReadableStream;
globalThis.WritableStream = globalThis.WritableStream ?? webStreams.WritableStream;
const ReadableStreamPF_ = ReadableStreamPF as typeof globalThis.ReadableStream;
const ReadableStreamPF = webStreams.ReadableStream as typeof globalThis.ReadableStream;
export { ReadableStreamPF_ as ReadableStreamPF };
export { ReadableStreamPF };

@@ -1,5 +0,5 @@

import { KEYUTIL, KJUR } from 'jsrsasign';
import jsrsasign from 'jsrsasign';
import type { ResponsePromise } from 'ky';
import ky from 'ky';
import type { Except, JsonObject } from 'type-fest';
import type { JsonObject, Merge } from 'type-fest';

@@ -9,3 +9,4 @@ import type { IdentityId } from './identity.js';

const DEFAULT_TOKEN_ENDPOINT = 'https://auth.oasislabs.com/oauth/token';
const DEFAULT_TOKEN_ENDPOINT =
globalThis?.process?.env?.PARCEL_TOKEN_ENDPOINT ?? 'https://auth.oasislabs.com/oauth/token';
export const PARCEL_RUNTIME_AUD = 'https://api.oasislabs.com/parcel'; // TODO(#326)

@@ -87,4 +88,4 @@

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

@@ -106,5 +107,5 @@ private readonly clientAssertionLifetime = 1 * 60 * 60; // 1 hour

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

@@ -114,3 +115,3 @@ this.clientId = clientId;

this.audience = audience ?? PARCEL_RUNTIME_AUD;
this.scopes = scopes ?? ['parcel.temp_api', 'parcel.temp_storage'];
this.scopes = scopes ?? ['parcel.*'];
}

@@ -121,3 +122,3 @@

privateKey: this.privateKeyPEM,
keyId: this.keyId,
keyId: this.privateKey.kid,
payload: {

@@ -127,3 +128,3 @@ sub: this.clientId,

aud: this.tokenEndpoint,
jti: KJUR.crypto.Util.getRandomHexOfNbytes(8),
jti: jsrsasign.KJUR.crypto.Util.getRandomHexOfNbytes(8),
},

@@ -208,4 +209,4 @@ lifetime: this.clientAssertionLifetime,

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

@@ -222,5 +223,5 @@ private readonly tokenLifetime: number;

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

@@ -236,3 +237,3 @@ this.principal = principal;

privateKey: this.privateKeyPEM,
keyId: this.keyId,
keyId: this.privateKey.kid,
payload: {

@@ -242,3 +243,3 @@ sub: this.principal,

aud: PARCEL_RUNTIME_AUD,
scope: this.scopes,
scope: this.scopes.join(' '),
},

@@ -288,3 +289,3 @@ lifetime: this.tokenLifetime,

};
export type PublicES256JWK = Except<PrivateES256JWK, 'd'>;
export type PublicES256JWK = Merge<PrivateES256JWK, { d?: undefined | null }>;

@@ -307,3 +308,3 @@ export type PublicJWK = PublicES256JWK;

/** Returns the PKCS8-encoded private key and the JWK"s key id. */
function jwkToPem(jwk: PrivateJWK): { privateKey: string; keyId: string } {
function jwkToPem(jwk: PrivateJWK): string {
if (jwk.kty !== 'EC' || jwk.alg !== 'ES256') {

@@ -314,9 +315,8 @@ throw new Error(`Unsupported private key. Expected \`alg: 'ES256'\` but was \`${jwk.alg}\` }`);

const kjurJWK = JSON.parse(JSON.stringify(jwk));
const keyId = jwk.kid ?? KJUR.jws.JWS.getJWKthumbprint(kjurJWK);
kjurJWK.crv = 'secp256r1'; // KJUR's preferred name for name for P-256
const privateKey = (KEYUTIL.getPEM(KEYUTIL.getKey(kjurJWK), 'PKCS8PRV') as unknown) as string; // The type definitions are wrong: they say `void` but it's actually `string`.
return {
privateKey,
keyId,
};
const privateKey = (jsrsasign.KEYUTIL.getPEM(
jsrsasign.KEYUTIL.getKey(kjurJWK),
'PKCS8PRV',
) as unknown) as string; // The type definitions are wrong: they say `void` but it's actually `string`.
return privateKey;
}

@@ -332,3 +332,3 @@

privateKey: string;
keyId: string;
keyId?: string;
payload: JsonObject;

@@ -348,3 +348,3 @@ /** The token's lifetime in seconds. */

return KJUR.jws.JWS.sign(null, header, payload, privateKey);
return jsrsasign.KJUR.jws.JWS.sign(null, header, payload, privateKey);
}
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