Skip to content

Commit

Permalink
Merge pull request #18 from agiledigital/beta
Browse files Browse the repository at this point in the history
Add checked Patch support
  • Loading branch information
dbalmain committed Jun 18, 2022
2 parents ddb60e0 + 52bff16 commit b0c62cc
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 28 deletions.
16 changes: 10 additions & 6 deletions bin/gen-idm-ts-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,11 @@ function generateConnectorTypes(idmConfigDir, subConnectorTypes) {
// Resolve the path preferring the current working directory
connectorObject = require(path.resolve(conn));
} catch (err) {
var newErr = Error("Failed to load connector file [" + conn + "]");
newErr.stack += "\nCaused by: " + err.stack;
throw newErr;
if (err instanceof Error) {
var newErr = Error("Failed to load connector file [" + conn + "]");
newErr.stack += "\nCaused by: " + err.stack;
throw newErr;
}
}

const match = provisionerRegex.exec(conn);
Expand Down Expand Up @@ -231,9 +233,11 @@ function generateManagedTypes(idmConfigDir, subManagedTypes) {
// Resolve the path preferring the current working directory
managedObjects = require(path.resolve(managedObjectsFile));
} catch (err) {
var newErr = Error("Failed to load managed objects file [" + managedObjectsFile + "]");
newErr.stack += "\nCaused by: " + err.stack;
throw newErr;
if (err instanceof Error) {
var newErr = Error("Failed to load managed objects file [" + managedObjectsFile + "]");
newErr.stack += "\nCaused by: " + err.stack;
throw newErr;
}
}
const idmTypes = managedObjects.objects.sort(compareName).map(mo => {
const managedTypeName = generateManagedTypeName(mo.name);
Expand Down
22 changes: 19 additions & 3 deletions lib/idm-globals.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,30 @@ interface HashedValue {}

type HashAlgorithm = "SHA-256" | "SHA-384" | "SHA-512" | "Bcrypt" | "Scrypt" | "PBKDF2";

type PatchOperation = "add" | "remove" | "replace" | "increment";
type PatchRemoveOperation = "remove"
type PatchValueOperation = "add" | "replace" | "increment" | "transform";
type PatchFromOperation = "copy" | "move";
type PatchOperation = PatchValueOperation | PatchRemoveOperation | PatchFromOperation;

type PatchOpts = {
operation: PatchOperation;
operation: PatchValueOperation;
field: string;
value: any;
} | {
operation: PatchRemoveOperation;
field: string;
value?: any;
} | {
operation: PatchFromOperation;
from: string;
field: string;
};

/**
* These are the valid actions available to a particular situation during synchronization.
*
* @see https://backstage.forgerock.com/docs/idm/7.1/synchronization-guide/sync-actions.html#sync-actions
*/
type Action = "CREATE" | "UPDATE" | "DELETE" | "LINK" | "UNLINK" | "EXCEPTION" | "IGNORE" | "REPORT" | "NOREPORT" | "ASYNC";

interface OpenIDM {
Expand All @@ -41,7 +57,7 @@ interface OpenIDM {
isEncrypted: (value: any) => value is EncryptedValue;
hash: (value: any, algorithm?: HashAlgorithm) => HashedValue;
isHashed: (value: any) => value is HashedValue;
matches: (string: HashedValue, value: any) => boolean;
matches: (string: string, value: HashedValue) => boolean;
}

type Cookie = {};
Expand Down
37 changes: 32 additions & 5 deletions lib/idm-ts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,26 @@ type ResultType<T extends IDMObjectType<string>, FieldTypes extends keyof T> = P
type QueryFilterTypesafeParams<T extends IDMObjectType<string>> = { filter: Filter<T> };
type QueryFilterExtended<T extends IDMObjectType<string>> = QueryFilter | (QueryFilterTypesafeParams<T> & QueryOpts);

export type CheckedPatchOpts<T> = {
operation: PatchValueOperation;
field: Fields<T>;
value: any;
} | {
operation: PatchRemoveOperation;
field: Fields<T>;
value?: any;
} | {
operation: PatchFromOperation;
from: string;
field: Fields<T>;
};

type CombinedPatchOpts<T> = {
readonly checkedPatches?: CheckedPatchOpts<T>[];
readonly unCheckedPatches: PatchOpts[];
}
type CompositePatchOpts<T> = CheckedPatchOpts<T>[] | CombinedPatchOpts<T>

export type WithOptionalId<A extends { _id: string }> = Omit<A, "_id"> & {
_id?: string;
};
Expand Down Expand Up @@ -60,23 +80,26 @@ export class IDMObject<T extends IDMObjectType<string>, D extends IDMObjectType<
public patch<F extends Fields<T>>(
id: string,
rev: string | null,
value: PatchOpts[],
value: CompositePatchOpts<T>,
options: { readonly params?: object; readonly fields: F[] }
): ResultType<T, F>;
public patch<F extends Fields<T>>(
id: string,
rev: string | null,
value: PatchOpts[],
value: CompositePatchOpts<T>,
options: { readonly params?: object; readonly unCheckedFields: F[] }
): T & Revision;
public patch<F extends Fields<T>>(id: string, rev: string | null, value: PatchOpts[], options?: { readonly params?: object }): D & Revision;
public patch<F extends Fields<T>>(id: string, rev: string | null, value: CompositePatchOpts<T>, options?: { readonly params?: object }): D & Revision;
public patch<F extends Fields<T>>(
id: string,
rev: string | null,
value: PatchOpts[],
value: CompositePatchOpts<T>,
{ params, fields, unCheckedFields }: { readonly params?: object; readonly fields?: F[]; readonly unCheckedFields?: string[] } = {}
) {
return openidm.patch(`${this.type}/${id}`, rev, value, params, unCheckedFields ? unCheckedFields : fields);
const patchValues = this.isCombinedPatchOpts(value)
? [...value.unCheckedPatches, ...value.checkedPatches ?? []]
: value;
return openidm.patch(`${this.type}/${id}`, rev, patchValues, params, unCheckedFields ? unCheckedFields : fields);
}

public update<F extends Fields<T>>(
Expand Down Expand Up @@ -155,6 +178,10 @@ export class IDMObject<T extends IDMObjectType<string>, D extends IDMObjectType<
return params;
}
}

private isCombinedPatchOpts(value: CompositePatchOpts<T>): value is CombinedPatchOpts<T> {
return (value as CombinedPatchOpts<T>)?.unCheckedPatches !== undefined
}
}

export const idmObject = <T extends IDMObjectType<string>, D extends IDMObjectType<string>>(type: Exclude<T["_tag"], undefined>) =>
Expand Down
6 changes: 3 additions & 3 deletions lib/query-filter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export const anyOf = <A>(...dsl: Filter<A>[]): Filter<A> => dsl.reduce((p, c) =>
// this returns true if any are true.
export const oneOf = <A, K extends keyof A>(field: keyof A, ...vals: A[K][]): Filter<A> => anyOf(...vals.map(x => equals(field, x)));

const escapeQuotes = (str: string): string => str.replace("'", "\\'");
const escapeQuotes = (str: string): string => str.replace(/'/g, "\\'");
const prepareValue = (val: unknown): string => {
if (typeof val === "string") {
return `'${escapeQuotes(val ?? "")}'`;
Expand All @@ -117,13 +117,13 @@ export const interpretToFilter = <A>(dsl: Filter<A>): string => {
case Kind.Contains:
case Kind.StartsWith:
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
return `/${dsl.field} ${dsl.kind} ${prepareValue(dsl.val)}`;
return `/${dsl.field.toString()} ${dsl.kind} ${prepareValue(dsl.val)}`;
case Kind.And:
case Kind.Or:
return `(${interpretToFilter(dsl.a)} ${dsl.kind} ${interpretToFilter(dsl.b)})`;
case Kind.Presence:
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
return `/${dsl.field} ${dsl.kind}`;
return `/${dsl.field.toString()} ${dsl.kind}`;
case Kind.Not:
return `${dsl.kind}(${interpretToFilter(dsl.filter)})`;
case Kind.True:
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"tslint-immutable": "^6.0.1",
"tslint-sonarts": "^1.9.0",
"type-coverage": "^2.1.0",
"typescript": "^3.9.4"
"typescript": "^4.7.3"
},
"scripts": {
"type-check": "tsc --noEmit",
Expand Down
20 changes: 10 additions & 10 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3484,9 +3484,9 @@ semver-diff@^3.1.1:
semver "^6.3.0"

semver-regex@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-3.1.2.tgz#34b4c0d361eef262e07199dbef316d0f2ab11807"
integrity sha512-bXWyL6EAKOJa81XG1OZ/Yyuq+oT0b2YLlxx7c+mrdYPaPbnj6WgVULXhinMIeZGufuUBu/eVRqXEhiv4imfwxA==
version "3.1.3"
resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-3.1.3.tgz#b2bcc6f97f63269f286994e297e229b6245d0dc3"
integrity sha512-Aqi54Mk9uYTjVexLnR67rTyBusmwd04cLkHy9hNvk3+G3nT2Oyg7E0l4XVbOaNwIvQ3hHeYxGcyEy+mKreyBFQ==

"semver@2 || 3 || 4 || 5", semver@^5.3.0:
version "5.7.1"
Expand Down Expand Up @@ -3783,9 +3783,9 @@ supports-hyperlinks@^2.1.0:
supports-color "^7.0.0"

tar@^6.0.2, tar@^6.1.0:
version "6.1.3"
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.3.tgz#e44b97ee7d6cc7a4c574e8b01174614538291825"
integrity sha512-3rUqwucgVZXTeyJyL2jqtUau8/8r54SioM1xj3AmTX3HnWQdj2AydfJ2qYYayPyIIznSplcvU9mhBb7dR2XF3w==
version "6.1.11"
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621"
integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==
dependencies:
chownr "^2.0.0"
fs-minipass "^2.0.0"
Expand Down Expand Up @@ -4014,10 +4014,10 @@ typedarray-to-buffer@^3.1.5:
dependencies:
is-typedarray "^1.0.0"

typescript@^3.9.4:
version "3.9.7"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa"
integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==
typescript@^4.7.3:
version "4.7.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.3.tgz#8364b502d5257b540f9de4c40be84c98e23a129d"
integrity sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA==

uglify-js@^3.1.4:
version "3.13.10"
Expand Down

0 comments on commit b0c62cc

Please sign in to comment.