datum-focus
Version:
Data shape, model, metadata, JSON, JSON Schema, GraphQL, MongoDB query and aggregations, iterator generators
194 lines (171 loc) • 7.5 kB
text/typescript
import { Query } from "sift";
import { v4 as guid } from "uuid";
import { KnownRecord } from "../record";
import { Guid } from "../string";
import { Model } from "../model";
export type K = { _id: Guid };
export const entity = <T extends {}>(record: T): Entity<T> => ({
_id: guid(),
...record,
});
export const collonize = <T extends {}>(
records: T[]
): Record<Guid, Entity<T>> =>
records.reduce((coll, record) => {
const ntt = entity(record);
return Object.assign(coll, { [ntt._id]: ntt });
}, {});
export type Entity<T extends {}> = {
_id: string;
} & T;
export type StoreResult<T extends {} = KnownRecord> = K & {
data?: T | null;
rescode?: ResultCode;
message?: string;
};
export interface Repository<T extends {} = KnownRecord> {
readonly model: Model<T>;
count: Promise<number>;
create(record: T): Promise<StoreResult<T>>;
delete(_id: string): Promise<StoreResult<T>>;
find(_id: string): Promise<StoreResult<T>>;
select(query?: Query<T>): Promise<AsyncIterable<Entity<T>>>;
update(entity: Entity<Partial<T>>): Promise<StoreResult<T>>;
}
export interface BatchRepository<T extends {} = KnownRecord> {
readonly model: Model<T>;
count: Promise<number>;
batchCreate(records: T[]): Promise<StoreResult<T>[]>;
batchDelete(ids: string[]): Promise<StoreResult<T>[]>;
batchFind(ids: string[]): Promise<AsyncIterable<Entity<T>>>;
batchUpdate(entities: Entity<Partial<T>>[]): Promise<StoreResult<T>[]>;
}
/*** 2×× SUCCESS ***/
export const RESULT_CODE__OK = 200;
export const RESULT_CODE__CREATED = 201;
export const RESULT_CODE__ACCEPTED = 202;
export const HTTP_RESULT_CODE_203_NON_AUTHORITATIVE_INFORMATION = 203;
export const HTTP_RESULT_CODE_204_NO_CONTENT = 204;
export const HTTP_RESULT_CODE_205_RESET_CONTENT = 205;
export const HTTP_RESULT_CODE_206_PARTIAL_CONTENT = 206;
export const HTTP_RESULT_CODE_207_MULTI_STATUS = 207;
export const HTTP_RESULT_CODE_208_ALREADY_REPORTED = 208;
export const HTTP_RESULT_CODE_226_IM_USED = 226;
/*** 3×× REDIRECTION ***/
export const HTTP_RESULT_CODE_300_MULTIPLE_CHOICES = 300;
export const HTTP_RESULT_CODE_301_MOVED_PERMANENTLY = 301;
export const HTTP_RESULT_CODE_302_FOUND = 302;
export const HTTP_RESULT_CODE_303_SEE_OTHER = 303;
export const HTTP_RESULT_CODE_304_NOT_MODIFIED = 304;
export const HTTP_RESULT_CODE_305_USE_PROXY = 305;
export const HTTP_RESULT_CODE_307_TEMPORARY_REDIRECT = 307;
export const HTTP_RESULT_CODE_308_PERMANENT_REDIRECT = 308;
/*** 4×× CLIENT ERROR ***/
export const RESULT_CODE__BAD_REQUEST = 400;
export const RESULT_CODE__UNAUTHORIZED = 401;
export const HTTP_RESULT_CODE_402_PAYMENT_REQUIRED = 402;
export const RESULT_CODE__FORBIDDEN = 403;
export const RESULT_CODE__NOT_FOUND = 404;
export const HTTP_RESULT_CODE_405_METHOD_NOT_ALLOWED = 405;
export const RESULT_CODE__NOT_ACCEPTABLE = 406;
export const HTTP_RESULT_CODE_407_PROXY_AUTHENTICATION_REQUIRED = 407;
export const HTTP_RESULT_CODE_408_REQUEST_TIMEOUT = 408;
export const RESULT_CODE_CONFLICT = 409;
export const HTTP_RESULT_CODE_410_GONE = 410;
export const HTTP_RESULT_CODE_411_LENGTH_REQUIRED = 411;
export const HTTP_RESULT_CODE_412_PRECONDITION_FAILED = 412;
export const HTTP_RESULT_CODE_413_PAYLOAD_TOO_LARGE = 413;
export const HTTP_RESULT_CODE_414_REQUEST_URI_TOO_LONG = 414;
export const HTTP_RESULT_CODE_415_UNSUPPORTED_MEDIA_TYPE = 415;
export const HTTP_RESULT_CODE_416_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
export const HTTP_RESULT_CODE_417_EXPECTATION_FAILED = 417;
export const HTTP_RESULT_CODE_418_IM_A_TEAPOT = 418;
export const HTTP_RESULT_CODE_421_MISDIRECTED_REQUEST = 421;
export const RESULT_CODE__UNPROCESSABLE_ENTITY = 422;
export const RESULT_CODE__LOCKED = 423;
export const HTTP_RESULT_CODE_424_FAILED_DEPENDENCY = 424;
export const HTTP_RESULT_CODE_426_UPGRADE_REQUIRED = 426;
export const RESULT_CODE__PRECONDITION_REQUIRED = 428;
export const RESULT_CODE__TOO_MANY_REQUESTS = 429;
export const HTTP_RESULT_CODE_431_REQUEST_HEADER_FIELDS_TOO_LARGE = 431;
export const HTTP_RESULT_CODE_444_CONNECTION_CLOSED_WITHOUT_RESPONSE = 444;
export const HTTP_RESULT_CODE_451_UNAVAILABLE_FOR_LEGAL_REASONS = 451;
export const HTTP_RESULT_CODE_499_CLIENT_CLOSED_REQUEST = 499;
/*** 5×× SERVER ERROR ***/
export const HTTP_RESULT_CODE_500_INTERNAL_SERVER_ERROR = 500;
export const RESULT_CODE__NOT_IMPLEMENTED = 501;
export const HTTP_RESULT_CODE_502_BAD_GATEWAY = 502;
export const RESULT_CODE__SERVICE_UNAVAILABLE = 503;
export const HTTP_RESULT_CODE_504_GATEWAY_TIMEOUT = 504;
export const HTTP_RESULT_CODE_505_HTTP_VERSION_NOT_SUPPORTED = 505;
export const HTTP_RESULT_CODE_506_VARIANT_ALSO_NEGOTIATES = 506;
export const RESULT_CODE__INSUFFICIENT_STORAGE = 507;
export const HTTP_RESULT_CODE_508_LOOP_DETECTED = 508;
export const HTTP_RESULT_CODE_510_NOT_EXTENDED = 510;
export const HTTP_RESULT_CODE_511_NETWORK_AUTHENTICATION_REQUIRED = 511;
export const HTTP_RESULT_CODE_599_NETWORK_CONNECTTIMEOUT_ERROR = 599;
export const RESULT_CODES = [
/*** 2×× SUCCESS ***/
RESULT_CODE__OK,
RESULT_CODE__CREATED,
RESULT_CODE__ACCEPTED,
HTTP_RESULT_CODE_203_NON_AUTHORITATIVE_INFORMATION,
HTTP_RESULT_CODE_204_NO_CONTENT,
HTTP_RESULT_CODE_205_RESET_CONTENT,
HTTP_RESULT_CODE_206_PARTIAL_CONTENT,
HTTP_RESULT_CODE_207_MULTI_STATUS,
HTTP_RESULT_CODE_208_ALREADY_REPORTED,
HTTP_RESULT_CODE_226_IM_USED,
/*** 3×× REDIRECTION ***/
HTTP_RESULT_CODE_300_MULTIPLE_CHOICES,
HTTP_RESULT_CODE_301_MOVED_PERMANENTLY,
HTTP_RESULT_CODE_302_FOUND,
HTTP_RESULT_CODE_303_SEE_OTHER,
HTTP_RESULT_CODE_304_NOT_MODIFIED,
/*** 4×× CLIENT ERROR ***/
RESULT_CODE__BAD_REQUEST,
RESULT_CODE__UNAUTHORIZED,
RESULT_CODE__FORBIDDEN,
RESULT_CODE__NOT_FOUND,
HTTP_RESULT_CODE_405_METHOD_NOT_ALLOWED,
RESULT_CODE__NOT_ACCEPTABLE,
HTTP_RESULT_CODE_407_PROXY_AUTHENTICATION_REQUIRED,
HTTP_RESULT_CODE_408_REQUEST_TIMEOUT,
RESULT_CODE_CONFLICT,
HTTP_RESULT_CODE_410_GONE,
HTTP_RESULT_CODE_411_LENGTH_REQUIRED,
HTTP_RESULT_CODE_412_PRECONDITION_FAILED,
HTTP_RESULT_CODE_413_PAYLOAD_TOO_LARGE,
HTTP_RESULT_CODE_414_REQUEST_URI_TOO_LONG,
HTTP_RESULT_CODE_415_UNSUPPORTED_MEDIA_TYPE,
HTTP_RESULT_CODE_416_REQUESTED_RANGE_NOT_SATISFIABLE,
HTTP_RESULT_CODE_417_EXPECTATION_FAILED,
HTTP_RESULT_CODE_418_IM_A_TEAPOT,
HTTP_RESULT_CODE_421_MISDIRECTED_REQUEST,
RESULT_CODE__UNPROCESSABLE_ENTITY,
RESULT_CODE__LOCKED,
HTTP_RESULT_CODE_424_FAILED_DEPENDENCY,
HTTP_RESULT_CODE_426_UPGRADE_REQUIRED,
RESULT_CODE__PRECONDITION_REQUIRED,
RESULT_CODE__TOO_MANY_REQUESTS,
HTTP_RESULT_CODE_431_REQUEST_HEADER_FIELDS_TOO_LARGE,
HTTP_RESULT_CODE_444_CONNECTION_CLOSED_WITHOUT_RESPONSE,
HTTP_RESULT_CODE_451_UNAVAILABLE_FOR_LEGAL_REASONS,
HTTP_RESULT_CODE_499_CLIENT_CLOSED_REQUEST,
/*** 5×× SERVER ERROR ***/
HTTP_RESULT_CODE_500_INTERNAL_SERVER_ERROR,
RESULT_CODE__NOT_IMPLEMENTED,
HTTP_RESULT_CODE_502_BAD_GATEWAY,
RESULT_CODE__SERVICE_UNAVAILABLE,
HTTP_RESULT_CODE_504_GATEWAY_TIMEOUT,
HTTP_RESULT_CODE_505_HTTP_VERSION_NOT_SUPPORTED,
HTTP_RESULT_CODE_506_VARIANT_ALSO_NEGOTIATES,
RESULT_CODE__INSUFFICIENT_STORAGE,
HTTP_RESULT_CODE_508_LOOP_DETECTED,
HTTP_RESULT_CODE_510_NOT_EXTENDED,
HTTP_RESULT_CODE_511_NETWORK_AUTHENTICATION_REQUIRED,
HTTP_RESULT_CODE_599_NETWORK_CONNECTTIMEOUT_ERROR,
] as const;
export type ResultCode = typeof RESULT_CODES[number];
export type HttpResultCodeMap<T> = Record<ResultCode, T>;
export type HttpResultCodeSet<T> = Partial<HttpResultCodeMap<T>>;