chore: standardize chrono provider

Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
2026-02-17 03:11:18 -05:00
parent 974d3fe11b
commit fccd7b1df6
31 changed files with 3800 additions and 2076 deletions

View File

@@ -1,70 +1,57 @@
/**
* Collection-related type definitions for Chrono Manager
* Collection type definitions
*/
import type { ListFilter, ListSort, SourceSelector } from "./common";
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;
}
/**
* Content type settings for a collection
* Collection information
*/
export interface CollectionContentsInterface {
event?: boolean;
task?: boolean;
journal?: boolean;
[contentType: string]: boolean | undefined;
}
/**
* Represents a collection (calendar) within a service
*/
export interface CollectionInterface {
provider: string;
service: string | number;
collection: string | number | null;
identifier: string | number;
signature?: string | null;
created?: string | null;
modified?: string | null;
properties: CollectionPropertiesInterface;
}
export interface CollectionBaseProperties {
'@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;
version: number;
}
export interface CollectionImmutableProperties extends CollectionBaseProperties {
total?: number;
contents: CollectionContentsInterface;
}
export interface CollectionMutableProperties extends CollectionBaseProperties {
label: string;
description: string | null;
rank: number | null;
visibility: boolean | null;
color: string | null;
}
export interface CollectionPropertiesInterface extends CollectionMutableProperties, CollectionImmutableProperties {}
/**
* Request to collection list endpoint
* Collection list
*/
export interface CollectionListRequest {
sources?: SourceSelector;
filter?: ListFilter;
sort?: ListSort;
uid?: string;
}
/**
* Response from collection list endpoint
*/
export interface CollectionListResponse {
[providerId: string]: {
[serviceId: string]: {
@@ -74,16 +61,23 @@ export interface CollectionListResponse {
}
/**
* Request to collection extant endpoint
* Collection fetch
*/
export interface CollectionFetchRequest {
provider: string;
service: string | number;
collection: string | number;
}
export interface CollectionFetchResponse extends CollectionInterface {}
/**
* Collection extant
*/
export interface CollectionExtantRequest {
sources: SourceSelector;
uid?: string;
}
/**
* Response from collection extant endpoint
*/
export interface CollectionExtantResponse {
[providerId: string]: {
[serviceId: string]: {
@@ -93,66 +87,42 @@ export interface CollectionExtantResponse {
}
/**
* Request to collection fetch endpoint
*/
export interface CollectionFetchRequest {
provider: string;
service: string;
identifier: string | number;
uid?: string;
}
/**
* Response from collection fetch endpoint
*/
export interface CollectionFetchResponse extends CollectionInterface {}
/**
* Request to collection create endpoint
* Collection create
*/
export interface CollectionCreateRequest {
provider: string;
service: string;
data: CollectionInterface;
options?: (string)[]
uid?: string;
service: string | number;
collection?: string | number | null; // Parent Collection Identifier
properties: CollectionMutableProperties;
}
/**
* Response from collection create endpoint
*/
export interface CollectionCreateResponse extends CollectionInterface {}
export interface CollectionCreateResponse extends CollectionInterface {}
/**
* Request to collection modify endpoint
* Collection modify
*/
export interface CollectionModifyRequest {
export interface CollectionUpdateRequest {
provider: string;
service: string;
service: string | number;
identifier: string | number;
data: CollectionInterface;
uid?: string;
properties: CollectionMutableProperties;
}
/**
* Response from collection modify endpoint
*/
export interface CollectionModifyResponse extends CollectionInterface {}
export interface CollectionUpdateResponse extends CollectionInterface {}
/**
* Request to collection destroy endpoint
* Collection delete
*/
export interface CollectionDestroyRequest {
export interface CollectionDeleteRequest {
provider: string;
service: string;
service: string | number;
identifier: string | number;
uid?: string;
options?: {
force?: boolean; // Whether to force delete even if collection is not empty
recursive?: boolean; // Whether to delete child collections/items as well
};
}
/**
* Response from collection destroy endpoint
*/
export interface CollectionDestroyResponse {
export interface CollectionDeleteResponse {
success: boolean;
}

View File

@@ -1,18 +1,62 @@
/**
* Common types shared across Chrono Manager services
* Common types shared across provider, service, collection, and entity request and responses.
*/
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;
}
/**
* Source selector structure for hierarchical resource selection
* Structure: Provider -> Service -> Collection -> Entity
* 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;
/**
* Selector for targeting specific providers, services, collections, or entities in list or extant operations.
*
* 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] } } }
* Example usage:
* {
* "provider1": true, // Select all services/collections/entities under provider1
* "provider2": {
* "serviceA": true, // Select all collections/entities under serviceA of provider2
* "serviceB": {
* "collectionX": true, // Select all entities under collectionX of serviceB of provider2
* "collectionY": [1, 2, 3] // Select entities with identifiers 1, 2, and 3 under collectionY of serviceB of provider2
* }
* }
* }
*/
export type SourceSelector = {
[provider: string]: boolean | ServiceSelector;
@@ -28,38 +72,85 @@ export type CollectionSelector = {
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
* Filter comparison for list operations
*/
export const ListFilterComparisonOperator = {
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
NLIKE: 512, // Not Like
} as const;
export type ListFilterComparisonOperator = typeof ListFilterComparisonOperator[keyof typeof ListFilterComparisonOperator];
/**
* Filter conjunction for list operations
*/
export const ListFilterConjunctionOperator = {
NONE: '',
AND: 'AND',
OR: 'OR',
} as const;
export type ListFilterConjunctionOperator = typeof ListFilterConjunctionOperator[keyof typeof ListFilterConjunctionOperator];
/**
* Filter condition for list operations
*
* Tuple format: [value, comparator?, conjunction?]
*/
export type ListFilterCondition = [
string | number | boolean | string[] | number[],
ListFilterComparisonOperator?,
ListFilterConjunctionOperator?
];
/**
* Filter for list operations
*
* Values can be:
* - Simple primitives (string | number | boolean) for default equality comparison
* - ListFilterCondition tuple for explicit comparator/conjunction
*
* Examples:
* - Simple usage: { name: "John" }
* - With comparator: { age: [25, ListFilterComparisonOperator.GT] }
* - With conjunction: { age: [25, ListFilterComparisonOperator.GT, ListFilterConjunctionOperator.AND] }
* - With array value for IN operator: { status: [["active", "pending"], ListFilterComparisonOperator.IN] }
*/
export interface ListFilter {
label?: string;
[key: string]: any;
[attribute: string]: string | number | boolean | ListFilterCondition;
}
/**
* Sort options for list operations
* Sort for list operations
*
* Values can be:
* - true for ascending
* - false for descending
*/
export interface ListSort {
[key: string]: boolean;
[attribute: string]: boolean;
}
/**
* Range specification for pagination/limiting results
* Range for list operations
*
* Values can be:
* - relative based on item identifier
* - absolute based on item count
*/
export interface ListRange {
type: 'tally';
anchor: 'absolute' | 'relative';
position: number;
anchor: 'relative' | 'absolute';
position: string | number;
tally: number;
}
}

View File

@@ -1,166 +1,131 @@
/**
* Entity type definitions
*/
import type { ListFilter, ListRange, ListSort, SourceSelector } from './common';
import type { EventInterface } from './event';
import type { TaskInterface } from './task';
import type { JournalInterface } from './journal';
/**
* Entity-related type definitions for Chrono Manager
* Entity definition
*/
/**
* Represents a chrono entity (event, task, or journal)
*/
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;
export interface EntityInterface<T = EventInterface | TaskInterface | JournalInterface> {
provider: string;
service: string;
collection: string | number;
identifier: string | number;
signature: string | null;
data: EventInterface | TaskInterface | JournalInterface | null;
created: string | null;
modified: string | null;
properties: T;
}
/**
* Request to entity list endpoint
* Entity list
*/
export interface EntityListRequest {
sources?: SourceSelector;
filter?: ListFilter;
sort?: ListSort;
range?: ListRange;
uid?: string;
}
/**
* Response from entity list endpoint
*/
export interface EntityListResponse {
[providerId: string]: {
[serviceId: string]: {
[collectionId: string]: {
[entityId: string]: EntityInterface;
[identifier: string]: EntityInterface<EventInterface | TaskInterface | JournalInterface>;
};
};
};
}
/**
* Request to entity delta endpoint
* Entity fetch
*/
export interface EntityDeltaRequest {
sources: SourceSelector;
uid?: string;
export interface EntityFetchRequest {
provider: string;
service: string | number;
collection: string | number;
identifiers: (string | number)[];
}
export interface EntityFetchResponse {
[identifier: string]: EntityInterface<EventInterface | TaskInterface | JournalInterface>;
}
/**
* 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
* Entity extant
*/
export interface EntityExtantRequest {
sources: SourceSelector;
uid?: string;
}
/**
* Response from entity extant endpoint
*/
export interface EntityExtantResponse {
[providerId: string]: {
[serviceId: string]: {
[collectionId: string]: {
[entityId: string]: boolean;
[identifier: string]: boolean;
};
};
};
}
/**
* Request to entity fetch endpoint
* Entity create
*/
export interface EntityFetchRequest {
export interface EntityCreateRequest<T = EventInterface | TaskInterface | JournalInterface> {
provider: string;
service: string;
service: string | number;
collection: string | number;
identifiers: (string | number)[];
uid?: string;
properties: T;
}
/**
* Response from entity fetch endpoint
*/
export interface EntityFetchResponse extends Record<string, EntityInterface> {}
export interface EntityCreateResponse<T = EventInterface | TaskInterface | JournalInterface> extends EntityInterface<T> {}
/**
* Request to entity create endpoint
* Entity update
*/
export interface EntityCreateRequest {
export interface EntityUpdateRequest<T = EventInterface | TaskInterface | JournalInterface> {
provider: string;
service: string;
collection: string | number;
data: EntityInterface;
options?: (string)[]
uid?: string;
}
/**
* Response from entity create endpoint
*/
export interface EntityCreateResponse extends EntityInterface {}
/**
* Request to entity modify endpoint
*/
export interface EntityModifyRequest {
provider: string;
service: string;
service: string | number;
collection: string | number;
identifier: string | number;
data: EntityInterface;
options?: (string)[]
uid?: string;
properties: T;
}
/**
* Response from entity modify endpoint
*/
export interface EntityModifyResponse extends EntityInterface {}
export interface EntityUpdateResponse<T = EventInterface | TaskInterface | JournalInterface> extends EntityInterface<T> {}
/**
* Request to entity destroy endpoint
* Entity delete
*/
export interface EntityDestroyRequest {
export interface EntityDeleteRequest {
provider: string;
service: string;
service: string | number;
collection: string | number;
identifier: string | number;
uid?: string;
}
/**
* Response from entity destroy endpoint
*/
export interface EntityDestroyResponse {
export interface EntityDeleteResponse {
success: boolean;
}
/**
* Entity delta
*/
export interface EntityDeltaRequest {
sources: SourceSelector;
}
export interface EntityDeltaResponse {
[providerId: string]: false | {
[serviceId: string]: false | {
[collectionId: string]: false | {
signature: string;
additions: (string | number)[];
modifications: (string | number)[];
deletions: (string | number)[];
};
};
};
}

View File

@@ -1,12 +1,8 @@
/**
* Central export point for all Chrono Manager types
*/
export type * from './collection';
export type * from './common';
export type * from './entity';
export type * from './event';
export type * from './task';
export type * from './journal';
export type * from './provider';
export type * from './service';
export type * from './task';

View File

@@ -1,5 +1,5 @@
/**
* Provider-specific types
* Provider type definitions
*/
import type { SourceSelector } from "./common";
@@ -11,9 +11,11 @@ export interface ProviderCapabilitiesInterface {
ServiceFetch?: boolean;
ServiceExtant?: boolean;
ServiceCreate?: boolean;
ServiceModify?: boolean;
ServiceUpdate?: boolean;
ServiceDelete?: boolean;
[key: string]: boolean | undefined;
ServiceDiscover?: boolean;
ServiceTest?: boolean;
[key: string]: boolean | object | string[] | undefined;
}
/**
@@ -21,33 +23,38 @@ export interface ProviderCapabilitiesInterface {
*/
export interface ProviderInterface {
'@type': string;
id: string;
identifier: string;
label: string;
capabilities: ProviderCapabilitiesInterface;
}
/**
* Request to provider list endpoint
* Provider list
*/
export interface ProviderListRequest {}
export interface ProviderListRequest {
sources?: SourceSelector;
}
/**
* Response from provider list endpoint
*/
export interface ProviderListResponse {
[providerId: string]: ProviderInterface;
[identifier: string]: ProviderInterface;
}
/**
* Request to provider extant endpoint
* Provider fetch
*/
export interface ProviderFetchRequest {
identifier: string;
}
export interface ProviderFetchResponse extends ProviderInterface {}
/**
* Provider extant
*/
export interface ProviderExtantRequest {
sources: SourceSelector;
}
/**
* Response from provider extant endpoint
*/
export interface ProviderExtantResponse {
[providerId: string]: boolean;
[identifier: string]: boolean;
}

View File

@@ -1,40 +1,254 @@
/**
* Service-related type definitions for Chrono Manager
* Service type definitions
*/
import type { ListFilter, ListSort, SourceSelector } from "./common";
import type { SourceSelector, ListFilterComparisonOperator } from './common';
/**
* Filter comparison operators (bitmask values)
* Service capabilities
*/
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];
export interface ServiceCapabilitiesInterface {
// Collection capabilities
CollectionList?: boolean;
CollectionListFilter?: ServiceListFilterCollection;
CollectionListSort?: ServiceListSortCollection;
CollectionExtant?: boolean;
CollectionFetch?: boolean;
CollectionCreate?: boolean;
CollectionUpdate?: boolean;
CollectionDelete?: boolean;
// Message capabilities
EntityList?: boolean;
EntityListFilter?: ServiceListFilterEntity;
EntityListSort?: ServiceListSortEntity;
EntityListRange?: ServiceListRange;
EntityDelta?: boolean;
EntityExtant?: boolean;
EntityFetch?: boolean;
EntityCreate?: boolean;
EntityUpdate?: boolean;
EntityDelete?: boolean;
EntityMove?: boolean;
EntityCopy?: boolean;
// Send capability
EntityTransmit?: boolean;
[key: string]: boolean | object | string | string[] | undefined;
}
/**
* Filter conjunction operators
* Service information
*/
export const FilterConjunctionOperator = {
NONE: '',
AND: 'AND',
OR: 'OR',
} as const;
export type FilterConjunctionOperator = typeof FilterConjunctionOperator[keyof typeof FilterConjunctionOperator];
export interface ServiceInterface {
'@type': string;
provider: string;
identifier: string | number | null;
label: string | null;
enabled: boolean;
capabilities?: ServiceCapabilitiesInterface;
location?: ServiceLocation | null;
identity?: ServiceIdentity | null;
auxiliary?: Record<string, any>; // Provider-specific extension data
}
/**
* Filter specification format
* Service list
*/
export interface ServiceListRequest {
sources?: SourceSelector;
}
export interface ServiceListResponse {
[provider: string]: {
[identifier: string]: ServiceInterface;
};
}
/**
* Service fetch
*/
export interface ServiceFetchRequest {
provider: string;
identifier: string | number;
}
export interface ServiceFetchResponse extends ServiceInterface {}
/**
* Service extant
*/
export interface ServiceExtantRequest {
sources: SourceSelector;
}
export interface ServiceExtantResponse {
[provider: string]: {
[identifier: string]: boolean;
};
}
/**
* Service create
*/
export interface ServiceCreateRequest {
provider: string;
data: Partial<ServiceInterface>;
}
export interface ServiceCreateResponse extends ServiceInterface {}
/**
* Service update
*/
export interface ServiceUpdateRequest {
provider: string;
identifier: string | number;
data: Partial<ServiceInterface>;
}
export interface ServiceUpdateResponse extends ServiceInterface {}
/**
* Service delete
*/
export interface ServiceDeleteRequest {
provider: string;
identifier: string | number;
}
export interface ServiceDeleteResponse {}
/**
* Service discovery
*/
export interface ServiceDiscoverRequest {
identity: string; // Email address or domain
provider?: string; // Optional: specific provider ('jmap', 'smtp', etc.) or null for all
location?: string; // Optional: known hostname (bypasses DNS lookup)
secret?: string; // Optional: password/token for credential validation
}
export interface ServiceDiscoverResponse {
[provider: string]: ServiceLocation; // Uses existing ServiceLocation discriminated union
}
/**
* Service connection test
*/
export interface ServiceTestRequest {
provider: string;
// For existing service
identifier?: string | number | null;
// For fresh configuration
location?: ServiceLocation | null;
identity?: ServiceIdentity | null;
}
export interface ServiceTestResponse {
success: boolean;
message: string;
}
/**
* Service location - Base
*/
export interface ServiceLocationBase {
type: 'URI' | 'FILE';
}
/**
* Service location - URI-based type
*/
export interface ServiceLocationUri extends ServiceLocationBase {
type: 'URI';
scheme: string; // e.g., 'https', 'http'
host: string; // e.g., 'api.example.com'
port: number; // e.g., 443
path?: string; // e.g., '/v1/api'
verifyPeer?: boolean; // Verify SSL/TLS peer certificate
verifyHost?: boolean; // Verify SSL/TLS certificate host
}
/**
* Service location - File-based type (e.g., for local mail delivery or Unix socket)
*/
export interface ServiceLocationFile extends ServiceLocationBase {
type: 'FILE';
path: string; // File system path
}
/**
* Service location types
*/
export type ServiceLocation =
| ServiceLocationUri
| ServiceLocationFile;
/**
* Service identity - base
*/
export interface ServiceIdentityBase {
type: 'NA' | 'BA' | 'TA' | 'OA' | 'CC';
}
/**
* Service identity - No authentication
*/
export interface ServiceIdentityNone extends ServiceIdentityBase {
type: 'NA';
}
/**
* Service identity - Basic authentication type
*/
export interface ServiceIdentityBasic extends ServiceIdentityBase {
type: 'BA';
identity: string; // Username/email
secret: string; // Password
}
/**
* Token authentication (API key, static token)
*/
export interface ServiceIdentityToken extends ServiceIdentityBase {
type: 'TA';
token: string; // Authentication token/API key
}
/**
* OAuth authentication
*/
export interface ServiceIdentityOAuth extends ServiceIdentityBase {
type: 'OA';
accessToken: string; // Current access token
accessScope?: string[]; // Token scopes
accessExpiry?: number; // Unix timestamp when token expires
refreshToken?: string; // Refresh token for getting new access tokens
refreshLocation?: string; // Token refresh endpoint URL
}
/**
* Client certificate authentication (mTLS)
*/
export interface ServiceIdentityCertificate extends ServiceIdentityBase {
type: 'CC';
certificate: string; // X.509 certificate (PEM format or file path)
privateKey: string; // Private key (PEM format or file path)
passphrase?: string; // Optional passphrase for encrypted private key
}
/**
* Service identity configuration
* Discriminated union of all identity types
*/
export type ServiceIdentity =
| ServiceIdentityNone
| ServiceIdentityBasic
| ServiceIdentityToken
| ServiceIdentityOAuth
| ServiceIdentityCertificate;
/**
* List filter specification format
*
* Format: "type:length:defaultComparator:supportedComparators"
*
* Examples:
@@ -50,165 +264,33 @@ export type FilterConjunctionOperator = typeof FilterConjunctionOperator[keyof t
*
* Comparator values are bitmasks that can be combined
*/
export type FilterSpec = string;
export type ServiceListFilterCollection = {
'label'?: string;
'rank'?: string;
[attribute: string]: string | undefined;
};
export type ServiceListFilterEntity = {
'*'?: string;
'before'?: string;
'after'?: string;
[attribute: string]: string | undefined;
}
/**
* Parsed filter specification
* Service list sort specification
*/
export interface ParsedFilterSpec {
type: 'string' | 'integer' | 'boolean' | 'array';
export type ServiceListSortCollection = ("label" | "rank" | string)[];
export type ServiceListSortEntity = ( "sent" | "size" | string)[];
export type ServiceListRange = {
'tally'?: string[];
};
export interface ServiceListFilterDefinition {
type: 'string' | 'integer' | 'date' | 'boolean' | 'array';
length: number;
defaultComparator: FilterComparisonOperator;
supportedComparators: FilterComparisonOperator[];
defaultComparator: ListFilterComparisonOperator;
supportedComparators: ListFilterComparisonOperator[];
}
/**
* 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;
uid?: string;
}
/**
* Response from service list endpoint
*/
export interface ServiceListResponse {
[providerId: string]: {
[serviceId: string]: ServiceInterface;
};
}
/**
* Request to service extant endpoint
*/
export interface ServiceExtantRequest {
sources: SourceSelector;
uid?: string;
}
/**
* 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;
uid?: string;
}
/**
* Response from service fetch endpoint
*/
export interface ServiceFetchResponse extends ServiceInterface {}