Initial commit

This commit is contained in:
root
2025-12-21 09:53:16 -05:00
committed by Sebastian Krupinski
commit a7ccac98a2
43 changed files with 6391 additions and 0 deletions
+161
View File
@@ -0,0 +1,161 @@
/**
* Collection-related type definitions for People Manager
*/
import type { ListFilter, ListSort, SourceSelector } from "./common";
/**
* Permission settings for a collection
*/
export interface CollectionPermissionInterface {
view: boolean;
create: boolean;
modify: boolean;
destroy: boolean;
share: boolean;
}
/**
* Permissions settings for multiple users in a collection
*/
export interface CollectionPermissionsInterface {
[userId: string]: CollectionPermissionInterface;
}
/**
* Role settings for a collection
*/
export interface CollectionRolesInterface {
individual?: boolean;
[roleType: string]: boolean | undefined;
}
/**
* Content type settings for a collection
*/
export interface CollectionContentsInterface {
individual?: boolean;
organization?: boolean;
group?: boolean;
[contentType: string]: boolean | undefined;
}
/**
* Represents a collection within a service
*/
export interface CollectionInterface {
'@type': string;
provider: string | null;
service: string | null;
in: number | string | null;
id: number | string | null;
label: string | null;
description: string | null;
priority: number | null;
visibility: string | null;
color: string | null;
enabled: boolean;
signature: string | null;
permissions: CollectionPermissionsInterface;
roles: CollectionRolesInterface;
contents: CollectionContentsInterface;
}
/**
* Request to collection list endpoint
*/
export interface CollectionListRequest {
sources?: SourceSelector;
filter?: ListFilter;
sort?: ListSort;
}
/**
* Response from collection list endpoint
*/
export interface CollectionListResponse {
[providerId: string]: {
[serviceId: string]: {
[collectionId: string]: CollectionInterface;
};
};
}
/**
* Request to collection extant endpoint
*/
export interface CollectionExtantRequest {
sources: SourceSelector;
}
/**
* Response from collection extant endpoint
*/
export interface CollectionExtantResponse {
[providerId: string]: {
[serviceId: string]: {
[collectionId: string]: boolean;
};
};
}
/**
* Request to collection fetch endpoint
*/
export interface CollectionFetchRequest {
provider: string;
service: string;
identifier: string | number;
}
/**
* Response from collection fetch endpoint
*/
export interface CollectionFetchResponse extends CollectionInterface {}
/**
* Request to collection create endpoint
*/
export interface CollectionCreateRequest {
provider: string;
service: string;
data: CollectionInterface;
options?: (string)[];
}
/**
* Response from collection create endpoint
*/
export interface CollectionCreateResponse extends CollectionInterface {}
/**
* Request to collection modify endpoint
*/
export interface CollectionModifyRequest {
provider: string;
service: string;
identifier: string | number;
data: CollectionInterface;
}
/**
* Response from collection modify endpoint
*/
export interface CollectionModifyResponse extends CollectionInterface {}
/**
* Request to collection destroy endpoint
*/
export interface CollectionDestroyRequest {
provider: string;
service: string;
identifier: string | number;
}
/**
* Response from collection destroy endpoint
*/
export interface CollectionDestroyResponse {
success: boolean;
}
+107
View File
@@ -0,0 +1,107 @@
/**
* Common types shared across People Manager services
*/
import type { FilterComparisonOperator, FilterConjunctionOperator } from './service';
/**
* Base API request envelope
*/
export interface ApiRequest<T = any> {
version: number;
transaction: string;
operation: string;
data: T;
user?: string;
}
/**
* Success response envelope
*/
export interface ApiSuccessResponse<T = any> {
version: number;
transaction: string;
operation: string;
status: 'success';
data: T;
}
/**
* Error response envelope
*/
export interface ApiErrorResponse {
version: number;
transaction: string;
operation: string;
status: 'error';
data: {
code: number;
message: string;
};
}
/**
* Combined response type
*/
export type ApiResponse<T = any> = ApiSuccessResponse<T> | ApiErrorResponse;
/**
* Source selector structure for hierarchical resource selection
* Structure: Provider -> Service -> Collection -> Entity
*
* Examples:
* - Simple boolean: { "local": true }
* - Nested services: { "system": { "personal": true, "recents": true } }
* - Collection IDs: { "system": { "personal": { "299": true, "176": true } } }
* - Entity IDs: { "system": { "personal": { "299": [1350, 1353, 5000] } } }
*/
export type SourceSelector = {
[provider: string]: boolean | ServiceSelector;
};
export type ServiceSelector = {
[service: string]: boolean | CollectionSelector;
};
export type CollectionSelector = {
[collection: string | number]: boolean | EntitySelector;
};
export type EntitySelector = (string | number)[];
/**
* Filter condition for building complex queries
*/
export interface FilterCondition {
attribute: string;
value: string | number | boolean | any[];
comparator?: FilterComparisonOperator;
conjunction?: FilterConjunctionOperator;
}
/**
* Filter criteria for list operations
* Can be simple key-value pairs or complex filter conditions
*/
export interface ListFilter {
label?: string;
[key: string]: any;
}
/**
* Sort options for list operations
*/
export interface ListSort {
[key: string]: boolean;
}
/**
* Range specification for pagination/limiting results
*/
export interface ListRange {
type: 'tally';
anchor: 'absolute' | 'relative';
position: number;
tally: number;
}
+159
View File
@@ -0,0 +1,159 @@
import type { ListFilter, ListRange, ListSort, SourceSelector } from './common';
import type { IndividualInterface } from './individual';
import type { OrganizationInterface } from './organization';
import type { GroupInterface } from './group';
/**
* Entity-related type definitions for People Manager
*/
/**
* Represents a person entity (contact)
*/
export interface EntityInterface {
'@type': string;
version: number;
in: string | number | null;
id: string | number | null;
createdOn: Date | null;
createdBy: string | null;
modifiedOn: Date | null;
modifiedBy: string | null;
signature: string | null;
data: IndividualInterface | OrganizationInterface | GroupInterface | null;
}
/**
* Request to entity list endpoint
*/
export interface EntityListRequest {
sources?: SourceSelector;
filter?: ListFilter;
sort?: ListSort;
range?: ListRange;
}
/**
* Response from entity list endpoint
*/
export interface EntityListResponse {
[providerId: string]: {
[serviceId: string]: {
[collectionId: string]: {
[entityId: string]: EntityInterface;
};
};
};
}
/**
* Request to entity delta endpoint
*/
export interface EntityDeltaRequest {
sources: SourceSelector;
}
/**
* Response from entity delta endpoint
*/
export interface EntityDeltaResponse {
[providerId: string]: {
[serviceId: string]: {
[collectionId: string]: {
signature: string;
created?: {
[entityId: string]: EntityInterface;
};
modified?: {
[entityId: string]: EntityInterface;
};
deleted?: string[]; // Array of deleted entity IDs
};
};
};
}
/**
* Request to entity extant endpoint
*/
export interface EntityExtantRequest {
sources: SourceSelector;
}
/**
* Response from entity extant endpoint
*/
export interface EntityExtantResponse {
[providerId: string]: {
[serviceId: string]: {
[collectionId: string]: {
[entityId: string]: boolean;
};
};
};
}
/**
* Request to entity fetch endpoint
*/
export interface EntityFetchRequest {
provider: string;
service: string;
collection: string | number;
identifiers: (string | number)[];
}
/**
* Response from entity fetch endpoint
*/
export interface EntityFetchResponse extends Record<string, EntityInterface> {}
/**
* Request to entity create endpoint
*/
export interface EntityCreateRequest {
provider: string;
service: string;
collection: string | number;
data: EntityInterface;
options?: (string)[];
}
/**
* Response from entity create endpoint
*/
export interface EntityCreateResponse extends EntityInterface {}
/**
* Request to entity modify endpoint
*/
export interface EntityModifyRequest {
provider: string;
service: string;
collection: string | number;
identifier: string | number;
data: EntityInterface;
options?: (string)[];
}
/**
* Response from entity modify endpoint
*/
export interface EntityModifyResponse extends EntityInterface {}
/**
* Request to entity destroy endpoint
*/
export interface EntityDestroyRequest {
provider: string;
service: string;
collection: string | number;
identifier: string | number;
}
/**
* Response from entity destroy endpoint
*/
export interface EntityDestroyResponse {
success: boolean;
}
+75
View File
@@ -0,0 +1,75 @@
/**
* Group-related type definitions
*/
/**
* Group name information
*/
export interface GroupName {
full: string | null;
sort: string | null;
aliases: string[];
}
/**
* Group member reference
*/
export interface GroupMember {
entityId: string | number | null;
role: string | null;
context: string | null;
priority: number | null;
}
/**
* Group virtual location
*/
export interface GroupVirtualLocation {
location: string | null;
label: string | null;
context: string | null;
priority: number | null;
}
/**
* Group media
*/
export interface GroupMedia {
type: string;
kind: string; // 'logo', 'photo'
uri: string;
mediaType?: string | null;
contexts?: string[] | null;
pref?: number | null;
label?: string | null;
}
/**
* Group note
*/
export interface GroupNote {
content: string | null;
date: Date | null;
authorUri: string | null;
authorName: string | null;
context: string | null;
priority: number | null;
}
/**
* Data for a group entity
*/
export interface GroupInterface {
type: string;
version: number;
urid: string | null;
created: Date | null;
modified: Date | null;
label: string | null;
names: GroupName;
members: Record<string, GroupMember>;
virtualLocations: Record<string, GroupVirtualLocation>;
media: Record<string, GroupMedia>;
tags: string[];
notes: Record<string, GroupNote>;
}
+12
View File
@@ -0,0 +1,12 @@
/**
* Central export point for all People Manager types
*/
export type * from './collection';
export type * from './common';
export type * from './entity';
export type * from './group';
export type * from './individual';
export type * from './organization';
export type * from './provider';
export type * from './service';
+176
View File
@@ -0,0 +1,176 @@
/**
* Serialized DateTime from backend
*/
/**
* Individual alias
*/
export interface IndividualAlias {
label: string | null;
context: string | null;
priority: number | null;
}
/**
* Individual name information
*/
export interface IndividualName {
family: string | null;
given: string | null;
additional: string | null;
prefix: string | null;
suffix: string | null;
phoneticFamily: string | null;
phoneticGiven: string | null;
phoneticAdditional: string | null;
aliases: IndividualAlias[];
}
/**
* Individual title
*/
export interface IndividualTitle {
kind: string | null; // 't' or 'r'
label: string | null;
relation: string | null;
context: string | null;
priority: number | null;
}
/**
* Individual anniversary
*/
export interface IndividualAnniversary {
type: string | null; // 'birth', 'death', 'nuptial'
when: Date | null;
location: string | null;
}
/**
* Individual physical location
*/
export interface IndividualPhysicalLocation {
box: string | null;
unit: string | null;
street: string | null;
locality: string | null;
region: string | null;
code: string | null;
country: string | null;
label: string | null;
coordinates: string | null;
timeZone: string | null;
context: string | null;
priority: number | null;
}
/**
* Individual phone
*/
export interface IndividualPhone {
number: string | null;
label: string | null;
context: string | null;
priority: number | null;
}
/**
* Individual email
*/
export interface IndividualEmail {
address: string | null;
context: string | null;
priority: number | null;
}
/**
* Individual virtual location
*/
export interface IndividualVirtualLocation {
location: string | null;
label: string | null;
context: string | null;
priority: number | null;
}
/**
* Individual organization
*/
export interface IndividualOrganization {
Label: string | null;
Units: string[];
sortName: string | null;
context: string | null;
priority: number | null;
}
/**
* Individual note
*/
export interface IndividualNote {
content: string | null;
date: Date | null;
authorUri: string | null;
authorName: string | null;
context: string | null;
priority: number | null;
}
/**
* Individual language
*/
export interface IndividualLanguage {
Data: string | null;
Id: string | null;
Priority: number | null;
Context: string | null;
}
/**
* Individual crypto
*/
export interface IndividualCrypto {
data: string | null;
type: string | null;
context: string | null;
priority: number | null;
}
/**
* Individual media
*/
export interface IndividualMedia {
type: string;
kind: string; // 'photo', 'sound', 'logo'
uri: string;
mediaType?: string | null;
contexts?: string[] | null;
pref?: number | null;
label?: string | null;
}
/**
* Data for an individual entity
*/
export interface IndividualInterface {
type: string;
version: number;
urid: string | null;
created: Date | null;
modified: Date | null;
label: string | null;
names: IndividualName;
titles: Record<string, IndividualTitle>;
anniversaries: IndividualAnniversary[];
physicalLocations: Record<string, IndividualPhysicalLocation>;
phones: Record<string, IndividualPhone>;
emails: Record<string, IndividualEmail>;
virtualLocations: Record<string, IndividualVirtualLocation>;
media: Record<string, IndividualMedia>;
organizations: Record<string, IndividualOrganization>;
tags: string[];
notes: Record<string, IndividualNote>;
language: string | null;
languages: IndividualLanguage[];
crypto: Record<string, IndividualCrypto>;
}
+115
View File
@@ -0,0 +1,115 @@
/**
* Organization-related type definitions
*/
/**
* Organization name information
*/
export interface OrganizationName {
full: string | null;
sort: string | null;
aliases: string[];
}
/**
* Organization physical location
*/
export interface OrganizationPhysicalLocation {
box: string | null;
unit: string | null;
street: string | null;
locality: string | null;
region: string | null;
code: string | null;
country: string | null;
label: string | null;
coordinates: string | null;
timeZone: string | null;
context: string | null;
priority: number | null;
}
/**
* Organization phone
*/
export interface OrganizationPhone {
number: string | null;
label: string | null;
context: string | null;
priority: number | null;
}
/**
* Organization email
*/
export interface OrganizationEmail {
address: string | null;
context: string | null;
priority: number | null;
}
/**
* Organization virtual location
*/
export interface OrganizationVirtualLocation {
location: string | null;
label: string | null;
context: string | null;
priority: number | null;
}
/**
* Organization media
*/
export interface OrganizationMedia {
type: string;
kind: string; // 'logo', 'photo'
uri: string;
mediaType?: string | null;
contexts?: string[] | null;
pref?: number | null;
label?: string | null;
}
/**
* Organization note
*/
export interface OrganizationNote {
content: string | null;
date: Date | null;
authorUri: string | null;
authorName: string | null;
context: string | null;
priority: number | null;
}
/**
* Organization crypto
*/
export interface OrganizationCrypto {
data: string | null;
type: string | null;
context: string | null;
priority: number | null;
}
/**
* Data for an organization entity
*/
export interface OrganizationInterface {
type: string;
version: number;
urid: string | null;
created: Date | null;
modified: Date | null;
label: string | null;
names: OrganizationName;
physicalLocations: Record<string, OrganizationPhysicalLocation>;
phones: Record<string, OrganizationPhone>;
emails: Record<string, OrganizationEmail>;
virtualLocations: Record<string, OrganizationVirtualLocation>;
media: Record<string, OrganizationMedia>;
tags: string[];
notes: Record<string, OrganizationNote>;
crypto: Record<string, OrganizationCrypto>;
}
+53
View File
@@ -0,0 +1,53 @@
/**
* Provider-specific types
*/
import type { SourceSelector } from "./common";
/**
* Provider capabilities
*/
export interface ProviderCapabilitiesInterface {
ServiceList?: boolean;
ServiceFetch?: boolean;
ServiceExtant?: boolean;
ServiceCreate?: boolean;
ServiceModify?: boolean;
ServiceDelete?: boolean;
[key: string]: boolean | undefined;
}
/**
* Provider information
*/
export interface ProviderInterface {
'@type': string;
id: string;
label: string;
capabilities: ProviderCapabilitiesInterface;
}
/**
* Request to provider list endpoint
*/
export interface ProviderListRequest {}
/**
* Response from provider list endpoint
*/
export interface ProviderListResponse {
[providerId: string]: ProviderInterface;
}
/**
* Request to provider extant endpoint
*/
export interface ProviderExtantRequest {
sources: SourceSelector;
}
/**
* Response from provider extant endpoint
*/
export interface ProviderExtantResponse {
[providerId: string]: boolean;
}
+211
View File
@@ -0,0 +1,211 @@
/**
* Service-related type definitions for People Manager
*/
import type { ListFilter, ListSort, SourceSelector } from "./common";
/**
* Filter comparison operators (bitmask values)
*/
export const FilterComparisonOperator = {
EQ: 1, // Equal
NEQ: 2, // Not Equal
GT: 4, // Greater Than
LT: 8, // Less Than
GTE: 16, // Greater Than or Equal
LTE: 32, // Less Than or Equal
IN: 64, // In Array
NIN: 128, // Not In Array
LIKE: 256, // Like (pattern matching)
NLIKE: 512, // Not Like
} as const;
export type FilterComparisonOperator = typeof FilterComparisonOperator[keyof typeof FilterComparisonOperator];
/**
* Filter conjunction operators
*/
export const FilterConjunctionOperator = {
NONE: '',
AND: 'AND',
OR: 'OR',
} as const;
export type FilterConjunctionOperator = typeof FilterConjunctionOperator[keyof typeof FilterConjunctionOperator];
/**
* Filter specification format
* Format: "type:length:defaultComparator:supportedComparators"
*
* Examples:
* - "s:200:256:771" = String field, max 200 chars, default LIKE, supports EQ|NEQ|LIKE|NLIKE
* - "a:10:64:192" = Array field, max 10 items, default IN, supports IN|NIN
* - "i:0:1:31" = Integer field, default EQ, supports EQ|NEQ|GT|LT|GTE|LTE
*
* Type codes:
* - s = string
* - i = integer
* - b = boolean
* - a = array
*
* Comparator values are bitmasks that can be combined
*/
export type FilterSpec = string;
/**
* Parsed filter specification
*/
export interface ParsedFilterSpec {
type: 'string' | 'integer' | 'boolean' | 'array';
length: number;
defaultComparator: FilterComparisonOperator;
supportedComparators: FilterComparisonOperator[];
}
/**
* Parse a filter specification string into its components
*
* @param spec - Filter specification string (e.g., "s:200:256:771")
* @returns Parsed filter specification object
*
* @example
* parseFilterSpec("s:200:256:771")
* // Returns: {
* // type: 'string',
* // length: 200,
* // defaultComparator: 256 (LIKE),
* // supportedComparators: [1, 2, 256, 512] (EQ, NEQ, LIKE, NLIKE)
* // }
*/
export function parseFilterSpec(spec: FilterSpec): ParsedFilterSpec {
const [typeCode, lengthStr, defaultComparatorStr, supportedComparatorsStr] = spec.split(':');
const typeMap: Record<string, ParsedFilterSpec['type']> = {
's': 'string',
'i': 'integer',
'b': 'boolean',
'a': 'array',
};
const type = typeMap[typeCode];
if (!type) {
throw new Error(`Invalid filter type code: ${typeCode}`);
}
const length = parseInt(lengthStr, 10);
const defaultComparator = parseInt(defaultComparatorStr, 10) as FilterComparisonOperator;
// Parse supported comparators from bitmask
const supportedComparators: FilterComparisonOperator[] = [];
const supportedBitmask = parseInt(supportedComparatorsStr, 10);
if (supportedBitmask !== 0) {
const allComparators = Object.values(FilterComparisonOperator).filter(v => typeof v === 'number') as number[];
for (const comparator of allComparators) {
if ((supportedBitmask & comparator) === comparator) {
supportedComparators.push(comparator as FilterComparisonOperator);
}
}
}
return {
type,
length,
defaultComparator,
supportedComparators,
};
}
/**
* Capabilities available for a service
*/
export interface ServiceCapabilitiesInterface {
// Collection capabilities
CollectionList?: boolean;
CollectionListFilter?: {
[key: string]: FilterSpec;
};
CollectionListSort?: string[];
CollectionExtant?: boolean;
CollectionFetch?: boolean;
CollectionCreate?: boolean;
CollectionModify?: boolean;
CollectionDestroy?: boolean;
// Entity capabilities
EntityList?: boolean;
EntityListFilter?: {
[key: string]: FilterSpec;
};
EntityListSort?: string[];
EntityListRange?: {
[rangeType: string]: string[]; // e.g., { "tally": ["absolute", "relative"] }
};
EntityDelta?: boolean;
EntityExtant?: boolean;
EntityFetch?: boolean;
EntityCreate?: boolean;
EntityModify?: boolean;
EntityDestroy?: boolean;
EntityCopy?: boolean;
EntityMove?: boolean;
}
/**
* Represents a service within a provider
*/
export interface ServiceInterface {
'@type': string;
provider: string;
id: string;
label: string;
capabilities?: ServiceCapabilitiesInterface;
enabled: boolean;
}
/**
* Request to service list endpoint
*/
export interface ServiceListRequest {
sources?: SourceSelector;
filter?: ListFilter;
sort?: ListSort;
}
/**
* Response from service list endpoint
*/
export interface ServiceListResponse {
[providerId: string]: {
[serviceId: string]: ServiceInterface;
};
}
/**
* Request to service extant endpoint
*/
export interface ServiceExtantRequest {
sources: SourceSelector;
}
/**
* Response from service extant endpoint
*/
export interface ServiceExtantResponse {
[providerId: string]: {
[serviceId: string]: boolean;
};
}
/**
* Request to service fetch endpoint
*/
export interface ServiceFetchRequest {
provider: string;
service: string;
}
/**
* Response from service fetch endpoint
*/
export interface ServiceFetchResponse extends ServiceInterface {}