Comparing version 1.7.1 to 2.0.0-rc.0
# Changelog | ||
## 2.0.0 | ||
See the [changelog entry][nodejs-2.0.0] and [migration guide][] for details. | ||
[nodejs-2.0.0]: https://www.osohq.com/docs/reference/client-apis/changelog#nodejs-2.0.0 | ||
[migration guide]: https://www.osohq.com/docs/reference/client-apis/node/migrating-to-v2 | ||
## 1.7.1 | ||
- Add `X-Request-ID` header to uniquely identify individual API requests; include this ID in error messages for better debugging. | ||
@@ -5,0 +13,0 @@ |
{ | ||
"name": "oso-cloud", | ||
"version": "1.7.1", | ||
"description": "Oso Cloud Node client", | ||
"version": "2.0.0-rc.0", | ||
"description": "Oso Cloud Node.js Client SDK", | ||
"engines": { | ||
"node": ">=16.0.0" | ||
}, | ||
"keywords": [ | ||
@@ -24,2 +27,3 @@ "authorization", | ||
"test": "jest -i", | ||
"ts:check": "tsc --noEmit", | ||
"prettier:check": "prettier --check \"**/*.{js,ts,tsx,json}\"", | ||
@@ -37,3 +41,3 @@ "prettier": "prettier --write \"**/*.{js,ts,tsx,json}\"", | ||
"devDependencies": { | ||
"@types/jest": "^28.1.2", | ||
"@types/jest": "^29.5.12", | ||
"@types/node-fetch": "^2.6.2", | ||
@@ -47,12 +51,12 @@ "@types/pg": "^8.11.2", | ||
"eslint-plugin-promise": "^6.0.0", | ||
"jest": "^28.1", | ||
"jest": "^29.7", | ||
"kysely": "^0.27.2", | ||
"pg": "^8.11.3", | ||
"prettier": "^2.6.2", | ||
"prettier": "^3.2.5", | ||
"rimraf": "^3.0.2", | ||
"sequelize": "^6.37.3", | ||
"ts-jest": "^28.0.5", | ||
"ts-jest": "^29.1.4", | ||
"typeorm": "0.3.19", | ||
"typescript": "^4.7.4" | ||
"typescript": "^5.4.5" | ||
} | ||
} |
@@ -6,31 +6,35 @@ /// <reference types="node" /> | ||
import { ClientOptions } from "."; | ||
export declare type ApiResult = { | ||
export type ApiResult = { | ||
message: string; | ||
}; | ||
export declare type ApiError = { | ||
export type ApiError = { | ||
message: string; | ||
}; | ||
export declare type Policy = { | ||
export type Policy = { | ||
filename: string | null; | ||
src: string; | ||
}; | ||
export declare type GetPolicyResult = { | ||
export type GetPolicyResult = { | ||
policy: Policy | null; | ||
}; | ||
export declare type Fact = { | ||
export type Fact = { | ||
predicate: string; | ||
args: Value[]; | ||
}; | ||
export declare type Value = { | ||
export type ConcreteFact = { | ||
predicate: string; | ||
args: TypedId[]; | ||
}; | ||
export type Value = { | ||
type: string | null; | ||
id: string | null; | ||
}; | ||
export declare type Bulk = { | ||
export type Bulk = { | ||
delete: Fact[]; | ||
tell: Fact[]; | ||
}; | ||
export declare type AuthorizeResult = { | ||
export type AuthorizeResult = { | ||
allowed: boolean; | ||
}; | ||
export declare type AuthorizeQuery = { | ||
export type AuthorizeQuery = { | ||
actor_type: string; | ||
@@ -43,16 +47,6 @@ actor_id: string; | ||
}; | ||
export declare type AuthorizeResourcesResult = { | ||
results: Value[]; | ||
}; | ||
export declare type AuthorizeResourcesQuery = { | ||
actor_type: string; | ||
actor_id: string; | ||
action: string; | ||
resources: Value[]; | ||
context_facts: Fact[]; | ||
}; | ||
export declare type ListResult = { | ||
export type ListResult = { | ||
results: string[]; | ||
}; | ||
export declare type ListQuery = { | ||
export type ListQuery = { | ||
actor_type: string; | ||
@@ -64,6 +58,6 @@ actor_id: string; | ||
}; | ||
export declare type ActionsResult = { | ||
export type ActionsResult = { | ||
results: string[]; | ||
}; | ||
export declare type ActionsQuery = { | ||
export type ActionsQuery = { | ||
actor_type: string; | ||
@@ -75,10 +69,10 @@ actor_id: string; | ||
}; | ||
export declare type QueryResult = { | ||
export type DeprecatedQueryResult = { | ||
results: Fact[]; | ||
}; | ||
export declare type Query = { | ||
export type DeprecatedQuery = { | ||
fact: Fact; | ||
context_facts: Fact[]; | ||
}; | ||
export declare type StatsResult = { | ||
export type StatsResult = { | ||
policy: { | ||
@@ -94,6 +88,35 @@ versions: string[]; | ||
}; | ||
export declare type LocalQueryResult = { | ||
export type BatchInserts = { | ||
inserts: Fact[]; | ||
}; | ||
export type BatchDeletes = { | ||
deletes: Fact[]; | ||
}; | ||
export type FactChangeset = BatchInserts | BatchDeletes; | ||
export type TypedId = { | ||
type: string; | ||
id: string; | ||
}; | ||
export type QueryCall = [string, string[]]; | ||
export type QueryConstraint = { | ||
type: string; | ||
ids: string[] | null; | ||
}; | ||
export type Query = { | ||
predicate: QueryCall; | ||
calls: QueryCall[]; | ||
constraints: { | ||
[key: string]: QueryConstraint; | ||
}; | ||
context_facts: ConcreteFact[]; | ||
}; | ||
export type QueryResult = { | ||
results: { | ||
[key: string]: string | null; | ||
}[]; | ||
}; | ||
export type LocalQueryResult = { | ||
sql: string; | ||
}; | ||
export declare type PolicyMetadata = { | ||
export type PolicyMetadata = { | ||
resources: { | ||
@@ -111,3 +134,3 @@ [resource: string]: { | ||
}; | ||
export declare type GetPolicyMetadataResult = { | ||
export type GetPolicyMetadataResult = { | ||
metadata: PolicyMetadata; | ||
@@ -150,13 +173,8 @@ }; | ||
postPolicy(data: Policy): Promise<ApiResult>; | ||
postFacts(data: Fact): Promise<Fact>; | ||
deleteFacts(data: Fact): Promise<ApiResult>; | ||
postBulkLoad(data: Fact[]): Promise<ApiResult>; | ||
postBulkDelete(data: Fact[]): Promise<ApiResult>; | ||
postBulk(data: Bulk): Promise<ApiResult>; | ||
postBatch(data: FactChangeset[]): Promise<ApiResult>; | ||
postAuthorize(data: AuthorizeQuery): Promise<AuthorizeResult>; | ||
postAuthorizeResources(data: AuthorizeResourcesQuery): Promise<AuthorizeResourcesResult>; | ||
postList(data: ListQuery): Promise<ListResult>; | ||
postActions(data: ActionsQuery): Promise<ActionsResult>; | ||
postBulkActions(data: ActionsQuery[]): Promise<ActionsResult[]>; | ||
postQuery(data: Query): Promise<QueryResult>; | ||
postQuery(data: DeprecatedQuery): Promise<DeprecatedQueryResult>; | ||
postQueryNew(data: Query): Promise<QueryResult>; | ||
getStats(): Promise<StatsResult>; | ||
@@ -163,0 +181,0 @@ postActionsQuery(query: ActionsQuery): Promise<LocalQueryResult>; |
@@ -1,2 +0,1 @@ | ||
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
@@ -11,16 +10,11 @@ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Api = void 0; | ||
// This file is generated from the openapi spec | ||
const url_1 = require("url"); | ||
const http_1 = __importDefault(require("http")); | ||
const https_1 = __importDefault(require("https")); | ||
const fs_1 = require("fs"); | ||
const crypto_1 = require("crypto"); | ||
const cross_fetch_1 = __importDefault(require("cross-fetch")); | ||
const package_json_1 = require("../package.json"); | ||
const fetch_retry_1 = __importDefault(require("fetch-retry")); | ||
import { URLSearchParams, URL } from "url"; | ||
import http from "http"; | ||
import https from "https"; | ||
import { promises as fs } from "fs"; | ||
import { randomUUID } from "crypto"; | ||
import originalFetch from "cross-fetch"; | ||
import { version } from "../package.json"; | ||
import fetchBuilder from "fetch-retry"; | ||
const retryOptions = { | ||
@@ -35,4 +29,4 @@ retries: 5, | ||
const maxBodySizeBytes = 10485760; | ||
const fetch = (0, fetch_retry_1.default)(cross_fetch_1.default, retryOptions); | ||
class Api { | ||
const fetch = fetchBuilder(originalFetch, retryOptions); | ||
export class Api { | ||
constructor(url, apiKey, options) { | ||
@@ -44,3 +38,3 @@ if (typeof url !== "string" && url !== undefined) | ||
this.debug = options.debug; | ||
this.clientId = (0, crypto_1.randomUUID)(); | ||
this.clientId = randomUUID(); | ||
if (options.userAgent) { | ||
@@ -50,13 +44,13 @@ this.userAgent = options.userAgent; | ||
else if (typeof process === "object") { | ||
this.userAgent = `Oso Cloud (nodejs ${process.version}; rv:${package_json_1.version})`; | ||
this.userAgent = `Oso Cloud (nodejs ${process.version}; rv:${version})`; | ||
} | ||
else { | ||
this.userAgent = `Oso Cloud (browser; rv:${package_json_1.version})`; | ||
this.userAgent = `Oso Cloud (browser; rv:${version})`; | ||
} | ||
const parsed = new url_1.URL(this.url); | ||
const parsed = new URL(this.url); | ||
if (parsed.protocol === "https:") { | ||
this.agent = new https_1.default.Agent({ keepAlive: true }); | ||
this.agent = new https.Agent({ keepAlive: true }); | ||
} | ||
else if (parsed.protocol === "http:") { | ||
this.agent = new http_1.default.Agent({ keepAlive: true }); | ||
this.agent = new http.Agent({ keepAlive: true }); | ||
} | ||
@@ -69,8 +63,8 @@ else { | ||
this.fallbackUrl = options.fallbackUrl; | ||
const parsed = new url_1.URL(this.fallbackUrl); | ||
const parsed = new URL(this.fallbackUrl); | ||
if (parsed.protocol === "https:") { | ||
this.fallbackAgent = new https_1.default.Agent({ keepAlive: true }); | ||
this.fallbackAgent = new https.Agent({ keepAlive: true }); | ||
} | ||
else if (parsed.protocol === "http:") { | ||
this.fallbackAgent = new http_1.default.Agent({ keepAlive: true }); | ||
this.fallbackAgent = new http.Agent({ keepAlive: true }); | ||
} | ||
@@ -82,3 +76,3 @@ else { | ||
if (options.dataBindings) { | ||
this.dataBindings = fs_1.promises.readFile(options.dataBindings, "utf-8"); | ||
this.dataBindings = fs.readFile(options.dataBindings, "utf-8"); | ||
} | ||
@@ -94,3 +88,3 @@ } | ||
"/actions", | ||
"/query", | ||
"/evaluate_query", | ||
].includes(path)); | ||
@@ -110,3 +104,3 @@ } | ||
try { | ||
yield fs_1.promises.appendFile(file, msg + "\n"); | ||
yield fs.appendFile(file, msg + "\n"); | ||
} | ||
@@ -140,3 +134,3 @@ catch (error) { | ||
if (params) | ||
url += `?${new url_1.URLSearchParams(params)}`; | ||
url += `?${new URLSearchParams(params)}`; | ||
let request = { | ||
@@ -163,3 +157,3 @@ method, | ||
request.agent = this.fallbackAgent; | ||
var result = yield (0, cross_fetch_1.default)(url, request); | ||
var result = yield originalFetch(url, request); | ||
} | ||
@@ -175,3 +169,3 @@ else { | ||
request.agent = this.fallbackAgent; | ||
var result = yield (0, cross_fetch_1.default)(url, request); | ||
var result = yield originalFetch(url, request); | ||
this.printRequestTimingInfo(result, fallbackStartTime, path); | ||
@@ -207,3 +201,3 @@ } | ||
_headers() { | ||
return Object.assign(Object.assign({ "Content-Type": "application/json", Authorization: `Bearer ${this.token}`, "User-Agent": this.userAgent, "X-OsoApiVersion": "0" }, (this.lastOffset ? { OsoOffset: this.lastOffset } : {})), { "X-Request-ID": (0, crypto_1.randomUUID)(), Accept: "application/json", "X-Oso-Instance-Id": this.clientId }); | ||
return Object.assign(Object.assign({ "Content-Type": "application/json", Authorization: `Bearer ${this.token}`, "User-Agent": this.userAgent, "X-OsoApiVersion": "0" }, (this.lastOffset ? { OsoOffset: this.lastOffset } : {})), { "X-Request-ID": randomUUID(), Accept: "application/json", "X-Oso-Instance-Id": this.clientId }); | ||
} | ||
@@ -230,27 +224,7 @@ getPolicy() { | ||
} | ||
postFacts(data) { | ||
postBatch(data) { | ||
const params = {}; | ||
const result = this._post(`/facts`, params, data, true); | ||
const result = this._post(`/batch`, params, data, true); | ||
return result; | ||
} | ||
deleteFacts(data) { | ||
const params = {}; | ||
const result = this._delete(`/facts`, params, data); | ||
return result; | ||
} | ||
postBulkLoad(data) { | ||
const params = {}; | ||
const result = this._post(`/bulk_load`, params, data, true); | ||
return result; | ||
} | ||
postBulkDelete(data) { | ||
const params = {}; | ||
const result = this._post(`/bulk_delete`, params, data, true); | ||
return result; | ||
} | ||
postBulk(data) { | ||
const params = {}; | ||
const result = this._post(`/bulk`, params, data, true); | ||
return result; | ||
} | ||
postAuthorize(data) { | ||
@@ -261,7 +235,2 @@ const params = {}; | ||
} | ||
postAuthorizeResources(data) { | ||
const params = {}; | ||
const result = this._post(`/authorize_resources`, params, data, false); | ||
return result; | ||
} | ||
postList(data) { | ||
@@ -277,10 +246,10 @@ const params = {}; | ||
} | ||
postBulkActions(data) { | ||
postQuery(data) { | ||
const params = {}; | ||
const result = this._post(`/bulk_actions`, params, data, false); | ||
const result = this._post(`/query`, params, data, false); | ||
return result; | ||
} | ||
postQuery(data) { | ||
postQueryNew(data) { | ||
const params = {}; | ||
const result = this._post(`/query`, params, data, false); | ||
const result = this._post(`/evaluate_query`, params, data, false); | ||
return result; | ||
@@ -331,4 +300,2 @@ } | ||
} | ||
// NOTE: the args stuff here does not show up in the openapi spec | ||
// so we don't codegen this correctly | ||
getFacts(predicate, args) { | ||
@@ -350,3 +317,2 @@ let params = {}; | ||
} | ||
exports.Api = Api; | ||
//# sourceMappingURL=api.js.map |
@@ -1,9 +0,15 @@ | ||
import { IntoInstance, Instance } from "."; | ||
import { Fact, Value } from "./api"; | ||
export declare function paramToFact(predicate: string, ...args: IntoInstance[]): Fact; | ||
export declare function mapParamsToFacts(params?: [predicate: string, ...args: IntoInstance[]][]): Fact[]; | ||
export declare function factToParam(fact: Fact): [predicate: string, ...args: Instance[]]; | ||
export declare function mapFactsToParams(facts?: Fact[]): [predicate: string, ...args: Instance[]][]; | ||
export declare function toValue(instance: IntoInstance): Value; | ||
export declare function fromValue(value: Value): Instance; | ||
import { Fact, Value, IntoFactPattern, IntoValuePattern, IntoValue, IntoFact } from "."; | ||
import { Fact as ApiFact, Value as ApiValue, ConcreteFact } from "./api"; | ||
export declare function paramToFact([predicate, ...args]: IntoFactPattern<Fact>): ApiFact; | ||
export declare function mapParamsToFacts(params?: IntoFactPattern<Fact>[]): ApiFact[]; | ||
export declare function paramToConcreteFact([predicate, ...args]: IntoFact<Fact>): ConcreteFact; | ||
export declare function mapParamsToConcreteFacts(params?: IntoFact<Fact>[]): ConcreteFact[]; | ||
export declare function factToParam<F extends [string, ...ApiValue[]]>({ predicate, args, }: ApiFact): F; | ||
export declare function mapFactsToParams<F extends [string, ...ApiValue[]]>(facts?: ApiFact[]): F[]; | ||
export declare function toValue(instance: IntoValue<Value>): Value; | ||
export declare function toValuePattern(instance: IntoValuePattern<Value>): ApiValue; | ||
export type DefaultPolarTypes = { | ||
fact: Fact; | ||
query: Fact; | ||
}; | ||
//# sourceMappingURL=helpers.d.ts.map |
@@ -1,25 +0,51 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.fromValue = exports.toValue = exports.mapFactsToParams = exports.factToParam = exports.mapParamsToFacts = exports.paramToFact = void 0; | ||
function paramToFact(predicate, ...args) { | ||
export function paramToFact([predicate, ...args]) { | ||
return { predicate, args: args.map(toValuePattern) }; | ||
} | ||
export function mapParamsToFacts(params) { | ||
if (!params) | ||
return []; | ||
return params.map(paramToFact); | ||
} | ||
export function paramToConcreteFact([predicate, ...args]) { | ||
return { predicate, args: args.map(toValue) }; | ||
} | ||
exports.paramToFact = paramToFact; | ||
function mapParamsToFacts(params) { | ||
export function mapParamsToConcreteFacts(params) { | ||
if (!params) | ||
return []; | ||
return params.map((param) => paramToFact(...param)); | ||
return params.map(paramToConcreteFact); | ||
} | ||
exports.mapParamsToFacts = mapParamsToFacts; | ||
function factToParam(fact) { | ||
return [fact.predicate, ...fact.args.map(fromValue)]; | ||
export function factToParam({ predicate, args, }) { | ||
return [predicate, ...args]; | ||
} | ||
exports.factToParam = factToParam; | ||
function mapFactsToParams(facts) { | ||
export function mapFactsToParams(facts) { | ||
if (!facts) | ||
return []; | ||
return facts.map((fact) => factToParam(fact)); | ||
return facts.map(factToParam); | ||
} | ||
exports.mapFactsToParams = mapFactsToParams; | ||
function toValue(instance) { | ||
export function toValue(instance) { | ||
if (typeof instance === "string") { | ||
if (instance === "") { | ||
throw new TypeError(`Oso: Instance cannot be an empty string. For wildcards, use the empty object ({}) or null.`); | ||
} | ||
return { type: "String", id: instance }; | ||
} | ||
if (typeof instance === "boolean") { | ||
return { type: "Boolean", id: instance.toString() }; | ||
} | ||
if (typeof instance === "number") { | ||
if (instance > Number.MAX_SAFE_INTEGER || | ||
instance < Number.MIN_SAFE_INTEGER) { | ||
throw new Error(`Oso: integer identifier is outside the range of safe integers, making it unsuitable for use as an identifier`); | ||
} | ||
if (!Number.isInteger(instance)) { | ||
throw new Error(`Oso: non-integer numeric values may not be used as identifiers`); | ||
} | ||
return { type: "Integer", id: instance.toString() }; | ||
} | ||
if (typeof instance === "bigint") { | ||
return { type: "Integer", id: instance.toString() }; | ||
} | ||
return { type: instance.type, id: instance.id }; | ||
} | ||
export function toValuePattern(instance) { | ||
if (instance === null) { | ||
@@ -65,27 +91,2 @@ return { type: null, id: null }; | ||
} | ||
exports.toValue = toValue; | ||
function fromValue(value) { | ||
if (value.id === null) { | ||
if (value.type === null) { | ||
return null; | ||
} | ||
else { | ||
return { type: value.type }; | ||
} | ||
} | ||
else { | ||
if (value.type === null) { | ||
throw new TypeError(`Oso: Invalid Value: ${value}`); | ||
} | ||
else { | ||
if (value.type === "String") { | ||
return value.id; | ||
} | ||
else { | ||
return { id: value.id, type: value.type }; | ||
} | ||
} | ||
} | ||
} | ||
exports.fromValue = fromValue; | ||
//# sourceMappingURL=helpers.js.map |
@@ -1,14 +0,58 @@ | ||
import { Api } from "./api"; | ||
export declare type Instance = { | ||
type?: string; | ||
id?: string; | ||
} | string | null; | ||
export declare type IntoInstance = Instance | boolean | number | bigint; | ||
export declare type Fact = [predicate: string, ...args: Instance[]]; | ||
export declare type IntoFact = [predicate: string, ...args: IntoInstance[]]; | ||
export declare type Context = { | ||
contextFacts?: IntoFact[]; | ||
import { Api, type FactChangeset } from "./api"; | ||
import { QueryBuilder, QueryArgs } from "./query"; | ||
import { DefaultPolarTypes } from "./helpers"; | ||
export { typedVar } from "./query"; | ||
export type Value = { | ||
type: string; | ||
id: string; | ||
}; | ||
export type Values = [Value] | [Value, Value] | [Value, Value, Value] | [Value, Value, Value, Value] | [Value, Value, Value, Value, Value]; | ||
export type Fact = [string, ...Values]; | ||
/** | ||
* The type of values that can be converted into an Oso fact arg of type `V`. For example, | ||
* ```typescript | ||
* IntoValue<{ type: "Integer"; id: "123" }> = | ||
* ``` | ||
* is equivalent to | ||
* ```typescript | ||
* { type: "Integer"; id: "123" } | 123 | ||
* ``` | ||
* | ||
* @param {Value} V | ||
*/ | ||
export type IntoValue<V extends Value = Value> = V | ("String" extends V["type"] ? V["id"] : never) | ("Integer" extends V["type"] ? V["id"] extends `${infer N extends number | bigint}` ? N : number | bigint : never) | ("Boolean" extends V["type"] ? V["id"] extends `${infer B extends boolean}` ? B : boolean : never); | ||
export type IntoValues<A extends Value[] = Values> = A extends [ | ||
infer HD extends Value, | ||
...infer TL extends Value[] | ||
] ? [IntoValue<HD>, ...IntoValues<TL>] : []; | ||
export type IntoFact<F extends Fact = Fact> = F extends [ | ||
infer P extends string, | ||
...infer A extends Value[] | ||
] ? [P, ...IntoValues<A>] : never; | ||
/** | ||
* The type of values that can query Oso fact arg of type `V`. For example, | ||
* ```typescript | ||
* IntoValueQuery<{ type: "Integer"; id: "123" }> = | ||
* ``` | ||
* is equivalent to | ||
* ```typescript | ||
* { type: "Integer"; id: "123" } | 123 | { type?: "Integer" | null; id?: null } | null | ||
* ``` | ||
* | ||
* @param {Value} V | ||
*/ | ||
export type IntoValuePattern<V extends Value = Value> = IntoValue<V> | { | ||
type?: V["type"] | null; | ||
id?: null; | ||
} | null; | ||
export type IntoValuePatterns<A extends Value[] = Values> = A extends [ | ||
infer HD extends Value, | ||
...infer TL extends Value[] | ||
] ? [IntoValuePattern<HD>, ...IntoValuePatterns<TL>] : []; | ||
export type IntoFactPattern<F extends Fact = Fact> = F extends [ | ||
infer P extends string, | ||
...infer A extends Value[] | ||
] ? [P, ...IntoValuePatterns<A>] : never; | ||
export { AuthorizeResult } from "./api"; | ||
export declare type ClientOptions = { | ||
export type ClientOptions = { | ||
debug?: { | ||
@@ -22,2 +66,74 @@ print?: boolean; | ||
}; | ||
type AuthorizeArgs<F extends Fact, Q extends Fact> = Q extends [ | ||
infer Allow, | ||
infer Actor extends Value, | ||
{ | ||
type: infer String; | ||
id: infer Action; | ||
}, | ||
infer Resource extends Value | ||
] ? ["allow", "String"] extends [Allow, String] ? [IntoValue<Actor>, Action, IntoValue<Resource>, IntoFact<F>[]?] : never : never; | ||
type ListArgs<F extends Fact, Q extends Fact> = Q extends [ | ||
infer Allow, | ||
infer Actor extends Value, | ||
{ | ||
type: infer String; | ||
id: infer Action; | ||
}, | ||
{ | ||
type: infer ResourceType; | ||
id: string; | ||
} | ||
] ? ["allow", "String"] extends [Allow, String] ? [IntoValue<Actor>, Action, ResourceType, IntoFact<F>[]?] : never : never; | ||
type ActionsArgs<F extends Fact, Q extends Fact> = Q extends [ | ||
infer Allow, | ||
infer Actor extends Value, | ||
{ | ||
type: infer String; | ||
}, | ||
infer Resource extends Value | ||
] ? ["allow", "String"] extends [Allow, String] ? [IntoValue<Actor>, IntoValue<Resource>, IntoFact<F>[]?] : never : never; | ||
type ActionsResult<Q extends Fact, Args extends ActionsArgs<Fact, Fact>> = Q extends [ | ||
infer Allow, | ||
Value, | ||
{ | ||
type: infer String; | ||
id: infer Action; | ||
}, | ||
Value | ||
] ? ["allow", "String", Args] extends [Allow, String, ActionsArgs<Fact, Q>] ? Action : never : never; | ||
type GetArgsArgs<A extends Value[]> = [] | (A extends [infer HD extends Value, ...infer TL extends Value[]] ? [IntoValuePattern<HD>, ...GetArgsArgs<TL>] : never); | ||
type GetArgs<F extends Fact> = F extends [ | ||
infer P extends string, | ||
...infer A extends Value[] | ||
] ? [P, ...GetArgsArgs<A>] : never; | ||
type GetResult<F extends Fact, Args extends GetArgs<Fact>> = F extends unknown ? Args extends GetArgs<F> ? F : never : never; | ||
type ActionsLocalArgs<Q extends Fact> = Q extends [ | ||
infer Allow, | ||
infer Actor extends Value, | ||
{ | ||
type: infer String; | ||
}, | ||
infer Resource extends Value | ||
] ? ["allow", "String"] extends [Allow, String] ? [IntoValue<Actor>, IntoValue<Resource>] : never : never; | ||
type AuthorizeLocalArgs<Q extends Fact> = Q extends [ | ||
infer Allow, | ||
infer Actor extends Value, | ||
{ | ||
type: infer String; | ||
id: infer Action; | ||
}, | ||
infer Resource extends Value | ||
] ? ["allow", "String"] extends [Allow, String] ? [IntoValue<Actor>, Action, IntoValue<Resource>] : never : never; | ||
type ListLocalArgs<Q extends Fact> = Q extends [ | ||
infer Allow, | ||
infer Actor extends Value, | ||
{ | ||
type: infer String; | ||
id: infer Action; | ||
}, | ||
{ | ||
type: infer ResourceType; | ||
} | ||
] ? ["allow", "String"] extends [Allow, String] ? [IntoValue<Actor>, Action, ResourceType, string] : never : never; | ||
/** | ||
@@ -29,3 +145,3 @@ * Oso Cloud client | ||
*/ | ||
export declare class Oso { | ||
export declare class Oso<PT extends DefaultPolarTypes = DefaultPolarTypes> { | ||
api: Api; | ||
@@ -36,23 +152,10 @@ constructor(url: string, apiKey: string, options?: ClientOptions); | ||
* | ||
* @param {IntoInstance} actor | ||
* @param {IntoValue} actor | ||
* @param {string} action | ||
* @param {IntoInstance} resource | ||
* @param {IntoValue} resource | ||
* @param {IntoFact[]} [contextFacts] | ||
* @returns {Promise<boolean>} | ||
*/ | ||
authorize(actor: IntoInstance, action: string, resource: IntoInstance, contextFacts?: IntoFact[]): Promise<boolean>; | ||
authorize(...[actor, action, resource, contextFacts]: AuthorizeArgs<PT["fact"], PT["query"]>): Promise<boolean>; | ||
/** | ||
* Check authorized resources: | ||
* | ||
* Returns a subset of the resources on which an actor can perform | ||
* a particular action. Ordering and duplicates, if any exist, are preserved. | ||
* | ||
* @param {IntoInstance} actor | ||
* @param {string} action | ||
* @param {IntoInstance[]} resources | ||
* @param {IntoFact[]} [contextFacts] | ||
* @returns {Promise<IntoInstance[]>} | ||
*/ | ||
authorizeResources<T extends IntoInstance>(actor: IntoInstance, action: string, resources: T[], contextFacts?: IntoFact[]): Promise<T[]>; | ||
/** | ||
* List authorized resources: | ||
@@ -62,3 +165,3 @@ * | ||
* | ||
* @param {IntoInstance} actor | ||
* @param {IntoValue} actor | ||
* @param {string} action | ||
@@ -69,3 +172,3 @@ * @param {string} resourceType | ||
*/ | ||
list(actor: IntoInstance, action: string, resourceType: string, contextFacts?: IntoFact[]): Promise<string[]>; | ||
list(...[actor, action, resourceType, contextFacts]: ListArgs<PT["fact"], PT["query"]>): Promise<string[]>; | ||
/** | ||
@@ -76,21 +179,9 @@ * List authorized actions: | ||
* | ||
* @param {IntoInstance} actor | ||
* @param {IntoInstance} resource | ||
* @param {IntoValue} actor | ||
* @param {IntoValue} resource | ||
* @param {IntoFact[]} [contextFacts] | ||
* @returns {Promise<string[]>} | ||
*/ | ||
actions(actor: IntoInstance, resource: IntoInstance, contextFacts?: IntoFact[]): Promise<string[]>; | ||
actions<Args extends ActionsArgs<PT["fact"], PT["query"]>>(...[actor, resource, contextFacts]: Args): Promise<ActionsResult<PT["query"], Args>[]>; | ||
/** | ||
* List authorized actions for a list of resources | ||
* Fetches a list of actions which an actor can perform on a list of resources. | ||
* | ||
* Note: this only works for resources of the same type. | ||
* | ||
* @param {IntoInstance} actor | ||
* @param {IntoInstance[]} resources | ||
* @param {IntoFact[]} [contextFacts] | ||
* @returns {Promise<string[][]>} | ||
*/ | ||
bulkActions(actor: IntoInstance, resources: IntoInstance[], contextFacts?: IntoFact[]): Promise<string[][]>; | ||
/** | ||
* Update the active policy: | ||
@@ -103,3 +194,3 @@ * | ||
*/ | ||
policy(src: string): Promise<void>; | ||
policy(src: DefaultPolarTypes extends PT ? string : "Updating the policy in this way is not recommended when using types generated from the policy."): Promise<void>; | ||
/** | ||
@@ -110,49 +201,2 @@ * Returns metadata about the currently active policy | ||
/** | ||
* Add a fact: | ||
* | ||
* Adds a fact with the given predicate and arguments. | ||
* | ||
* @param {string} predicate | ||
* @param {...IntoInstance} args | ||
* @returns {Promise<Fact>} | ||
*/ | ||
tell(predicate: string, ...args: IntoInstance[]): Promise<Fact>; | ||
/** | ||
* Delete fact: | ||
* | ||
* Deletes a fact. Does not throw an error if the fact is not found. | ||
* | ||
* @param {string} predicate | ||
* @param {...IntoInstance} args | ||
*/ | ||
delete(predicate: string, ...args: IntoInstance[]): Promise<void>; | ||
/** | ||
* Add many facts: | ||
* | ||
* Adds many facts at once. | ||
* | ||
* @param {IntoFact[]} facts | ||
*/ | ||
bulkTell(facts: IntoFact[]): Promise<void>; | ||
/** | ||
* Delete many facts: | ||
* | ||
* Deletes many facts at once. Does not throw an error when some of the | ||
* facts are not found. | ||
* | ||
* @param {IntoFact[]} facts | ||
*/ | ||
bulkDelete(facts: IntoFact[]): Promise<void>; | ||
/** | ||
* Transactionally delete and add facts: oso.bulk(delete, tell) | ||
* | ||
* Deletes and adds many facts in one atomic transaction. | ||
* The deletions are performed before the adds. null can be used as a wildcard in facts in delete. | ||
* Does not throw an error when the facts to delete are not found. | ||
* | ||
* @param {IntoFact[]} delete | ||
* @param {IntoFact[]} tell | ||
*/ | ||
bulk(delete_?: IntoFact[], tell?: IntoFact[]): Promise<void>; | ||
/** | ||
* Get facts: | ||
@@ -169,25 +213,7 @@ * | ||
* @param {string} predicate | ||
* @param {...IntoInstance} args | ||
* @param {...IntoValuePattern} args | ||
* @returns {Promise<Fact[]>} | ||
*/ | ||
get(predicate: string, ...args: IntoInstance[]): Promise<Fact[]>; | ||
get<Args extends GetArgs<PT["fact"]>>(...[predicate, ...args]: Args): Promise<GetResult<PT["fact"], Args>[]>; | ||
/** | ||
* Query Oso Cloud for any predicate, and any combination of concrete and | ||
* wildcard arguments. | ||
* | ||
* @param {string} predicate | ||
* @param {...IntoInstance} args | ||
* @returns {Promise<Fact[]>} | ||
*/ | ||
query(predicate: string, ...args: IntoInstance[]): Promise<Fact[]>; | ||
/** | ||
* Query Oso Cloud for any predicate, and any combination of concrete and | ||
* wildcard arguments. Accepts a list of context facts. | ||
* | ||
* @param {IntoFact} fact | ||
* @param {Context} context | ||
* @returns {Promise<Fact[]>} | ||
*/ | ||
query_with_context(fact: IntoFact, { contextFacts }: Context): Promise<Fact[]>; | ||
/** | ||
* Fetches a query that can be run against your database to determine the actions | ||
@@ -198,7 +224,7 @@ * an actor can perform on a resource. | ||
* | ||
* @param {IntoInstance} actor | ||
* @param {IntoInstance} resource | ||
* @param {IntoValue} actor | ||
* @param {IntoValue} resource | ||
* @returns {Promise<string>} | ||
*/ | ||
actionsLocal(actor: IntoInstance, resource: IntoInstance): Promise<string>; | ||
actionsLocal(...[actor, resource]: ActionsLocalArgs<PT["query"]>): Promise<string>; | ||
/** | ||
@@ -209,8 +235,8 @@ * Check a permission depending on data both in Oso Cloud and stored in a local database. | ||
* | ||
* @param {IntoInstance} actor | ||
* @param {IntoValue} actor | ||
* @param {string} action | ||
* @param {IntoInstance} resource | ||
* @param {IntoValue} resource | ||
* @returns {Promise<string>} | ||
*/ | ||
authorizeLocal(actor: IntoInstance, action: string, resource: IntoInstance): Promise<string>; | ||
authorizeLocal(...[actor, action, resource]: AuthorizeLocalArgs<PT["query"]>): Promise<string>; | ||
/** | ||
@@ -221,3 +247,3 @@ * List authorized resources depending on data both in Oso Cloud and stored in a local database. | ||
* | ||
* @param {IntoInstance} actor | ||
* @param {IntoValue} actor | ||
* @param {string} action | ||
@@ -228,4 +254,61 @@ * @param {string} resourceType | ||
*/ | ||
listLocal(actor: IntoInstance, action: string, resourceType: string, column: string): Promise<string>; | ||
listLocal(...[actor, action, resourceType, column]: ListLocalArgs<PT["query"]>): Promise<string>; | ||
/** | ||
* Query for an arbitrary expression. | ||
* Use `typedVar` to create variables to use in the query, | ||
* and refer to them in the final `evaluate` call to get their values. | ||
* | ||
* @param query | ||
* @returns {QueryBuilder} | ||
*/ | ||
buildQuery(query: QueryArgs<PT["fact"] | PT["query"]>): QueryBuilder<PT>; | ||
/** | ||
* Add a fact: | ||
* | ||
* Adds a fact with the given predicate and arguments. | ||
* | ||
* @param {IntoFact} fact | ||
*/ | ||
insert(fact: IntoFact<PT["fact"]>): Promise<void>; | ||
/** | ||
* Delete fact: | ||
* | ||
* Deletes a fact. Does not throw an error if the fact is not found. | ||
* You can use `null` as a wildcard argument. | ||
* | ||
* @param {IntoFactPattern} fact | ||
*/ | ||
delete(fact: IntoFactPattern<PT["fact"]>): Promise<void>; | ||
/** | ||
* Transactionally delete and add facts: | ||
* | ||
* Allows deleting and inserting many facts in one atomic transaction. | ||
* Deletions and insertions are run in the order they appear in the closure. | ||
* | ||
* @param {(tx: BatchTransaction) => any} the closure which runs the `insert`s and `delete`s. | ||
* These changes can be issued via `tx.insert(fact)` and `tx.delete(fact)` within the closure. | ||
*/ | ||
batch(f: (tx: BatchTransaction<PT>) => any): Promise<void>; | ||
} | ||
declare class BatchTransaction<PT extends DefaultPolarTypes> { | ||
changes: FactChangeset[]; | ||
constructor(); | ||
/** | ||
* Add a fact: | ||
* | ||
* Adds a fact with the given predicate and arguments. | ||
* | ||
* @param {IntoFact} fact | ||
*/ | ||
insert(fact: IntoFact<PT["fact"]>): void; | ||
/** | ||
* Delete fact: | ||
* | ||
* Deletes a fact. Does not throw an error if the fact is not found. | ||
* You can use `null` as a wildcard argument. | ||
* | ||
* @param {IntoFactPattern} fact | ||
*/ | ||
delete(fact: IntoFactPattern<PT["fact"]>): void; | ||
} | ||
//# sourceMappingURL=index.d.ts.map |
@@ -1,2 +0,1 @@ | ||
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
@@ -11,6 +10,6 @@ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Oso = void 0; | ||
const helpers_1 = require("./helpers"); | ||
const api_1 = require("./api"); | ||
import { mapFactsToParams, paramToFact, toValuePattern, toValue, mapParamsToConcreteFacts, } from "./helpers"; | ||
import { Api } from "./api"; | ||
import { QueryBuilder } from "./query"; | ||
export { typedVar } from "./query"; | ||
/** | ||
@@ -22,5 +21,8 @@ * Oso Cloud client | ||
*/ | ||
class Oso { | ||
export class Oso { | ||
constructor(url, apiKey, options) { | ||
this.api = new api_1.Api(url, apiKey, options || {}); | ||
if ((options === null || options === void 0 ? void 0 : options.fallbackUrl) !== undefined) { | ||
throw new Error("The `fallbackUrl` option is not currently supported in the Node.js client while we are rolling out support for the new APIs in Oso Fallback."); | ||
} | ||
this.api = new Api(url, apiKey, options || {}); | ||
} | ||
@@ -30,15 +32,15 @@ /** | ||
* | ||
* @param {IntoInstance} actor | ||
* @param {IntoValue} actor | ||
* @param {string} action | ||
* @param {IntoInstance} resource | ||
* @param {IntoValue} resource | ||
* @param {IntoFact[]} [contextFacts] | ||
* @returns {Promise<boolean>} | ||
*/ | ||
authorize(actor, action, resource, contextFacts) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
authorize() { | ||
return __awaiter(this, arguments, void 0, function* (...[actor, action, resource, contextFacts]) { | ||
if (typeof action !== "string") { | ||
throw new TypeError(`'action' should be a string: ${action}`); | ||
} | ||
let { type: actor_type, id: actor_id } = (0, helpers_1.toValue)(actor); | ||
let { type: resource_type, id: resource_id } = (0, helpers_1.toValue)(resource); | ||
let { type: actor_type, id: actor_id } = toValue(actor); | ||
let { type: resource_type, id: resource_id } = toValue(resource); | ||
if (actor_type == null || actor_id == null) { | ||
@@ -56,3 +58,3 @@ throw new TypeError(`'actor' can not be a wildcard: ${actor}`); | ||
resource_id, | ||
context_facts: (0, helpers_1.mapParamsToFacts)(contextFacts), | ||
context_facts: mapParamsToConcreteFacts(contextFacts), | ||
}); | ||
@@ -63,50 +65,2 @@ return result.allowed; | ||
/** | ||
* Check authorized resources: | ||
* | ||
* Returns a subset of the resources on which an actor can perform | ||
* a particular action. Ordering and duplicates, if any exist, are preserved. | ||
* | ||
* @param {IntoInstance} actor | ||
* @param {string} action | ||
* @param {IntoInstance[]} resources | ||
* @param {IntoFact[]} [contextFacts] | ||
* @returns {Promise<IntoInstance[]>} | ||
*/ | ||
authorizeResources(actor, action, resources, contextFacts) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (typeof action !== "string") { | ||
throw new TypeError(`'action' should be a string: ${action}`); | ||
} | ||
const { type: actor_type, id: actor_id } = (0, helpers_1.toValue)(actor); | ||
function key(e) { | ||
return `${e.type}:${e.id}`; | ||
} | ||
if (!resources || resources.length === 0) { | ||
return []; | ||
} | ||
if (actor_type == null || actor_id == null) { | ||
throw new TypeError(`'actor' can not be a wildcard: ${actor}`); | ||
} | ||
const resourcesExtracted = resources.map((r) => (0, helpers_1.toValue)(r)); | ||
const { results } = yield this.api.postAuthorizeResources({ | ||
actor_type, | ||
actor_id, | ||
action, | ||
resources: resourcesExtracted, | ||
context_facts: (0, helpers_1.mapParamsToFacts)(contextFacts), | ||
}); | ||
if (results.length == 0) { | ||
return []; | ||
} | ||
const resultsLookup = {}; | ||
for (let i = 0, len = results.length; i < len; ++i) { | ||
let k = key(results[i]); | ||
if (!(k in resultsLookup)) { | ||
resultsLookup[k] = true; | ||
} | ||
} | ||
return resources.filter((r) => resultsLookup[key((0, helpers_1.toValue)(r))]); | ||
}); | ||
} | ||
/** | ||
* List authorized resources: | ||
@@ -116,3 +70,3 @@ * | ||
* | ||
* @param {IntoInstance} actor | ||
* @param {IntoValue} actor | ||
* @param {string} action | ||
@@ -123,7 +77,7 @@ * @param {string} resourceType | ||
*/ | ||
list(actor, action, resourceType, contextFacts) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
list() { | ||
return __awaiter(this, arguments, void 0, function* (...[actor, action, resourceType, contextFacts]) { | ||
if (typeof action !== "string") | ||
throw new TypeError(`'action' should be a string: ${action}`); | ||
const { type: actor_type, id: actor_id } = (0, helpers_1.toValue)(actor); | ||
const { type: actor_type, id: actor_id } = toValue(actor); | ||
if (actor_type == null || actor_id == null) { | ||
@@ -137,3 +91,3 @@ throw new TypeError(`'actor' can not be a wildcard: ${actor}`); | ||
resource_type: resourceType, | ||
context_facts: (0, helpers_1.mapParamsToFacts)(contextFacts), | ||
context_facts: mapParamsToConcreteFacts(contextFacts), | ||
}); | ||
@@ -148,11 +102,11 @@ return results; | ||
* | ||
* @param {IntoInstance} actor | ||
* @param {IntoInstance} resource | ||
* @param {IntoValue} actor | ||
* @param {IntoValue} resource | ||
* @param {IntoFact[]} [contextFacts] | ||
* @returns {Promise<string[]>} | ||
*/ | ||
actions(actor, resource, contextFacts) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let { type: actor_type, id: actor_id } = (0, helpers_1.toValue)(actor); | ||
let { type: resource_type, id: resource_id } = (0, helpers_1.toValue)(resource); | ||
actions() { | ||
return __awaiter(this, arguments, void 0, function* (...[actor, resource, contextFacts]) { | ||
let { type: actor_type, id: actor_id } = toValue(actor); | ||
let { type: resource_type, id: resource_id } = toValue(resource); | ||
if (actor_type == null || actor_id == null) { | ||
@@ -169,3 +123,3 @@ throw new TypeError(`'actor' can not be a wildcard: ${actor}`); | ||
resource_id, | ||
context_facts: (0, helpers_1.mapParamsToFacts)(contextFacts), | ||
context_facts: mapParamsToConcreteFacts(contextFacts), | ||
}); | ||
@@ -176,50 +130,2 @@ return results; | ||
/** | ||
* List authorized actions for a list of resources | ||
* Fetches a list of actions which an actor can perform on a list of resources. | ||
* | ||
* Note: this only works for resources of the same type. | ||
* | ||
* @param {IntoInstance} actor | ||
* @param {IntoInstance[]} resources | ||
* @param {IntoFact[]} [contextFacts] | ||
* @returns {Promise<string[][]>} | ||
*/ | ||
bulkActions(actor, resources, contextFacts) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const { type: actor_type, id: actor_id } = (0, helpers_1.toValue)(actor); | ||
if (actor_type === null || actor_id === null) { | ||
throw new TypeError(`'actor' can not be a wildcard: ${actor}`); | ||
} | ||
let resourceType = null; | ||
const mappedResources = resources.map((resource) => { | ||
const { type: resource_type, id: resource_id } = (0, helpers_1.toValue)(resource); | ||
if (resource_type === null) { | ||
throw new TypeError(`'resource' can not be a wildcard: ${resource}`); | ||
} | ||
else if (resource_id === null) { | ||
throw new TypeError(`'resource' can not be a wildcard: ${resource}`); | ||
} | ||
else if (resourceType === null) { | ||
resourceType = resource_type; | ||
} | ||
else if (resourceType !== resource_type) { | ||
throw new TypeError(`BulkActions resources must be of the same type. Expected ${resourceType}; got ${resource_type}`); | ||
} | ||
return { type: resource_type, id: resource_id }; | ||
}); | ||
if (mappedResources.length === 0) { | ||
return []; | ||
} | ||
const queries = mappedResources.map((resource, idx) => ({ | ||
actor_type, | ||
actor_id, | ||
resource_type: resource.type, | ||
resource_id: resource.id, | ||
context_facts: idx === 0 ? (0, helpers_1.mapParamsToFacts)(contextFacts) : [], | ||
})); | ||
const results = yield this.api.postBulkActions(queries); | ||
return results.map((r) => r.results); | ||
}); | ||
} | ||
/** | ||
* Update the active policy: | ||
@@ -246,78 +152,2 @@ * | ||
/** | ||
* Add a fact: | ||
* | ||
* Adds a fact with the given predicate and arguments. | ||
* | ||
* @param {string} predicate | ||
* @param {...IntoInstance} args | ||
* @returns {Promise<Fact>} | ||
*/ | ||
tell(predicate, ...args) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return (0, helpers_1.factToParam)(yield this.api.postFacts({ | ||
predicate, | ||
args: args.map(helpers_1.toValue), | ||
})); | ||
}); | ||
} | ||
/** | ||
* Delete fact: | ||
* | ||
* Deletes a fact. Does not throw an error if the fact is not found. | ||
* | ||
* @param {string} predicate | ||
* @param {...IntoInstance} args | ||
*/ | ||
delete(predicate, ...args) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
yield this.api.deleteFacts({ | ||
predicate, | ||
args: args.map(helpers_1.toValue), | ||
}); | ||
}); | ||
} | ||
/** | ||
* Add many facts: | ||
* | ||
* Adds many facts at once. | ||
* | ||
* @param {IntoFact[]} facts | ||
*/ | ||
bulkTell(facts) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
yield this.api.postBulkLoad((0, helpers_1.mapParamsToFacts)(facts)); | ||
}); | ||
} | ||
/** | ||
* Delete many facts: | ||
* | ||
* Deletes many facts at once. Does not throw an error when some of the | ||
* facts are not found. | ||
* | ||
* @param {IntoFact[]} facts | ||
*/ | ||
bulkDelete(facts) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
yield this.api.postBulkDelete((0, helpers_1.mapParamsToFacts)(facts)); | ||
}); | ||
} | ||
/** | ||
* Transactionally delete and add facts: oso.bulk(delete, tell) | ||
* | ||
* Deletes and adds many facts in one atomic transaction. | ||
* The deletions are performed before the adds. null can be used as a wildcard in facts in delete. | ||
* Does not throw an error when the facts to delete are not found. | ||
* | ||
* @param {IntoFact[]} delete | ||
* @param {IntoFact[]} tell | ||
*/ | ||
bulk(delete_ = [], tell = []) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
yield this.api.postBulk({ | ||
delete: (0, helpers_1.mapParamsToFacts)(delete_), | ||
tell: (0, helpers_1.mapParamsToFacts)(tell), | ||
}); | ||
}); | ||
} | ||
/** | ||
* Get facts: | ||
@@ -334,41 +164,13 @@ * | ||
* @param {string} predicate | ||
* @param {...IntoInstance} args | ||
* @param {...IntoValuePattern} args | ||
* @returns {Promise<Fact[]>} | ||
*/ | ||
get(predicate, ...args) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let varArgs = args.map(helpers_1.toValue); | ||
let facts = (0, helpers_1.mapFactsToParams)(yield this.api.getFacts(predicate, varArgs)); | ||
return facts; | ||
get() { | ||
return __awaiter(this, arguments, void 0, function* (...[predicate, ...args]) { | ||
// TODO: either change arity-wildcarding in backend or weaken return type | ||
let varArgs = args.map(toValuePattern); | ||
return mapFactsToParams(yield this.api.getFacts(predicate, varArgs)); | ||
}); | ||
} | ||
/** | ||
* Query Oso Cloud for any predicate, and any combination of concrete and | ||
* wildcard arguments. | ||
* | ||
* @param {string} predicate | ||
* @param {...IntoInstance} args | ||
* @returns {Promise<Fact[]>} | ||
*/ | ||
query(predicate, ...args) { | ||
return this.query_with_context([predicate, ...args], {}); | ||
} | ||
/** | ||
* Query Oso Cloud for any predicate, and any combination of concrete and | ||
* wildcard arguments. Accepts a list of context facts. | ||
* | ||
* @param {IntoFact} fact | ||
* @param {Context} context | ||
* @returns {Promise<Fact[]>} | ||
*/ | ||
query_with_context(fact, { contextFacts }) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const { results } = yield this.api.postQuery({ | ||
fact: (0, helpers_1.paramToFact)(...fact), | ||
context_facts: (0, helpers_1.mapParamsToFacts)(contextFacts), | ||
}); | ||
return (0, helpers_1.mapFactsToParams)(results); | ||
}); | ||
} | ||
/** | ||
* Fetches a query that can be run against your database to determine the actions | ||
@@ -379,10 +181,10 @@ * an actor can perform on a resource. | ||
* | ||
* @param {IntoInstance} actor | ||
* @param {IntoInstance} resource | ||
* @param {IntoValue} actor | ||
* @param {IntoValue} resource | ||
* @returns {Promise<string>} | ||
*/ | ||
actionsLocal(actor, resource) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const { type: actor_type, id: actor_id } = (0, helpers_1.toValue)(actor); | ||
const { type: resource_type, id: resource_id } = (0, helpers_1.toValue)(resource); | ||
actionsLocal() { | ||
return __awaiter(this, arguments, void 0, function* (...[actor, resource]) { | ||
const { type: actor_type, id: actor_id } = toValue(actor); | ||
const { type: resource_type, id: resource_id } = toValue(resource); | ||
if (actor_type == null || actor_id == null) { | ||
@@ -409,14 +211,14 @@ throw new TypeError(`'actor' can not be a wildcard: ${actor}`); | ||
* | ||
* @param {IntoInstance} actor | ||
* @param {IntoValue} actor | ||
* @param {string} action | ||
* @param {IntoInstance} resource | ||
* @param {IntoValue} resource | ||
* @returns {Promise<string>} | ||
*/ | ||
authorizeLocal(actor, action, resource) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
authorizeLocal() { | ||
return __awaiter(this, arguments, void 0, function* (...[actor, action, resource]) { | ||
if (typeof action !== "string") { | ||
throw new TypeError(`'action' should be a string: ${action}`); | ||
} | ||
const { type: actor_type, id: actor_id } = (0, helpers_1.toValue)(actor); | ||
const { type: resource_type, id: resource_id } = (0, helpers_1.toValue)(resource); | ||
const { type: actor_type, id: actor_id } = toValue(actor); | ||
const { type: resource_type, id: resource_id } = toValue(resource); | ||
if (actor_type == null || actor_id == null) { | ||
@@ -444,3 +246,3 @@ throw new TypeError(`'actor' can not be a wildcard: ${actor}`); | ||
* | ||
* @param {IntoInstance} actor | ||
* @param {IntoValue} actor | ||
* @param {string} action | ||
@@ -451,7 +253,7 @@ * @param {string} resourceType | ||
*/ | ||
listLocal(actor, action, resourceType, column) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
listLocal() { | ||
return __awaiter(this, arguments, void 0, function* (...[actor, action, resourceType, column]) { | ||
if (typeof action !== "string") | ||
throw new TypeError(`'action' should be a string: ${action}`); | ||
const { type: actor_type, id: actor_id } = (0, helpers_1.toValue)(actor); | ||
const { type: actor_type, id: actor_id } = toValue(actor); | ||
if (actor_type == null || actor_id == null) { | ||
@@ -470,4 +272,97 @@ throw new TypeError(`'actor' can not be a wildcard: ${actor}`); | ||
} | ||
/** | ||
* Query for an arbitrary expression. | ||
* Use `typedVar` to create variables to use in the query, | ||
* and refer to them in the final `evaluate` call to get their values. | ||
* | ||
* @param query | ||
* @returns {QueryBuilder} | ||
*/ | ||
buildQuery(query) { | ||
return QueryBuilder.init(this, query); | ||
} | ||
/** | ||
* Add a fact: | ||
* | ||
* Adds a fact with the given predicate and arguments. | ||
* | ||
* @param {IntoFact} fact | ||
*/ | ||
insert(fact) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const fact_ = paramToFact(fact); | ||
yield this.api.postBatch([{ inserts: [fact_] }]); | ||
}); | ||
} | ||
/** | ||
* Delete fact: | ||
* | ||
* Deletes a fact. Does not throw an error if the fact is not found. | ||
* You can use `null` as a wildcard argument. | ||
* | ||
* @param {IntoFactPattern} fact | ||
*/ | ||
delete(fact) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const fact_ = paramToFact(fact); | ||
yield this.api.postBatch([{ deletes: [fact_] }]); | ||
}); | ||
} | ||
/** | ||
* Transactionally delete and add facts: | ||
* | ||
* Allows deleting and inserting many facts in one atomic transaction. | ||
* Deletions and insertions are run in the order they appear in the closure. | ||
* | ||
* @param {(tx: BatchTransaction) => any} the closure which runs the `insert`s and `delete`s. | ||
* These changes can be issued via `tx.insert(fact)` and `tx.delete(fact)` within the closure. | ||
*/ | ||
batch(f) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
let txn = new BatchTransaction(); | ||
yield f(txn); | ||
if (txn.changes.length) { | ||
yield this.api.postBatch(txn.changes); | ||
} | ||
}); | ||
} | ||
} | ||
exports.Oso = Oso; | ||
class BatchTransaction { | ||
constructor() { | ||
this.changes = []; | ||
} | ||
/** | ||
* Add a fact: | ||
* | ||
* Adds a fact with the given predicate and arguments. | ||
* | ||
* @param {IntoFact} fact | ||
*/ | ||
insert(fact) { | ||
const fact_ = paramToFact(fact); | ||
let last = this.changes[this.changes.length - 1]; | ||
if (last === undefined || !("inserts" in last)) { | ||
last = { inserts: [] }; | ||
this.changes.push(last); | ||
} | ||
last.inserts.push(fact_); | ||
} | ||
/** | ||
* Delete fact: | ||
* | ||
* Deletes a fact. Does not throw an error if the fact is not found. | ||
* You can use `null` as a wildcard argument. | ||
* | ||
* @param {IntoFactPattern} fact | ||
*/ | ||
delete(fact) { | ||
const fact_ = paramToFact(fact); | ||
let last = this.changes[this.changes.length - 1]; | ||
if (last === undefined || !("deletes" in last)) { | ||
last = { deletes: [] }; | ||
this.changes.push(last); | ||
} | ||
last.deletes.push(fact_); | ||
} | ||
} | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "oso-cloud", | ||
"version": "1.7.1", | ||
"description": "Oso Cloud Node client", | ||
"version": "2.0.0-rc.0", | ||
"description": "Oso Cloud Node.js Client SDK", | ||
"engines": { | ||
"node": ">=16.0.0" | ||
}, | ||
"keywords": [ | ||
@@ -24,2 +27,3 @@ "authorization", | ||
"test": "jest -i", | ||
"ts:check": "tsc --noEmit", | ||
"prettier:check": "prettier --check \"**/*.{js,ts,tsx,json}\"", | ||
@@ -37,3 +41,3 @@ "prettier": "prettier --write \"**/*.{js,ts,tsx,json}\"", | ||
"devDependencies": { | ||
"@types/jest": "^28.1.2", | ||
"@types/jest": "^29.5.12", | ||
"@types/node-fetch": "^2.6.2", | ||
@@ -47,12 +51,12 @@ "@types/pg": "^8.11.2", | ||
"eslint-plugin-promise": "^6.0.0", | ||
"jest": "^28.1", | ||
"jest": "^29.7", | ||
"kysely": "^0.27.2", | ||
"pg": "^8.11.3", | ||
"prettier": "^2.6.2", | ||
"prettier": "^3.2.5", | ||
"rimraf": "^3.0.2", | ||
"sequelize": "^6.37.3", | ||
"ts-jest": "^28.0.5", | ||
"ts-jest": "^29.1.4", | ||
"typeorm": "0.3.19", | ||
"typescript": "^4.7.4" | ||
"typescript": "^5.4.5" | ||
} | ||
} |
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
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
112217
20
1619
2