@party-stack/foundry-ontology 0.19.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -32
- package/lib/adapter/backend.d.ts +35 -0
- package/lib/adapter/backend.d.ts.map +1 -0
- package/lib/adapter/backend.js +210 -0
- package/lib/adapter/backend.js.map +1 -0
- package/lib/adapter/encrypted.d.ts +12 -0
- package/lib/adapter/encrypted.d.ts.map +1 -0
- package/lib/adapter/encrypted.js +79 -0
- package/lib/adapter/encrypted.js.map +1 -0
- package/lib/adapter/foundryActionError.d.ts +7 -0
- package/lib/adapter/foundryActionError.d.ts.map +1 -0
- package/lib/adapter/foundryActionError.js +61 -0
- package/lib/adapter/foundryActionError.js.map +1 -0
- package/lib/adapter/foundryActionValidation.d.ts +4 -3
- package/lib/adapter/foundryActionValidation.d.ts.map +1 -1
- package/lib/adapter/foundryActionValidation.js +71 -25
- package/lib/adapter/foundryActionValidation.js.map +1 -1
- package/lib/adapter/foundryCodec.d.ts +2 -5
- package/lib/adapter/foundryCodec.d.ts.map +1 -1
- package/lib/adapter/foundryCodec.js +19 -7
- package/lib/adapter/foundryCodec.js.map +1 -1
- package/lib/adapter/foundryObjectSearch.d.ts +13 -0
- package/lib/adapter/foundryObjectSearch.d.ts.map +1 -0
- package/lib/adapter/foundryObjectSearch.js +57 -0
- package/lib/adapter/foundryObjectSearch.js.map +1 -0
- package/lib/adapter/index.d.ts +3 -4
- package/lib/adapter/index.js +3 -4
- package/lib/adapter/likeFilter.d.ts +10 -0
- package/lib/adapter/likeFilter.d.ts.map +1 -0
- package/lib/adapter/likeFilter.js +87 -0
- package/lib/adapter/likeFilter.js.map +1 -0
- package/lib/adapter/makeFoundryOntologyBackend.d.ts +76 -0
- package/lib/adapter/makeFoundryOntologyBackend.d.ts.map +1 -0
- package/lib/adapter/makeFoundryOntologyBackend.js +505 -0
- package/lib/adapter/makeFoundryOntologyBackend.js.map +1 -0
- package/lib/adapter/subsetFilter.d.ts +14 -0
- package/lib/adapter/subsetFilter.d.ts.map +1 -0
- package/lib/adapter/subsetFilter.js +105 -0
- package/lib/adapter/subsetFilter.js.map +1 -0
- package/lib/adapter/uploads.d.ts +25 -0
- package/lib/adapter/uploads.d.ts.map +1 -0
- package/lib/adapter/uploads.js +78 -0
- package/lib/adapter/uploads.js.map +1 -0
- package/lib/backend.d.ts +80 -0
- package/lib/backend.d.ts.map +1 -0
- package/lib/backend.js +34 -0
- package/lib/backend.js.map +1 -0
- package/lib/config/index.d.ts +8 -12
- package/lib/config/index.d.ts.map +1 -1
- package/lib/config/index.js +49 -52
- package/lib/config/index.js.map +1 -1
- package/lib/connectionOptions.d.ts +9 -0
- package/lib/connectionOptions.d.ts.map +1 -0
- package/lib/connectionOptions.js +1 -0
- package/lib/context.d.ts +21 -0
- package/lib/context.d.ts.map +1 -0
- package/lib/context.js +16 -0
- package/lib/context.js.map +1 -0
- package/lib/index.d.ts +7 -7
- package/lib/index.js +6 -7
- package/lib/meta/backend.d.ts +10 -0
- package/lib/meta/backend.d.ts.map +1 -0
- package/lib/meta/backend.js +161 -0
- package/lib/meta/backend.js.map +1 -0
- package/lib/meta/convertMetaActionType.d.ts +3 -2
- package/lib/meta/convertMetaActionType.d.ts.map +1 -1
- package/lib/meta/convertMetaActionType.js +3 -3
- package/lib/meta/convertMetaActionType.js.map +1 -1
- package/lib/meta/convertMetaLinkType.d.ts +2 -2
- package/lib/meta/convertMetaLinkType.d.ts.map +1 -1
- package/lib/meta/convertMetaLinkType.js +13 -13
- package/lib/meta/convertMetaLinkType.js.map +1 -1
- package/lib/meta/convertMetaObjectType.d.ts +2 -2
- package/lib/meta/convertMetaObjectType.d.ts.map +1 -1
- package/lib/meta/convertMetaObjectType.js +5 -1
- package/lib/meta/convertMetaObjectType.js.map +1 -1
- package/lib/meta/convertMetaQueryFunctionType.d.ts +1 -1
- package/lib/meta/convertMetaQueryFunctionType.js.map +1 -1
- package/lib/meta/convertMetaTypeDef.d.ts +1 -1
- package/lib/meta/convertMetaTypeDef.d.ts.map +1 -1
- package/lib/meta/convertMetaTypeDef.js +7 -1
- package/lib/meta/convertMetaTypeDef.js.map +1 -1
- package/lib/meta/convertMetaValueType.d.ts +2 -2
- package/lib/meta/convertMetaValueType.d.ts.map +1 -1
- package/lib/meta/convertMetaValueType.js.map +1 -1
- package/lib/meta/convertOmsActionParameterMetadata.d.ts +1 -1
- package/lib/meta/convertOmsActionParameterMetadata.js +1 -1
- package/lib/meta/convertOmsActionParameterMetadata.js.map +1 -1
- package/lib/meta/index.d.ts +2 -4
- package/lib/meta/index.js +2 -4
- package/lib/meta/listObjectTypes.d.ts +6 -0
- package/lib/meta/listObjectTypes.d.ts.map +1 -0
- package/lib/meta/listObjectTypes.js +13 -0
- package/lib/meta/listObjectTypes.js.map +1 -0
- package/lib/meta/loadActions.d.ts +7 -0
- package/lib/meta/loadActions.d.ts.map +1 -0
- package/lib/meta/loadActions.js +20 -0
- package/lib/meta/loadActions.js.map +1 -0
- package/lib/meta/loadEntities.d.ts +9 -0
- package/lib/meta/loadEntities.d.ts.map +1 -0
- package/lib/meta/loadEntities.js +73 -0
- package/lib/meta/loadEntities.js.map +1 -0
- package/lib/meta/loadQueryFunctions.d.ts +11 -0
- package/lib/meta/loadQueryFunctions.d.ts.map +1 -0
- package/lib/meta/loadQueryFunctions.js +18 -0
- package/lib/meta/loadQueryFunctions.js.map +1 -0
- package/lib/meta/planMetaLookup.d.ts +12 -0
- package/lib/meta/planMetaLookup.d.ts.map +1 -0
- package/lib/meta/planMetaLookup.js +44 -0
- package/lib/meta/planMetaLookup.js.map +1 -0
- package/lib/platform.d.ts +78 -0
- package/lib/platform.d.ts.map +1 -0
- package/lib/platform.js +116 -0
- package/lib/platform.js.map +1 -0
- package/lib/platformCollections.d.ts +68 -0
- package/lib/platformCollections.d.ts.map +1 -0
- package/lib/platformCollections.js +7 -0
- package/lib/platformCollections.js.map +1 -0
- package/lib/serviceConnector.d.ts +8 -0
- package/lib/serviceConnector.d.ts.map +1 -0
- package/lib/serviceConnector.js +105 -0
- package/lib/serviceConnector.js.map +1 -0
- package/lib/stagedWrites.d.ts +3 -2
- package/lib/stagedWrites.d.ts.map +1 -1
- package/lib/stagedWrites.js +30 -3
- package/lib/stagedWrites.js.map +1 -1
- package/lib/users/admin.d.ts +105 -0
- package/lib/users/admin.d.ts.map +1 -0
- package/lib/users/admin.js +35 -0
- package/lib/users/admin.js.map +1 -0
- package/lib/users/createFoundryUsersIntegration.d.ts +2 -2
- package/lib/users/createFoundryUsersIntegration.d.ts.map +1 -1
- package/lib/users/createFoundryUsersIntegration.js +4 -6
- package/lib/users/createFoundryUsersIntegration.js.map +1 -1
- package/lib/users/foundryUser.d.ts +2 -2
- package/lib/users/foundryUser.js +1 -1
- package/lib/users/foundryUser.js.map +1 -1
- package/lib/users/index.d.ts +2 -3
- package/lib/users/index.js +2 -3
- package/lib/users/loadUserSubset.d.ts +8 -0
- package/lib/users/loadUserSubset.d.ts.map +1 -0
- package/lib/users/loadUserSubset.js +166 -0
- package/lib/users/loadUserSubset.js.map +1 -0
- package/lib/utils/AsyncIterable.d.ts +1 -1
- package/lib/utils/AsyncIterable.d.ts.map +1 -1
- package/lib/utils/AsyncIterable.js +11 -0
- package/lib/utils/AsyncIterable.js.map +1 -1
- package/package.json +16 -15
- package/lib/adapter/convertLoadSubsetOptions.d.ts +0 -8
- package/lib/adapter/convertLoadSubsetOptions.d.ts.map +0 -1
- package/lib/adapter/convertLoadSubsetOptions.js +0 -178
- package/lib/adapter/convertLoadSubsetOptions.js.map +0 -1
- package/lib/adapter/createFoundryOntologyBackendAdapter.d.ts +0 -29
- package/lib/adapter/createFoundryOntologyBackendAdapter.d.ts.map +0 -1
- package/lib/adapter/createFoundryOntologyBackendAdapter.js +0 -311
- package/lib/adapter/createFoundryOntologyBackendAdapter.js.map +0 -1
- package/lib/adapter/objectCollectionOptions.d.ts +0 -33
- package/lib/adapter/objectCollectionOptions.d.ts.map +0 -1
- package/lib/adapter/objectCollectionOptions.js +0 -482
- package/lib/adapter/objectCollectionOptions.js.map +0 -1
- package/lib/config/applyAttachmentConstraintOverrides.d.ts +0 -10
- package/lib/config/applyAttachmentConstraintOverrides.d.ts.map +0 -1
- package/lib/config/applyAttachmentConstraintOverrides.js +0 -50
- package/lib/config/applyAttachmentConstraintOverrides.js.map +0 -1
- package/lib/connection.d.ts +0 -38
- package/lib/connection.d.ts.map +0 -1
- package/lib/connection.js +0 -195
- package/lib/connection.js.map +0 -1
- package/lib/installation/createFoundryBackendInstallation.d.ts +0 -29
- package/lib/installation/createFoundryBackendInstallation.d.ts.map +0 -1
- package/lib/installation/createFoundryBackendInstallation.js +0 -60
- package/lib/installation/createFoundryBackendInstallation.js.map +0 -1
- package/lib/installation/index.d.ts +0 -2
- package/lib/installation/index.js +0 -1
- package/lib/meta/actionTypeCollectionOptions.d.ts +0 -14
- package/lib/meta/actionTypeCollectionOptions.d.ts.map +0 -1
- package/lib/meta/actionTypeCollectionOptions.js +0 -58
- package/lib/meta/actionTypeCollectionOptions.js.map +0 -1
- package/lib/meta/convertActionTypeLoadSubsetOptions.d.ts +0 -7
- package/lib/meta/convertActionTypeLoadSubsetOptions.d.ts.map +0 -1
- package/lib/meta/convertActionTypeLoadSubsetOptions.js +0 -84
- package/lib/meta/convertActionTypeLoadSubsetOptions.js.map +0 -1
- package/lib/meta/createFoundryMetaOntologyBackendAdapter.d.ts +0 -11
- package/lib/meta/createFoundryMetaOntologyBackendAdapter.d.ts.map +0 -1
- package/lib/meta/createFoundryMetaOntologyBackendAdapter.js +0 -43
- package/lib/meta/createFoundryMetaOntologyBackendAdapter.js.map +0 -1
- package/lib/meta/entityCollectionOptions.d.ts +0 -25
- package/lib/meta/entityCollectionOptions.d.ts.map +0 -1
- package/lib/meta/entityCollectionOptions.js +0 -69
- package/lib/meta/entityCollectionOptions.js.map +0 -1
- package/lib/meta/queryFunctionTypeCollectionOptions.d.ts +0 -12
- package/lib/meta/queryFunctionTypeCollectionOptions.d.ts.map +0 -1
- package/lib/meta/queryFunctionTypeCollectionOptions.js +0 -59
- package/lib/meta/queryFunctionTypeCollectionOptions.js.map +0 -1
- package/lib/users/createFoundryAdminOntologyRoute.d.ts +0 -55
- package/lib/users/createFoundryAdminOntologyRoute.d.ts.map +0 -1
- package/lib/users/createFoundryAdminOntologyRoute.js +0 -33
- package/lib/users/createFoundryAdminOntologyRoute.js.map +0 -1
- package/lib/users/userCollectionOptions.d.ts +0 -25
- package/lib/users/userCollectionOptions.d.ts.map +0 -1
- package/lib/users/userCollectionOptions.js +0 -94
- package/lib/users/userCollectionOptions.js.map +0 -1
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { makeFoundryBackend } from "../backend.js";
|
|
2
|
+
//#region src/users/admin.d.ts
|
|
3
|
+
export declare const foundryAdminOntology: {
|
|
4
|
+
types: never[];
|
|
5
|
+
objectTypes: {
|
|
6
|
+
name: string;
|
|
7
|
+
displayName: string;
|
|
8
|
+
pluralDisplayName: string;
|
|
9
|
+
primaryKey: string;
|
|
10
|
+
title?: string;
|
|
11
|
+
icon?: {
|
|
12
|
+
name: import("@party-stack/ontology-spec").IconName;
|
|
13
|
+
meta?: {
|
|
14
|
+
[x: string]: unknown;
|
|
15
|
+
} | undefined;
|
|
16
|
+
} | undefined;
|
|
17
|
+
color?: string;
|
|
18
|
+
properties: {
|
|
19
|
+
name: string;
|
|
20
|
+
displayName: string;
|
|
21
|
+
type: import("@party-stack/ontology-spec").TypeDef;
|
|
22
|
+
description?: string;
|
|
23
|
+
deprecated?: {
|
|
24
|
+
message: string;
|
|
25
|
+
} | undefined;
|
|
26
|
+
}[];
|
|
27
|
+
description?: string;
|
|
28
|
+
deprecated?: {
|
|
29
|
+
message: string;
|
|
30
|
+
} | undefined;
|
|
31
|
+
}[];
|
|
32
|
+
linkTypes: never[];
|
|
33
|
+
actionTypes: never[];
|
|
34
|
+
queryFunctionTypes: never[];
|
|
35
|
+
context: {
|
|
36
|
+
type: {
|
|
37
|
+
kind: "struct";
|
|
38
|
+
value: {
|
|
39
|
+
fields: {
|
|
40
|
+
name: "userId";
|
|
41
|
+
displayName: "User ID";
|
|
42
|
+
type: {
|
|
43
|
+
kind: "objectReference";
|
|
44
|
+
value: {
|
|
45
|
+
objectType: "FoundryUser";
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
}[];
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
partition: "userId"[][];
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
export declare function makeFoundryAdminBackend(options: Omit<Parameters<typeof makeFoundryBackend>[0], "ir" | "users">): import("effect/Effect").Effect<{
|
|
55
|
+
name: string;
|
|
56
|
+
sourceId: string;
|
|
57
|
+
supportsIdempotency: boolean;
|
|
58
|
+
maintenance?: import("effect/Effect").Effect<void, import("@party-stack/ontology-backend").BackendError>;
|
|
59
|
+
loadSubset: (subset: import("@party-stack/ontology-spec/query").ObjectSubset) => import("effect/Effect").Effect<import("@party-stack/ontology-backend").BackendSnapshot, import("@party-stack/ontology-backend").BackendError>;
|
|
60
|
+
query: (document: import("@party-stack/ontology-spec").QueryDocument, options?: {
|
|
61
|
+
readonly inputs?: Record<string, unknown>;
|
|
62
|
+
}) => import("effect/Effect").Effect<Record<string, unknown>, import("@party-stack/ontology-backend").BackendError>;
|
|
63
|
+
subscribeSelection?: (selection: import("@party-stack/ontology-backend").ObjectSelection, policy?: import("@party-stack/ontology-backend/delivery").DeliveryPolicy, resume?: import("@party-stack/ontology-backend/delivery").DeliveryPosition) => import("effect/Effect").Effect<import("@party-stack/ontology-backend/delivery").DeliverySubscription, import("@party-stack/ontology-backend").BackendError, import("effect/Scope").Scope>;
|
|
64
|
+
acknowledgeDelivery?: (position: import("@party-stack/ontology-backend/delivery").DeliveryPosition) => import("effect/Effect").Effect<void, import("@party-stack/ontology-backend").BackendError>;
|
|
65
|
+
resolveActionParameters?: (name: string, parameters: Record<string, unknown>) => import("effect/Effect").Effect<Record<string, unknown>, import("@party-stack/ontology-backend").BackendError>;
|
|
66
|
+
watchSubset?: (subset: import("@party-stack/ontology-spec/query").ObjectSubset) => import("effect/Effect").Effect<import("effect/Stream").Stream<import("@party-stack/ontology-backend").SubsetWatchEvent, import("@party-stack/ontology-backend").BackendError>, import("@party-stack/ontology-backend").BackendError, import("effect/Scope").Scope> | undefined;
|
|
67
|
+
refresh?: (subset: import("@party-stack/ontology-spec/query").ObjectSubset) => {
|
|
68
|
+
readonly pollIntervalMs?: number | false;
|
|
69
|
+
readonly maxCoverageAgeMs?: number;
|
|
70
|
+
} | undefined;
|
|
71
|
+
applyAction: (invocation: import("@party-stack/ontology-backend").ActionRequest) => import("effect/Effect").Effect<import("@party-stack/ontology-backend").ActionReceipt, import("@party-stack/ontology-backend").BackendError>;
|
|
72
|
+
queryFunction: (name: string, parameters: Record<string, unknown>) => import("effect/Effect").Effect<unknown, import("@party-stack/ontology-backend").BackendError>;
|
|
73
|
+
changes?: {
|
|
74
|
+
readonly pull: (options: {
|
|
75
|
+
readonly cursor?: string;
|
|
76
|
+
readonly limit?: number;
|
|
77
|
+
}) => import("effect/Effect").Effect<import("@party-stack/ontology-backend").BackendChangePage, import("@party-stack/ontology-backend").BackendError>;
|
|
78
|
+
readonly watch?: import("effect/Effect").Effect<import("effect/Stream").Stream<void, import("@party-stack/ontology-backend").BackendError>, import("@party-stack/ontology-backend").BackendError, import("effect/Scope").Scope>;
|
|
79
|
+
};
|
|
80
|
+
attachments?: import("@party-stack/ontology-backend").BackendAttachments;
|
|
81
|
+
encrypted?: import("@party-stack/ontology-backend").BackendEncryptedValues;
|
|
82
|
+
validateAction: (name: string, parameters: Record<string, unknown>, settings?: {
|
|
83
|
+
readonly knownParameters?: readonly string[];
|
|
84
|
+
}) => import("effect/Effect").Effect<{
|
|
85
|
+
readonly certain: false;
|
|
86
|
+
} | {
|
|
87
|
+
readonly certain: true;
|
|
88
|
+
readonly value: {
|
|
89
|
+
readonly kind: "ok";
|
|
90
|
+
readonly value: void;
|
|
91
|
+
} | {
|
|
92
|
+
readonly kind: "err";
|
|
93
|
+
readonly value: readonly {
|
|
94
|
+
readonly message: string;
|
|
95
|
+
readonly path?: readonly (string | number)[] | undefined;
|
|
96
|
+
readonly code?: string | undefined;
|
|
97
|
+
readonly category?: "custom" | "input" | "reference" | undefined;
|
|
98
|
+
readonly source?: "parameter" | "submission" | "user-facing" | undefined;
|
|
99
|
+
readonly messageSource?: "configured" | "standard" | undefined;
|
|
100
|
+
}[];
|
|
101
|
+
};
|
|
102
|
+
}, import("@party-stack/ontology-backend").BackendError<"Conflict" | "Forbidden" | "HistoryExpired" | "Internal" | "InvalidConfiguration" | "InvalidRequest" | "InvalidResponse" | "NotFound" | "NotImplemented" | "RateLimited" | "ResultExpired" | "SchemaMismatch" | "SessionExpired" | "SessionReplaced" | "SourceMismatch" | "Unauthenticated" | "Unavailable" | "ValidationFailed" | "ViewReplaced">, never>;
|
|
103
|
+
}, import("@party-stack/ontology-backend").BackendError<"Conflict" | "Forbidden" | "HistoryExpired" | "Internal" | "InvalidConfiguration" | "InvalidRequest" | "InvalidResponse" | "NotFound" | "NotImplemented" | "RateLimited" | "ResultExpired" | "SchemaMismatch" | "SessionExpired" | "SessionReplaced" | "SourceMismatch" | "Unauthenticated" | "Unavailable" | "ValidationFailed" | "ViewReplaced">, import("effect/Scope").Scope>;
|
|
104
|
+
//#endregion
|
|
105
|
+
//# sourceMappingURL=admin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin.d.ts","names":[],"sources":["../../src/users/admin.ts"],"mappings":";;qBAaa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBAsBG,wBACZ,SAAS,KAAK,kBAAkB,kEAAuC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2CAO1E,wXAAA"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { makeFoundryBackend } from "../backend.js";
|
|
2
|
+
import { foundryUserObjectType } from "./foundryUser.js";
|
|
3
|
+
import { createFoundryUsersIntegration } from "./createFoundryUsersIntegration.js";
|
|
4
|
+
import { defineOntology, o } from "@party-stack/ontology-spec";
|
|
5
|
+
//#region src/users/admin.ts
|
|
6
|
+
const foundryUserIdentityLens = { operations: [o.LensOp.select({ properties: foundryUserObjectType.properties.map((property) => property.name) })] };
|
|
7
|
+
const foundryAdminOntology = defineOntology({
|
|
8
|
+
types: [],
|
|
9
|
+
objectTypes: [foundryUserObjectType],
|
|
10
|
+
linkTypes: [],
|
|
11
|
+
actionTypes: [],
|
|
12
|
+
queryFunctionTypes: [],
|
|
13
|
+
context: {
|
|
14
|
+
type: o.struct({ fields: [{
|
|
15
|
+
name: "userId",
|
|
16
|
+
displayName: "User ID",
|
|
17
|
+
type: o.objectReference({ objectType: "FoundryUser" })
|
|
18
|
+
}] }),
|
|
19
|
+
partition: [["userId"]]
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
function makeFoundryAdminBackend(options) {
|
|
23
|
+
return makeFoundryBackend({
|
|
24
|
+
...options,
|
|
25
|
+
ir: foundryAdminOntology,
|
|
26
|
+
users: createFoundryUsersIntegration({
|
|
27
|
+
objectType: "FoundryUser",
|
|
28
|
+
lens: foundryUserIdentityLens
|
|
29
|
+
})
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
export { foundryAdminOntology, makeFoundryAdminBackend };
|
|
34
|
+
|
|
35
|
+
//# sourceMappingURL=admin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin.js","names":[],"sources":["../../src/users/admin.ts"],"sourcesContent":["import { defineOntology, o } from \"@party-stack/ontology-spec\";\nimport { makeFoundryBackend } from \"../backend.js\";\nimport { createFoundryUsersIntegration } from \"./createFoundryUsersIntegration.js\";\nimport { foundryUserObjectType } from \"./foundryUser.js\";\n\nconst foundryUserIdentityLens = {\n operations: [\n o.LensOp.select({\n properties: foundryUserObjectType.properties.map((property) => property.name),\n }),\n ],\n};\n\nexport const foundryAdminOntology = defineOntology({\n types: [],\n objectTypes: [foundryUserObjectType],\n linkTypes: [],\n actionTypes: [],\n queryFunctionTypes: [],\n context: {\n type: o.struct({\n fields: [\n {\n name: \"userId\",\n displayName: \"User ID\",\n type: o.objectReference({\n objectType: \"FoundryUser\",\n }),\n },\n ],\n }),\n partition: [[\"userId\"]],\n },\n});\n\nexport function makeFoundryAdminBackend(\n options: Omit<Parameters<typeof makeFoundryBackend>[0], \"ir\" | \"users\">\n) {\n return makeFoundryBackend({\n ...options,\n ir: foundryAdminOntology,\n users: createFoundryUsersIntegration({ objectType: \"FoundryUser\", lens: foundryUserIdentityLens }),\n });\n}\n"],"mappings":";;;;;AAKA,MAAM,0BAA0B,EAC5B,YAAY,CACR,EAAE,OAAO,OAAO,EACZ,YAAY,sBAAsB,WAAW,KAAK,aAAa,SAAS,IAAI,EAChF,CAAC,CACL,EACJ;AAEA,MAAa,uBAAuB,eAAe;CAC/C,OAAO,CAAC;CACR,aAAa,CAAC,qBAAqB;CACnC,WAAW,CAAC;CACZ,aAAa,CAAC;CACd,oBAAoB,CAAC;CACrB,SAAS;EACL,MAAM,EAAE,OAAO,EACX,QAAQ,CACJ;GACI,MAAM;GACN,aAAa;GACb,MAAM,EAAE,gBAAgB,EACpB,YAAY,cAChB,CAAC;EACL,CACJ,EACJ,CAAC;EACD,WAAW,CAAC,CAAC,QAAQ,CAAC;CAC1B;AACJ,CAAC;AAED,SAAgB,wBACZ,SACF;CACE,OAAO,mBAAmB;EACtB,GAAG;EACH,IAAI;EACJ,OAAO,8BAA8B;GAAE,YAAY;GAAe,MAAM;EAAwB,CAAC;CACrG,CAAC;AACL"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { FoundryUsersIntegration } from "../adapter/
|
|
2
|
-
import { Lens } from "@party-stack/ontology";
|
|
1
|
+
import { FoundryUsersIntegration } from "../adapter/makeFoundryOntologyBackend.js";
|
|
2
|
+
import { Lens } from "@party-stack/ontology-spec";
|
|
3
3
|
//#region src/users/createFoundryUsersIntegration.d.ts
|
|
4
4
|
export declare function createFoundryUsersIntegration(options: {
|
|
5
5
|
objectType: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createFoundryUsersIntegration.d.ts","names":[],"sources":["../../src/users/createFoundryUsersIntegration.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"createFoundryUsersIntegration.d.ts","names":[],"sources":["../../src/users/createFoundryUsersIntegration.ts"],"mappings":";;;wBAOgB,8BAA8B;EAC1C;EACA,MAAM;IACN"}
|
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
import { decodeFoundryUserProfilePictureAttachment } from "./foundryUser.js";
|
|
2
|
-
import {
|
|
2
|
+
import { loadUserSubset } from "./loadUserSubset.js";
|
|
3
|
+
import { readableByteSource } from "@party-stack/ontology-storage/blobs";
|
|
3
4
|
import { Users } from "@osdk/foundry.admin";
|
|
4
5
|
//#region src/users/createFoundryUsersIntegration.ts
|
|
5
6
|
function createFoundryUsersIntegration(options) {
|
|
6
7
|
return {
|
|
7
8
|
objectType: options.objectType,
|
|
8
|
-
|
|
9
|
-
client,
|
|
10
|
-
lens: options.lens
|
|
11
|
-
}),
|
|
9
|
+
loadSubset: (client, query, signal) => loadUserSubset(client, options.objectType, options.lens, query, signal),
|
|
12
10
|
async getAttachmentContent(client, attachment) {
|
|
13
11
|
const userId = decodeFoundryUserProfilePictureAttachment(attachment.id);
|
|
14
12
|
if (!userId) return;
|
|
15
13
|
const profilePicture = await Users.profilePicture(client, userId);
|
|
16
14
|
if (profilePicture.status === 204) return new Blob();
|
|
17
|
-
return profilePicture.
|
|
15
|
+
return profilePicture.body ? readableByteSource(profilePicture.body, { type: profilePicture.headers.get("content-type") ?? "application/octet-stream" }) : new Blob();
|
|
18
16
|
},
|
|
19
17
|
getAttachmentMetadata(_client, attachment) {
|
|
20
18
|
const userId = decodeFoundryUserProfilePictureAttachment(attachment.id);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createFoundryUsersIntegration.js","names":[],"sources":["../../src/users/createFoundryUsersIntegration.ts"],"sourcesContent":["import { Users } from \"@osdk/foundry.admin\";\nimport { decodeFoundryUserProfilePictureAttachment } from \"./foundryUser.js\";\nimport {
|
|
1
|
+
{"version":3,"file":"createFoundryUsersIntegration.js","names":[],"sources":["../../src/users/createFoundryUsersIntegration.ts"],"sourcesContent":["import { Users } from \"@osdk/foundry.admin\";\nimport { readableByteSource } from \"@party-stack/ontology-storage/blobs\";\nimport { decodeFoundryUserProfilePictureAttachment } from \"./foundryUser.js\";\nimport { loadUserSubset } from \"./loadUserSubset.js\";\nimport type { FoundryUsersIntegration } from \"../adapter/makeFoundryOntologyBackend.js\";\nimport type { Lens } from \"@party-stack/ontology-spec\";\n\nexport function createFoundryUsersIntegration(options: {\n objectType: string;\n lens: Lens;\n}): FoundryUsersIntegration {\n return {\n objectType: options.objectType,\n loadSubset: (client, query, signal) =>\n loadUserSubset(client, options.objectType, options.lens, query, signal),\n async getAttachmentContent(client, attachment) {\n const userId = decodeFoundryUserProfilePictureAttachment(attachment.id);\n if (!userId) return;\n const profilePicture = await Users.profilePicture(client, userId);\n if (profilePicture.status === 204) {\n return new Blob();\n }\n return profilePicture.body\n ? readableByteSource(profilePicture.body, {\n type: profilePicture.headers.get(\"content-type\") ?? \"application/octet-stream\",\n })\n : new Blob();\n },\n getAttachmentMetadata(_client, attachment) {\n const userId = decodeFoundryUserProfilePictureAttachment(attachment.id);\n return Promise.resolve(\n userId\n ? {\n id: attachment.id,\n type: attachment.type,\n name: `${userId} profile picture`,\n }\n : undefined\n );\n },\n };\n}\n"],"mappings":";;;;;AAOA,SAAgB,8BAA8B,SAGlB;CACxB,OAAO;EACH,YAAY,QAAQ;EACpB,aAAa,QAAQ,OAAO,WACxB,eAAe,QAAQ,QAAQ,YAAY,QAAQ,MAAM,OAAO,MAAM;EAC1E,MAAM,qBAAqB,QAAQ,YAAY;GAC3C,MAAM,SAAS,0CAA0C,WAAW,EAAE;GACtE,IAAI,CAAC,QAAQ;GACb,MAAM,iBAAiB,MAAM,MAAM,eAAe,QAAQ,MAAM;GAChE,IAAI,eAAe,WAAW,KAC1B,OAAO,IAAI,KAAK;GAEpB,OAAO,eAAe,OAChB,mBAAmB,eAAe,MAAM,EACpC,MAAM,eAAe,QAAQ,IAAI,cAAc,KAAK,2BACxD,CAAC,IACD,IAAI,KAAK;EACnB;EACA,sBAAsB,SAAS,YAAY;GACvC,MAAM,SAAS,0CAA0C,WAAW,EAAE;GACtE,OAAO,QAAQ,QACX,SACM;IACI,IAAI,WAAW;IACf,MAAM,WAAW;IACjB,MAAM,GAAG,OAAO;GACpB,IACA,KAAA,CACV;EACJ;CACJ;AACJ"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Lens, ObjectTypeDef } from "@party-stack/ontology";
|
|
2
|
-
import * as v from "@party-stack/ontology/values";
|
|
1
|
+
import { Lens, ObjectTypeDef } from "@party-stack/ontology-spec";
|
|
2
|
+
import * as v from "@party-stack/ontology-spec/values";
|
|
3
3
|
//#region src/users/foundryUser.d.ts
|
|
4
4
|
export declare const foundryUserObjectType: ObjectTypeDef;
|
|
5
5
|
/**
|
package/lib/users/foundryUser.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"foundryUser.js","names":[],"sources":["../../src/users/foundryUser.ts"],"sourcesContent":["import { applyLensToObjectType, o, type Lens, type ObjectTypeDef } from \"@party-stack/ontology\";\nimport type * as v from \"@party-stack/ontology/values\";\n\nexport const foundryUserObjectType: ObjectTypeDef = {\n name: \"FoundryUser\",\n displayName: \"Foundry user\",\n pluralDisplayName: \"Foundry users\",\n primaryKey: \"id\",\n properties: [\n { name: \"id\", displayName: \"ID\", type: o.string({}) },\n { name: \"username\", displayName: \"Username\", type: o.string({}) },\n {\n name: \"givenName\",\n displayName: \"Given name\",\n type: o.optional({ type: o.string({}) }),\n },\n {\n name: \"familyName\",\n displayName: \"Family name\",\n type: o.optional({ type: o.string({}) }),\n },\n {\n name: \"email\",\n displayName: \"Email\",\n type: o.optional({ type: o.string({}) }),\n },\n {\n name: \"profilePicture\",\n displayName: \"Profile picture\",\n type: o.optional({\n type: o.attachment({\n constraint: {\n content: o.AttachmentContentConstraint.image({\n // Accepted types shown by the \"Edit profile picture\" file input in Foundry settings.\n mediaTypes: [\"image/png\", \"image/jpeg\", \"image/gif\", \"image/svg+xml\"],\n }),\n },\n }),\n }),\n },\n ],\n};\n\nconst PROFILE_PICTURE_PREFIX = \"foundry-user-profile:\";\nconst PROFILE_PICTURE_CACHE_WINDOW_MS = 60 * 60 * 1_000;\n\n/**\n * Foundry exposes profile pictures through a mutable endpoint but does not\n * include presence or version metadata on User records. The hourly bucket acts\n * as a pseudo-version so BlobManager can retain its immutable-ID cache model:\n * user rows loaded in the same hour share cached content, while a later row\n * load produces a new ID and refetches the picture. Missing pictures are stored\n * as empty blobs for that bucket and retried when the ID rotates.\n */\nexport function foundryUserProfilePictureAttachment(userId: string): v.attachment {\n const cacheBucket = Math.floor(Date.now() / PROFILE_PICTURE_CACHE_WINDOW_MS);\n return {\n id: `${PROFILE_PICTURE_PREFIX}${encodeURIComponent(userId)}:${cacheBucket}`,\n };\n}\n\nexport function decodeFoundryUserProfilePictureAttachment(attachmentId: string): string | undefined {\n if (!attachmentId.startsWith(PROFILE_PICTURE_PREFIX)) {\n return;\n }\n const encoded = attachmentId.slice(PROFILE_PICTURE_PREFIX.length);\n const separator = encoded.lastIndexOf(\":\");\n if (separator >= 0 && !/^\\d+$/.test(encoded.slice(separator + 1))) {\n return;\n }\n try {\n return decodeURIComponent(separator < 0 ? encoded : encoded.slice(0, separator));\n } catch {\n return;\n }\n}\n\nexport function createFoundryUserObjectType(objectType: string, lens: Lens): ObjectTypeDef {\n return applyLensToObjectType(foundryUserObjectType, lens, {\n name: objectType,\n });\n}\n"],"mappings":";;AAGA,MAAa,wBAAuC;CAChD,MAAM;CACN,aAAa;CACb,mBAAmB;CACnB,YAAY;CACZ,YAAY;EACR;GAAE,MAAM;GAAM,aAAa;GAAM,MAAM,EAAE,OAAO,CAAC,CAAC;EAAE;EACpD;GAAE,MAAM;GAAY,aAAa;GAAY,MAAM,EAAE,OAAO,CAAC,CAAC;EAAE;EAChE;GACI,MAAM;GACN,aAAa;GACb,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;EAC3C;EACA;GACI,MAAM;GACN,aAAa;GACb,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;EAC3C;EACA;GACI,MAAM;GACN,aAAa;GACb,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;EAC3C;EACA;GACI,MAAM;GACN,aAAa;GACb,MAAM,EAAE,SAAS,EACb,MAAM,EAAE,WAAW,EACf,YAAY,EACR,SAAS,EAAE,4BAA4B,MAAM,EAEzC,YAAY;IAAC;IAAa;IAAc;IAAa;GAAe,EACxE,CAAC,EACL,EACJ,CAAC,EACL,CAAC;EACL;CACJ;AACJ;AAEA,MAAM,yBAAyB;AAC/B,MAAM,kCAAkC;;;;;;;;;AAUxC,SAAgB,oCAAoC,QAA8B;CAC9E,MAAM,cAAc,KAAK,MAAM,KAAK,IAAI,IAAI,+BAA+B;CAC3E,OAAO,EACH,IAAI,GAAG,yBAAyB,mBAAmB,MAAM,EAAE,GAAG,cAClE;AACJ;AAEA,SAAgB,0CAA0C,cAA0C;CAChG,IAAI,CAAC,aAAa,WAAW,sBAAsB,GAC/C;CAEJ,MAAM,UAAU,aAAa,MAAM,EAA6B;CAChE,MAAM,YAAY,QAAQ,YAAY,GAAG;CACzC,IAAI,aAAa,KAAK,CAAC,QAAQ,KAAK,QAAQ,MAAM,YAAY,CAAC,CAAC,GAC5D;CAEJ,IAAI;EACA,OAAO,mBAAmB,YAAY,IAAI,UAAU,QAAQ,MAAM,GAAG,SAAS,CAAC;CACnF,QAAQ;EACJ;CACJ;AACJ;AAEA,SAAgB,4BAA4B,YAAoB,MAA2B;CACvF,OAAO,sBAAsB,uBAAuB,MAAM,EACtD,MAAM,WACV,CAAC;AACL"}
|
|
1
|
+
{"version":3,"file":"foundryUser.js","names":[],"sources":["../../src/users/foundryUser.ts"],"sourcesContent":["import { applyLensToObjectType, o, type Lens, type ObjectTypeDef } from \"@party-stack/ontology-spec\";\nimport type * as v from \"@party-stack/ontology-spec/values\";\n\nexport const foundryUserObjectType: ObjectTypeDef = {\n name: \"FoundryUser\",\n displayName: \"Foundry user\",\n pluralDisplayName: \"Foundry users\",\n primaryKey: \"id\",\n properties: [\n { name: \"id\", displayName: \"ID\", type: o.string({}) },\n { name: \"username\", displayName: \"Username\", type: o.string({}) },\n {\n name: \"givenName\",\n displayName: \"Given name\",\n type: o.optional({ type: o.string({}) }),\n },\n {\n name: \"familyName\",\n displayName: \"Family name\",\n type: o.optional({ type: o.string({}) }),\n },\n {\n name: \"email\",\n displayName: \"Email\",\n type: o.optional({ type: o.string({}) }),\n },\n {\n name: \"profilePicture\",\n displayName: \"Profile picture\",\n type: o.optional({\n type: o.attachment({\n constraint: {\n content: o.AttachmentContentConstraint.image({\n // Accepted types shown by the \"Edit profile picture\" file input in Foundry settings.\n mediaTypes: [\"image/png\", \"image/jpeg\", \"image/gif\", \"image/svg+xml\"],\n }),\n },\n }),\n }),\n },\n ],\n};\n\nconst PROFILE_PICTURE_PREFIX = \"foundry-user-profile:\";\nconst PROFILE_PICTURE_CACHE_WINDOW_MS = 60 * 60 * 1_000;\n\n/**\n * Foundry exposes profile pictures through a mutable endpoint but does not\n * include presence or version metadata on User records. The hourly bucket acts\n * as a pseudo-version so BlobManager can retain its immutable-ID cache model:\n * user rows loaded in the same hour share cached content, while a later row\n * load produces a new ID and refetches the picture. Missing pictures are stored\n * as empty blobs for that bucket and retried when the ID rotates.\n */\nexport function foundryUserProfilePictureAttachment(userId: string): v.attachment {\n const cacheBucket = Math.floor(Date.now() / PROFILE_PICTURE_CACHE_WINDOW_MS);\n return {\n id: `${PROFILE_PICTURE_PREFIX}${encodeURIComponent(userId)}:${cacheBucket}`,\n };\n}\n\nexport function decodeFoundryUserProfilePictureAttachment(attachmentId: string): string | undefined {\n if (!attachmentId.startsWith(PROFILE_PICTURE_PREFIX)) {\n return;\n }\n const encoded = attachmentId.slice(PROFILE_PICTURE_PREFIX.length);\n const separator = encoded.lastIndexOf(\":\");\n if (separator >= 0 && !/^\\d+$/.test(encoded.slice(separator + 1))) {\n return;\n }\n try {\n return decodeURIComponent(separator < 0 ? encoded : encoded.slice(0, separator));\n } catch {\n return;\n }\n}\n\nexport function createFoundryUserObjectType(objectType: string, lens: Lens): ObjectTypeDef {\n return applyLensToObjectType(foundryUserObjectType, lens, {\n name: objectType,\n });\n}\n"],"mappings":";;AAGA,MAAa,wBAAuC;CAChD,MAAM;CACN,aAAa;CACb,mBAAmB;CACnB,YAAY;CACZ,YAAY;EACR;GAAE,MAAM;GAAM,aAAa;GAAM,MAAM,EAAE,OAAO,CAAC,CAAC;EAAE;EACpD;GAAE,MAAM;GAAY,aAAa;GAAY,MAAM,EAAE,OAAO,CAAC,CAAC;EAAE;EAChE;GACI,MAAM;GACN,aAAa;GACb,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;EAC3C;EACA;GACI,MAAM;GACN,aAAa;GACb,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;EAC3C;EACA;GACI,MAAM;GACN,aAAa;GACb,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;EAC3C;EACA;GACI,MAAM;GACN,aAAa;GACb,MAAM,EAAE,SAAS,EACb,MAAM,EAAE,WAAW,EACf,YAAY,EACR,SAAS,EAAE,4BAA4B,MAAM,EAEzC,YAAY;IAAC;IAAa;IAAc;IAAa;GAAe,EACxE,CAAC,EACL,EACJ,CAAC,EACL,CAAC;EACL;CACJ;AACJ;AAEA,MAAM,yBAAyB;AAC/B,MAAM,kCAAkC;;;;;;;;;AAUxC,SAAgB,oCAAoC,QAA8B;CAC9E,MAAM,cAAc,KAAK,MAAM,KAAK,IAAI,IAAI,+BAA+B;CAC3E,OAAO,EACH,IAAI,GAAG,yBAAyB,mBAAmB,MAAM,EAAE,GAAG,cAClE;AACJ;AAEA,SAAgB,0CAA0C,cAA0C;CAChG,IAAI,CAAC,aAAa,WAAW,sBAAsB,GAC/C;CAEJ,MAAM,UAAU,aAAa,MAAM,EAA6B;CAChE,MAAM,YAAY,QAAQ,YAAY,GAAG;CACzC,IAAI,aAAa,KAAK,CAAC,QAAQ,KAAK,QAAQ,MAAM,YAAY,CAAC,CAAC,GAC5D;CAEJ,IAAI;EACA,OAAO,mBAAmB,YAAY,IAAI,UAAU,QAAQ,MAAM,GAAG,SAAS,CAAC;CACnF,QAAQ;EACJ;CACJ;AACJ;AAEA,SAAgB,4BAA4B,YAAoB,MAA2B;CACvF,OAAO,sBAAsB,uBAAuB,MAAM,EACtD,MAAM,WACV,CAAC;AACL"}
|
package/lib/users/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { foundryAdminOntology, makeFoundryAdminBackend } from "./admin.js";
|
|
2
2
|
import { createFoundryUsersIntegration } from "./createFoundryUsersIntegration.js";
|
|
3
3
|
import { createFoundryUserObjectType, decodeFoundryUserProfilePictureAttachment, foundryUserObjectType, foundryUserProfilePictureAttachment } from "./foundryUser.js";
|
|
4
|
-
|
|
5
|
-
export { UserCollectionOpts, convertQuery, createFoundryAdminOntologyRoute, createFoundryUserObjectType, createFoundryUsersIntegration, decodeFoundryUserProfilePictureAttachment, foundryAdminOntology, foundryUserObjectType, foundryUserProfilePictureAttachment, userCollectionOptions };
|
|
4
|
+
export { createFoundryUserObjectType, createFoundryUsersIntegration, decodeFoundryUserProfilePictureAttachment, foundryAdminOntology, foundryUserObjectType, foundryUserProfilePictureAttachment, makeFoundryAdminBackend };
|
package/lib/users/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { createFoundryUserObjectType, decodeFoundryUserProfilePictureAttachment, foundryUserObjectType, foundryUserProfilePictureAttachment } from "./foundryUser.js";
|
|
2
|
-
import { convertQuery, userCollectionOptions } from "./userCollectionOptions.js";
|
|
3
2
|
import { createFoundryUsersIntegration } from "./createFoundryUsersIntegration.js";
|
|
4
|
-
import {
|
|
5
|
-
export {
|
|
3
|
+
import { foundryAdminOntology, makeFoundryAdminBackend } from "./admin.js";
|
|
4
|
+
export { createFoundryUserObjectType, createFoundryUsersIntegration, decodeFoundryUserProfilePictureAttachment, foundryAdminOntology, foundryUserObjectType, foundryUserProfilePictureAttachment, makeFoundryAdminBackend };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Client } from "@party-stack/foundry-client";
|
|
2
|
+
import { BackendSnapshot } from "@party-stack/ontology-backend";
|
|
3
|
+
import { Lens } from "@party-stack/ontology-spec";
|
|
4
|
+
import { Query } from "@party-stack/ontology-storage";
|
|
5
|
+
//#region src/users/loadUserSubset.d.ts
|
|
6
|
+
export declare function loadUserSubset(client: Client, objectType: string, lens: Lens, query: Query, signal: AbortSignal): Promise<BackendSnapshot>;
|
|
7
|
+
//#endregion
|
|
8
|
+
//# sourceMappingURL=loadUserSubset.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadUserSubset.d.ts","names":[],"sources":["../../src/users/loadUserSubset.ts"],"mappings":";;;;;wBAmHsB,eAClB,QAAQ,QACR,oBACA,MAAM,MACN,OAAO,OACP,QAAQ,cACT,QAAQ"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { fromPagination, toArray } from "../utils/AsyncIterable.js";
|
|
2
|
+
import { foundryUserProfilePictureAttachment } from "./foundryUser.js";
|
|
3
|
+
import { chunk } from "../utils/chunk.js";
|
|
4
|
+
import { Redacted, Schema } from "effect";
|
|
5
|
+
import { BackendError } from "@party-stack/ontology-backend";
|
|
6
|
+
import { applyLensToObject, mapTargetPathToSourceWithLens } from "@party-stack/ontology-spec";
|
|
7
|
+
import { objectSubset } from "@party-stack/ontology-backend/subset";
|
|
8
|
+
import { evaluateQuery } from "@party-stack/ontology-storage";
|
|
9
|
+
import { isField } from "@party-stack/ontology-storage/tables";
|
|
10
|
+
import { Users } from "@osdk/foundry.admin";
|
|
11
|
+
//#region src/users/loadUserSubset.ts
|
|
12
|
+
const UserIdentity = Schema.Struct({ id: Schema.String });
|
|
13
|
+
const UserPage = Schema.Struct({
|
|
14
|
+
data: Schema.Array(UserIdentity),
|
|
15
|
+
nextPageToken: Schema.optional(Schema.String)
|
|
16
|
+
});
|
|
17
|
+
const UserBatch = Schema.Struct({ data: Schema.Record(Schema.String, UserIdentity) });
|
|
18
|
+
function checked(schema, value) {
|
|
19
|
+
try {
|
|
20
|
+
Schema.decodeUnknownSync(schema)(value);
|
|
21
|
+
return value;
|
|
22
|
+
} catch (cause) {
|
|
23
|
+
throw new BackendError({
|
|
24
|
+
operation: "foundry.users.loadSubset",
|
|
25
|
+
kind: "InvalidResponse",
|
|
26
|
+
message: "Foundry returned an invalid user response.",
|
|
27
|
+
retryable: false,
|
|
28
|
+
cause: Redacted.make(cause)
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** Choose only a safe candidate set. Every response is checked against the full query. */
|
|
33
|
+
function select(predicate, lens, path = []) {
|
|
34
|
+
if (predicate.op === "and" || predicate.op === "or") {
|
|
35
|
+
const children = predicate.predicates.map((child, index) => select(child, lens, [...path, index]));
|
|
36
|
+
if (predicate.op === "and") return children.find((child) => child?.type === "getBatch") ?? children.find(Boolean);
|
|
37
|
+
if (children.some((child) => !child)) return;
|
|
38
|
+
if (children.every((child) => child?.type === "getBatch")) return {
|
|
39
|
+
type: "getBatch",
|
|
40
|
+
ids: [...new Set(children.flatMap((child) => child.ids))],
|
|
41
|
+
paths: children.flatMap((child) => child.paths)
|
|
42
|
+
};
|
|
43
|
+
const first = children[0];
|
|
44
|
+
if (first?.type === "search" && children.every((child) => child?.type === "search" && child.term === first.term)) return {
|
|
45
|
+
...first,
|
|
46
|
+
paths: children.flatMap((child) => child.paths)
|
|
47
|
+
};
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (predicate.op === "not") return;
|
|
51
|
+
const left = predicate.op === "eq" && !isField(predicate.left) && isField(predicate.right) ? predicate.right : predicate.left;
|
|
52
|
+
const right = predicate.op === "eq" && left === predicate.right ? predicate.left : predicate.op !== "in" ? predicate.right : void 0;
|
|
53
|
+
if (!isField(left)) return;
|
|
54
|
+
const source = mapTargetPathToSourceWithLens(left.path, lens).join(".");
|
|
55
|
+
if (source === "id") {
|
|
56
|
+
if (predicate.op === "eq" && typeof right === "string") return {
|
|
57
|
+
type: "getBatch",
|
|
58
|
+
ids: [right],
|
|
59
|
+
paths: [path]
|
|
60
|
+
};
|
|
61
|
+
if (predicate.op === "in" && predicate.values.every((value) => typeof value === "string")) return {
|
|
62
|
+
type: "getBatch",
|
|
63
|
+
ids: [...new Set(predicate.values)],
|
|
64
|
+
paths: [path]
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
if ((predicate.op === "like" || predicate.op === "ilike") && typeof right === "string" && [
|
|
68
|
+
"username",
|
|
69
|
+
"givenName",
|
|
70
|
+
"familyName"
|
|
71
|
+
].includes(source)) {
|
|
72
|
+
const term = right.slice(0, -1);
|
|
73
|
+
if (right.endsWith("%") && term.length > 0 && !/[%_\\]/.test(term)) return {
|
|
74
|
+
type: "search",
|
|
75
|
+
term,
|
|
76
|
+
paths: [path]
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function placements(predicate, selection) {
|
|
81
|
+
const selected = new Set(selection?.paths.map((path) => JSON.stringify(path)));
|
|
82
|
+
const result = [];
|
|
83
|
+
const visit = (predicate, path) => {
|
|
84
|
+
if (predicate.op === "and" || predicate.op === "or") predicate.predicates.forEach((child, index) => visit(child, [...path, index]));
|
|
85
|
+
else if (predicate.op === "not") visit(predicate.predicate, [...path, 0]);
|
|
86
|
+
else result.push({
|
|
87
|
+
path,
|
|
88
|
+
execution: selected.has(JSON.stringify(path)) ? selection?.type === "getBatch" ? "source" : "candidate" : "engine"
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
if (predicate) visit(predicate, []);
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
async function loadUserSubset(client, objectType, lens, query, signal) {
|
|
95
|
+
signal.throwIfAborted();
|
|
96
|
+
evaluateQuery([], query);
|
|
97
|
+
if (query.limit === 0) return {
|
|
98
|
+
rows: [],
|
|
99
|
+
complete: true,
|
|
100
|
+
fetchedRows: 0
|
|
101
|
+
};
|
|
102
|
+
const requestClient = {
|
|
103
|
+
...client,
|
|
104
|
+
fetch: (input, init) => client.fetch(input, {
|
|
105
|
+
...init,
|
|
106
|
+
signal: init?.signal ? AbortSignal.any([signal, init.signal]) : signal
|
|
107
|
+
})
|
|
108
|
+
};
|
|
109
|
+
const selection = query.where ? select(query.where, lens) : void 0;
|
|
110
|
+
const users = [];
|
|
111
|
+
const batches = selection?.type === "getBatch" ? chunk(selection.ids, 500) : void 0;
|
|
112
|
+
if (batches) for (const ids of batches) {
|
|
113
|
+
signal.throwIfAborted();
|
|
114
|
+
const response = await Users.getBatch(requestClient, ids.map((userId) => ({ userId })));
|
|
115
|
+
checked(UserBatch, response);
|
|
116
|
+
users.push(...Object.values(response.data));
|
|
117
|
+
}
|
|
118
|
+
else users.push(...await toArray(fromPagination(async (_pageSize, pageToken) => {
|
|
119
|
+
signal.throwIfAborted();
|
|
120
|
+
const page = selection?.type === "search" ? await Users.search(requestClient, {
|
|
121
|
+
where: {
|
|
122
|
+
type: "queryString",
|
|
123
|
+
value: selection.term
|
|
124
|
+
},
|
|
125
|
+
pageToken
|
|
126
|
+
}) : await Users.list(requestClient, { pageToken });
|
|
127
|
+
return checked(UserPage, page);
|
|
128
|
+
}, (page) => page.nextPageToken, (page) => page.data, 500)));
|
|
129
|
+
signal.throwIfAborted();
|
|
130
|
+
return {
|
|
131
|
+
rows: users.map((user) => ({
|
|
132
|
+
key: user.id,
|
|
133
|
+
value: applyLensToObject({
|
|
134
|
+
...user,
|
|
135
|
+
profilePicture: foundryUserProfilePictureAttachment(user.id)
|
|
136
|
+
}, lens)
|
|
137
|
+
})),
|
|
138
|
+
fulfilledSubset: objectSubset(objectType, selection ? { where: query.where } : {}),
|
|
139
|
+
complete: true,
|
|
140
|
+
fetchedRows: users.length,
|
|
141
|
+
pushdown: {
|
|
142
|
+
source: "Foundry users",
|
|
143
|
+
predicates: placements(query.where, selection),
|
|
144
|
+
sorting: query.orderBy?.length ? "engine" : "none",
|
|
145
|
+
pagination: query.limit !== void 0 || query.offset !== void 0 || query.after ? "engine" : "none",
|
|
146
|
+
rechecksFilter: Boolean(query.where),
|
|
147
|
+
native: {
|
|
148
|
+
language: "json",
|
|
149
|
+
text: JSON.stringify(batches ? {
|
|
150
|
+
operation: "Users.getBatch",
|
|
151
|
+
batches: batches.map((ids) => ids.map((userId) => ({ userId })))
|
|
152
|
+
} : selection?.type === "search" ? {
|
|
153
|
+
operation: "Users.search",
|
|
154
|
+
where: {
|
|
155
|
+
type: "queryString",
|
|
156
|
+
value: selection.term
|
|
157
|
+
}
|
|
158
|
+
} : { operation: "Users.list" }, null, 2)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
//#endregion
|
|
164
|
+
export { loadUserSubset };
|
|
165
|
+
|
|
166
|
+
//# sourceMappingURL=loadUserSubset.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadUserSubset.js","names":["AsyncIterable.toArray","AsyncIterable.fromPagination"],"sources":["../../src/users/loadUserSubset.ts"],"sourcesContent":["import { Users, type User } from \"@osdk/foundry.admin\";\nimport { BackendError } from \"@party-stack/ontology-backend\";\nimport { objectSubset } from \"@party-stack/ontology-backend/subset\";\nimport { applyLensToObject, mapTargetPathToSourceWithLens, type Lens } from \"@party-stack/ontology-spec\";\nimport { evaluateQuery, type Predicate, type Query } from \"@party-stack/ontology-storage\";\nimport { isField } from \"@party-stack/ontology-storage/tables\";\nimport { Schema, Redacted } from \"effect\";\nimport * as AsyncIterable from \"../utils/AsyncIterable.js\";\nimport { chunk } from \"../utils/chunk.js\";\nimport { foundryUserProfilePictureAttachment } from \"./foundryUser.js\";\nimport type { Client } from \"@party-stack/foundry-client\";\nimport type { BackendSnapshot, SourceQueryPlan } from \"@party-stack/ontology-backend\";\n\nconst UserIdentity = Schema.Struct({ id: Schema.String });\nconst UserPage = Schema.Struct({\n data: Schema.Array(UserIdentity),\n nextPageToken: Schema.optional(Schema.String),\n});\nconst UserBatch = Schema.Struct({ data: Schema.Record(Schema.String, UserIdentity) });\nfunction checked<A>(schema: Schema.Decoder<unknown>, value: A): A {\n try {\n Schema.decodeUnknownSync(schema)(value);\n return value;\n } catch (cause) {\n throw new BackendError({\n operation: \"foundry.users.loadSubset\",\n kind: \"InvalidResponse\",\n message: \"Foundry returned an invalid user response.\",\n retryable: false,\n cause: Redacted.make(cause),\n });\n }\n}\n\ntype Selection =\n | { type: \"getBatch\"; ids: string[]; paths: number[][] }\n | { type: \"search\"; term: string; paths: number[][] };\n\n/** Choose only a safe candidate set. Every response is checked against the full query. */\nfunction select(predicate: Predicate, lens: Lens, path: number[] = []): Selection | undefined {\n if (predicate.op === \"and\" || predicate.op === \"or\") {\n const children = predicate.predicates.map((child, index) => select(child, lens, [...path, index]));\n if (predicate.op === \"and\")\n return children.find((child) => child?.type === \"getBatch\") ?? children.find(Boolean);\n if (children.some((child) => !child)) return;\n if (children.every((child) => child?.type === \"getBatch\"))\n return {\n type: \"getBatch\",\n ids: [...new Set(children.flatMap((child) => child.ids))],\n paths: children.flatMap((child) => child.paths),\n };\n const first = children[0];\n if (\n first?.type === \"search\" &&\n children.every((child) => child?.type === \"search\" && child.term === first.term)\n )\n return { ...first, paths: children.flatMap((child) => child!.paths) };\n return;\n }\n if (predicate.op === \"not\") return;\n const left =\n predicate.op === \"eq\" && !isField(predicate.left) && isField(predicate.right)\n ? predicate.right\n : predicate.left;\n const right =\n predicate.op === \"eq\" && left === predicate.right\n ? predicate.left\n : predicate.op !== \"in\"\n ? predicate.right\n : undefined;\n if (!isField(left)) return;\n const source = mapTargetPathToSourceWithLens(left.path, lens).join(\".\");\n if (source === \"id\") {\n if (predicate.op === \"eq\" && typeof right === \"string\")\n return { type: \"getBatch\", ids: [right], paths: [path] };\n if (predicate.op === \"in\" && predicate.values.every((value) => typeof value === \"string\"))\n return { type: \"getBatch\", ids: [...new Set(predicate.values)], paths: [path] };\n }\n if (\n (predicate.op === \"like\" || predicate.op === \"ilike\") &&\n typeof right === \"string\" &&\n [\"username\", \"givenName\", \"familyName\"].includes(source)\n ) {\n // Admin search is case-insensitive prefix matching across all name fields.\n // Complex patterns must not become a narrower, incorrect search term.\n const term = right.slice(0, -1);\n if (right.endsWith(\"%\") && term.length > 0 && !/[%_\\\\]/.test(term))\n return { type: \"search\", term, paths: [path] };\n }\n}\n\nfunction placements(\n predicate: Predicate | undefined,\n selection: Selection | undefined\n): SourceQueryPlan[\"predicates\"] {\n const selected = new Set(selection?.paths.map((path) => JSON.stringify(path)));\n const result: SourceQueryPlan[\"predicates\"][number][] = [];\n const visit = (predicate: Predicate, path: number[]) => {\n if (predicate.op === \"and\" || predicate.op === \"or\")\n predicate.predicates.forEach((child, index) => visit(child, [...path, index]));\n else if (predicate.op === \"not\") visit(predicate.predicate, [...path, 0]);\n else\n result.push({\n path,\n execution: selected.has(JSON.stringify(path))\n ? selection?.type === \"getBatch\"\n ? \"source\"\n : \"candidate\"\n : \"engine\",\n });\n };\n if (predicate) visit(predicate, []);\n return result;\n}\n\nexport async function loadUserSubset(\n client: Client,\n objectType: string,\n lens: Lens,\n query: Query,\n signal: AbortSignal\n): Promise<BackendSnapshot> {\n signal.throwIfAborted();\n evaluateQuery([], query);\n if (query.limit === 0) return { rows: [], complete: true, fetchedRows: 0 };\n const requestClient = {\n ...client,\n fetch: (input: RequestInfo | URL, init?: RequestInit) =>\n client.fetch(input, {\n ...init,\n signal: init?.signal ? AbortSignal.any([signal, init.signal]) : signal,\n }),\n };\n const selection = query.where ? select(query.where, lens) : undefined;\n const users: User[] = [];\n const batches = selection?.type === \"getBatch\" ? chunk(selection.ids, 500) : undefined;\n if (batches) {\n for (const ids of batches) {\n signal.throwIfAborted();\n const response = await Users.getBatch(\n requestClient,\n ids.map((userId) => ({ userId }))\n );\n checked(UserBatch, response);\n users.push(...Object.values(response.data));\n }\n } else {\n users.push(\n ...(await AsyncIterable.toArray(\n AsyncIterable.fromPagination(\n async (_pageSize, pageToken: string | undefined) => {\n signal.throwIfAborted();\n const page =\n selection?.type === \"search\"\n ? await Users.search(requestClient, {\n where: { type: \"queryString\", value: selection.term },\n pageToken,\n })\n : await Users.list(requestClient, { pageToken });\n return checked(UserPage, page);\n },\n (page) => page.nextPageToken,\n (page) => page.data,\n 500\n )\n ))\n );\n }\n signal.throwIfAborted();\n const rows = users.map((user) => ({\n key: user.id,\n value: applyLensToObject(\n { ...user, profilePicture: foundryUserProfilePictureAttachment(user.id) },\n lens\n ),\n }));\n return {\n rows,\n fulfilledSubset: objectSubset(objectType, selection ? { where: query.where } : {}),\n complete: true,\n fetchedRows: users.length,\n pushdown: {\n source: \"Foundry users\",\n predicates: placements(query.where, selection),\n sorting: query.orderBy?.length ? \"engine\" : \"none\",\n pagination:\n query.limit !== undefined || query.offset !== undefined || query.after ? \"engine\" : \"none\",\n rechecksFilter: Boolean(query.where),\n native: {\n language: \"json\",\n text: JSON.stringify(\n batches\n ? {\n operation: \"Users.getBatch\",\n batches: batches.map((ids) => ids.map((userId) => ({ userId }))),\n }\n : selection?.type === \"search\"\n ? {\n operation: \"Users.search\",\n where: { type: \"queryString\", value: selection.term },\n }\n : { operation: \"Users.list\" },\n null,\n 2\n ),\n },\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region src/utils/AsyncIterable.d.ts
|
|
2
2
|
export declare function toArray<T>(asyncIterable: AsyncIterable<T>): Promise<T[]>;
|
|
3
3
|
export declare function fromBatches<T, R>(values: readonly T[], getBatch: (batch: T[]) => Promise<readonly R[]>, batchSize: number): AsyncIterable<R>;
|
|
4
|
-
export declare function fromPagination<C extends string | number, P, T>(getPage: (pageSize: number, pageToken?: C) => Promise<P>, getPageToken: (page: P) => C | undefined, getElements: (page: P) => T[] | Promise<T[]>, defaultPageSize: number, limit?: number): AsyncIterable<T>;
|
|
4
|
+
export declare function fromPagination<C extends string | number, P, T>(getPage: (pageSize: number, pageToken?: C) => Promise<P>, getPageToken: (page: P) => C | undefined, getElements: (page: P) => readonly T[] | Promise<readonly T[]>, defaultPageSize: number, limit?: number): AsyncIterable<T>;
|
|
5
5
|
//#endregion
|
|
6
6
|
//# sourceMappingURL=AsyncIterable.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AsyncIterable.d.ts","names":[],"sources":["../../src/utils/AsyncIterable.ts"],"mappings":";
|
|
1
|
+
{"version":3,"file":"AsyncIterable.d.ts","names":[],"sources":["../../src/utils/AsyncIterable.ts"],"mappings":";wBAKsB,QAAQ,GAAG,eAAe,cAAc,KAAK,QAAQ;wBAQpD,YAAY,GAAG,GAClC,iBAAiB,KACjB,WAAW,OAAO,QAAQ,iBAAiB,MAC3C,oBACD,cAAc;wBAYM,eAAe,2BAA2B,GAAG,GAChE,UAAU,kBAAkB,YAAY,MAAM,QAAQ,IACtD,eAAe,MAAM,MAAM,eAC3B,cAAc,MAAM,eAAe,MAAM,iBAAiB,MAC1D,yBACA,iBACD,cAAc"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { BackendError } from "@party-stack/ontology-backend";
|
|
1
2
|
//#region src/utils/AsyncIterable.ts
|
|
2
3
|
async function toArray(asyncIterable) {
|
|
3
4
|
const result = [];
|
|
@@ -12,10 +13,20 @@ async function* fromBatches(values, getBatch, batchSize) {
|
|
|
12
13
|
}
|
|
13
14
|
}
|
|
14
15
|
async function* fromPagination(getPage, getPageToken, getElements, defaultPageSize, limit = Infinity) {
|
|
16
|
+
const visited = /* @__PURE__ */ new Set();
|
|
15
17
|
let pageToken = void 0;
|
|
16
18
|
let hasMore = true;
|
|
17
19
|
let count = 0;
|
|
18
20
|
while (hasMore && count < limit) {
|
|
21
|
+
if (pageToken !== void 0) {
|
|
22
|
+
if (visited.has(pageToken)) throw new BackendError({
|
|
23
|
+
operation: "provider.pagination",
|
|
24
|
+
kind: "InvalidResponse",
|
|
25
|
+
message: "The provider repeated a pagination cursor.",
|
|
26
|
+
retryable: false
|
|
27
|
+
});
|
|
28
|
+
visited.add(pageToken);
|
|
29
|
+
}
|
|
19
30
|
const page = await getPage(Math.min(limit - count, defaultPageSize), pageToken);
|
|
20
31
|
const elements = await getElements(page);
|
|
21
32
|
for (const element of elements) yield element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AsyncIterable.js","names":[],"sources":["../../src/utils/AsyncIterable.ts"],"sourcesContent":["// TODO: move to utils\n\n// Replace later with https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fromAsync\nexport async function toArray<T>(asyncIterable: AsyncIterable<T>): Promise<T[]> {\n const result = [];\n for await (const element of asyncIterable) {\n result.push(element);\n }\n return result;\n}\n\nexport async function* fromBatches<T, R>(\n values: readonly T[],\n getBatch: (batch: T[]) => Promise<readonly R[]>,\n batchSize: number\n): AsyncIterable<R> {\n if (!Number.isInteger(batchSize) || batchSize <= 0) {\n throw new RangeError(\"Batch size must be a positive integer.\");\n }\n for (let index = 0; index < values.length; index += batchSize) {\n const results = await getBatch(values.slice(index, index + batchSize));\n for (const result of results) {\n yield result;\n }\n }\n}\n\nexport async function* fromPagination<C extends string | number, P, T>(\n getPage: (pageSize: number, pageToken?: C) => Promise<P>,\n getPageToken: (page: P) => C | undefined,\n getElements: (page: P) => T[] | Promise<T[]>,\n defaultPageSize: number,\n limit: number = Infinity\n): AsyncIterable<T> {\n let pageToken: C | undefined = undefined;\n let hasMore = true;\n let count = 0;\n while (hasMore && count < limit) {\n const page = await getPage(Math.min(limit - count, defaultPageSize), pageToken);\n const elements = await getElements(page);\n for (const element of elements) {\n yield element;\n }\n count += elements.length;\n pageToken = getPageToken(page);\n if (pageToken === undefined) {\n hasMore = false;\n }\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"AsyncIterable.js","names":[],"sources":["../../src/utils/AsyncIterable.ts"],"sourcesContent":["import { BackendError } from \"@party-stack/ontology-backend\";\n\n// TODO: move to utils\n\n// Replace later with https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fromAsync\nexport async function toArray<T>(asyncIterable: AsyncIterable<T>): Promise<T[]> {\n const result = [];\n for await (const element of asyncIterable) {\n result.push(element);\n }\n return result;\n}\n\nexport async function* fromBatches<T, R>(\n values: readonly T[],\n getBatch: (batch: T[]) => Promise<readonly R[]>,\n batchSize: number\n): AsyncIterable<R> {\n if (!Number.isInteger(batchSize) || batchSize <= 0) {\n throw new RangeError(\"Batch size must be a positive integer.\");\n }\n for (let index = 0; index < values.length; index += batchSize) {\n const results = await getBatch(values.slice(index, index + batchSize));\n for (const result of results) {\n yield result;\n }\n }\n}\n\nexport async function* fromPagination<C extends string | number, P, T>(\n getPage: (pageSize: number, pageToken?: C) => Promise<P>,\n getPageToken: (page: P) => C | undefined,\n getElements: (page: P) => readonly T[] | Promise<readonly T[]>,\n defaultPageSize: number,\n limit: number = Infinity\n): AsyncIterable<T> {\n const visited = new Set<C>();\n let pageToken: C | undefined = undefined;\n let hasMore = true;\n let count = 0;\n while (hasMore && count < limit) {\n if (pageToken !== undefined) {\n if (visited.has(pageToken))\n throw new BackendError({\n operation: \"provider.pagination\",\n kind: \"InvalidResponse\",\n message: \"The provider repeated a pagination cursor.\",\n retryable: false,\n });\n visited.add(pageToken);\n }\n const page = await getPage(Math.min(limit - count, defaultPageSize), pageToken);\n const elements = await getElements(page);\n for (const element of elements) {\n yield element;\n }\n count += elements.length;\n pageToken = getPageToken(page);\n if (pageToken === undefined) {\n hasMore = false;\n }\n }\n}\n"],"mappings":";;AAKA,eAAsB,QAAW,eAA+C;CAC5E,MAAM,SAAS,CAAC;CAChB,WAAW,MAAM,WAAW,eACxB,OAAO,KAAK,OAAO;CAEvB,OAAO;AACX;AAEA,gBAAuB,YACnB,QACA,UACA,WACgB;CAChB,IAAI,CAAC,OAAO,UAAU,SAAS,KAAK,aAAa,GAC7C,MAAM,IAAI,WAAW,wCAAwC;CAEjE,KAAK,IAAI,QAAQ,GAAG,QAAQ,OAAO,QAAQ,SAAS,WAAW;EAC3D,MAAM,UAAU,MAAM,SAAS,OAAO,MAAM,OAAO,QAAQ,SAAS,CAAC;EACrE,KAAK,MAAM,UAAU,SACjB,MAAM;CAEd;AACJ;AAEA,gBAAuB,eACnB,SACA,cACA,aACA,iBACA,QAAgB,UACA;CAChB,MAAM,0BAAU,IAAI,IAAO;CAC3B,IAAI,YAA2B,KAAA;CAC/B,IAAI,UAAU;CACd,IAAI,QAAQ;CACZ,OAAO,WAAW,QAAQ,OAAO;EAC7B,IAAI,cAAc,KAAA,GAAW;GACzB,IAAI,QAAQ,IAAI,SAAS,GACrB,MAAM,IAAI,aAAa;IACnB,WAAW;IACX,MAAM;IACN,SAAS;IACT,WAAW;GACf,CAAC;GACL,QAAQ,IAAI,SAAS;EACzB;EACA,MAAM,OAAO,MAAM,QAAQ,KAAK,IAAI,QAAQ,OAAO,eAAe,GAAG,SAAS;EAC9E,MAAM,WAAW,MAAM,YAAY,IAAI;EACvC,KAAK,MAAM,WAAW,UAClB,MAAM;EAEV,SAAS,SAAS;EAClB,YAAY,aAAa,IAAI;EAC7B,IAAI,cAAc,KAAA,GACd,UAAU;CAElB;AACJ"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@party-stack/foundry-ontology",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"files": [
|
|
5
5
|
"lib"
|
|
6
6
|
],
|
|
@@ -21,6 +21,10 @@
|
|
|
21
21
|
"./config": {
|
|
22
22
|
"types": "./lib/config/index.d.ts",
|
|
23
23
|
"default": "./lib/config/index.js"
|
|
24
|
+
},
|
|
25
|
+
"./platform/collections": {
|
|
26
|
+
"types": "./lib/platformCollections.d.ts",
|
|
27
|
+
"default": "./lib/platformCollections.js"
|
|
24
28
|
}
|
|
25
29
|
},
|
|
26
30
|
"dependencies": {
|
|
@@ -31,36 +35,33 @@
|
|
|
31
35
|
"@osdk/foundry.core": "^2.77.0",
|
|
32
36
|
"@osdk/foundry.mediasets": "^2.77.0",
|
|
33
37
|
"@osdk/foundry.ontologies": "^2.77.0",
|
|
34
|
-
"@tanstack/store": "^0.11.0",
|
|
35
38
|
"change-case": "^5.4.4",
|
|
36
|
-
"
|
|
39
|
+
"effect": "^4.0.5",
|
|
37
40
|
"temporal-polyfill": "^0.3.0",
|
|
38
41
|
"zod": "^4.4.3",
|
|
39
|
-
"@party-stack/
|
|
40
|
-
"@party-stack/errors": "0.2.1",
|
|
42
|
+
"@party-stack/connect": "0.2.0",
|
|
41
43
|
"@party-stack/foundry-client": "0.3.1",
|
|
42
|
-
"@party-stack/foundry-object-set-watcher": "0.
|
|
44
|
+
"@party-stack/foundry-object-set-watcher": "0.6.0",
|
|
43
45
|
"@party-stack/icons-blueprint": "0.2.1",
|
|
44
|
-
"@party-stack/
|
|
45
|
-
"@party-stack/ontology": "0.
|
|
46
|
-
"@party-stack/
|
|
46
|
+
"@party-stack/ontology": "0.21.0",
|
|
47
|
+
"@party-stack/ontology-backend": "0.2.0",
|
|
48
|
+
"@party-stack/ontology-spec": "0.2.0",
|
|
49
|
+
"@party-stack/ontology-storage": "0.2.0",
|
|
50
|
+
"@party-stack/runtime": "0.5.0"
|
|
47
51
|
},
|
|
48
52
|
"devDependencies": {
|
|
49
|
-
"@tanstack/db": "0.
|
|
50
|
-
"@tanstack/query-db-collection": "1.4.4",
|
|
53
|
+
"@tanstack/db": "1.0.0-rc.1.4",
|
|
51
54
|
"@types/node": "^24.10.1",
|
|
52
55
|
"@types/react": "^19.3.0",
|
|
53
56
|
"react": "^19.3.0",
|
|
54
57
|
"ts-node": "^10.9.2",
|
|
55
58
|
"tsx": "^4.20.6",
|
|
56
59
|
"typescript": "~7.0.2",
|
|
60
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@1.2.0",
|
|
57
61
|
"vite-plus": "1.2.0",
|
|
58
|
-
"@party-stack/build-config": "0.
|
|
62
|
+
"@party-stack/build-config": "0.2.0"
|
|
59
63
|
},
|
|
60
64
|
"peerDependencies": {
|
|
61
|
-
"@tanstack/db": "0.14.0",
|
|
62
|
-
"@tanstack/query-core": "^5.102.8",
|
|
63
|
-
"@tanstack/query-db-collection": "1.4.4",
|
|
64
65
|
"react": "^18.0.0 || ^19.0.0"
|
|
65
66
|
}
|
|
66
67
|
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { SearchJsonQueryV2, SearchOrderByV2 } from "@osdk/foundry.ontologies";
|
|
2
|
-
import { LoadSubsetOptions } from "@tanstack/db";
|
|
3
|
-
//#region src/adapter/convertLoadSubsetOptions.d.ts
|
|
4
|
-
export declare function isAlwaysFalseFilter(filter: SearchJsonQueryV2 | undefined): boolean;
|
|
5
|
-
export declare function convertLoadSubsetFilter(filter: LoadSubsetOptions["where"]): SearchJsonQueryV2 | undefined;
|
|
6
|
-
export declare function convertLoadSubsetOrderBy(orderBy: LoadSubsetOptions["orderBy"]): SearchOrderByV2 | undefined;
|
|
7
|
-
//#endregion
|
|
8
|
-
//# sourceMappingURL=convertLoadSubsetOptions.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"convertLoadSubsetOptions.d.ts","names":[],"sources":["../../src/adapter/convertLoadSubsetOptions.ts"],"mappings":";;;wBA8JgB,oBAAoB,QAAQ;wBAI5B,wBAAwB,QAAQ,6BAA6B;wBA4F7D,yBAAyB,SAAS,+BAA+B"}
|