@sinio/sdk 0.0.0-stage → 0.2.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/LICENSE +21 -0
- package/README.md +136 -2
- package/dist/cjs/client.d.ts +75 -0
- package/dist/cjs/client.js +196 -0
- package/dist/cjs/client.js.map +1 -0
- package/dist/cjs/errors.d.ts +35 -0
- package/dist/cjs/errors.js +60 -0
- package/dist/cjs/errors.js.map +1 -0
- package/dist/cjs/http.d.ts +22 -0
- package/dist/cjs/http.js +139 -0
- package/dist/cjs/http.js.map +1 -0
- package/dist/cjs/index.d.ts +5 -0
- package/dist/cjs/index.js +27 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/serialize.d.ts +49 -0
- package/dist/cjs/serialize.js +191 -0
- package/dist/cjs/serialize.js.map +1 -0
- package/dist/cjs/types.d.ts +126 -0
- package/dist/cjs/types.js +3 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/cjs/vocabularies.d.ts +23 -0
- package/dist/cjs/vocabularies.js +39 -0
- package/dist/cjs/vocabularies.js.map +1 -0
- package/dist/esm/client.d.ts +75 -0
- package/dist/esm/client.js +192 -0
- package/dist/esm/client.js.map +1 -0
- package/dist/esm/errors.d.ts +35 -0
- package/dist/esm/errors.js +49 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/http.d.ts +22 -0
- package/dist/esm/http.js +134 -0
- package/dist/esm/http.js.map +1 -0
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/serialize.d.ts +49 -0
- package/dist/esm/serialize.js +179 -0
- package/dist/esm/serialize.js.map +1 -0
- package/dist/esm/types.d.ts +126 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/vocabularies.d.ts +23 -0
- package/dist/esm/vocabularies.js +35 -0
- package/dist/esm/vocabularies.js.map +1 -0
- package/package.json +43 -4
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { SinioValidationError } from "./errors.js";
|
|
2
|
+
import { ASSIGNMENT_RELATIONS, ENTITY_KINDS, EVENT_ROLES, INGESTION_MODES, LOCATION_LEVELS } from "./vocabularies.js";
|
|
3
|
+
/** The API caps every collection at 500 items per call. */
|
|
4
|
+
export const MAX_ITEMS_PER_CALL = 500;
|
|
5
|
+
/** The most units one event may stand for. */
|
|
6
|
+
export const MAX_EVENT_COUNT = 1_000_000;
|
|
7
|
+
// The API's own rule: a `T`, seconds, an optional fraction, then `Z` or an offset. It rejects the
|
|
8
|
+
// event otherwise (`invalid_occurred_at`); refused here, it is a fixable local error before any call.
|
|
9
|
+
const ISO_WITH_OFFSET = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:?\d{2})$/;
|
|
10
|
+
export function toIso(value, field) {
|
|
11
|
+
if (value instanceof Date) {
|
|
12
|
+
if (Number.isNaN(value.getTime())) {
|
|
13
|
+
throw new SinioValidationError(`${field} is an invalid Date`);
|
|
14
|
+
}
|
|
15
|
+
return value.toISOString();
|
|
16
|
+
}
|
|
17
|
+
if (typeof value !== "string" || !ISO_WITH_OFFSET.test(value)) {
|
|
18
|
+
throw new SinioValidationError(`${field} must be an ISO 8601 timestamp with an offset (got ${JSON.stringify(value)})`);
|
|
19
|
+
}
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
22
|
+
/** Drops `undefined` keys so they never reach the wire as `null`. */
|
|
23
|
+
function compact(record) {
|
|
24
|
+
return Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined));
|
|
25
|
+
}
|
|
26
|
+
export function chunk(items, size) {
|
|
27
|
+
const chunks = [];
|
|
28
|
+
for (let index = 0; index < items.length; index += size) {
|
|
29
|
+
chunks.push(items.slice(index, index + size));
|
|
30
|
+
}
|
|
31
|
+
return chunks;
|
|
32
|
+
}
|
|
33
|
+
// Local checks, each the API's own rule: the types already say it to TypeScript callers, these say it
|
|
34
|
+
// at runtime to plain JavaScript and to values typed loosely (`as`, `any`, parsed JSON).
|
|
35
|
+
function isPlainObject(value) {
|
|
36
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
const prototype = Object.getPrototypeOf(value);
|
|
40
|
+
return prototype === Object.prototype || prototype === null;
|
|
41
|
+
}
|
|
42
|
+
function requireItem(value, field) {
|
|
43
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
44
|
+
throw new SinioValidationError(`${field} must be an object (got ${describe(value)})`);
|
|
45
|
+
}
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
48
|
+
function requireString(value, field) {
|
|
49
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
50
|
+
throw new SinioValidationError(`${field} is required and must be a non-empty string (got ${describe(value)})`);
|
|
51
|
+
}
|
|
52
|
+
return value;
|
|
53
|
+
}
|
|
54
|
+
function optionalString(value, field) {
|
|
55
|
+
if (value !== undefined && typeof value !== "string") {
|
|
56
|
+
throw new SinioValidationError(`${field} must be a string (got ${describe(value)})`);
|
|
57
|
+
}
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
60
|
+
function optionalNonEmptyString(value, field) {
|
|
61
|
+
return value === undefined ? undefined : requireString(value, field);
|
|
62
|
+
}
|
|
63
|
+
function optionalObject(value, field) {
|
|
64
|
+
if (value !== undefined && !isPlainObject(value)) {
|
|
65
|
+
throw new SinioValidationError(`${field} must be a JSON object (got ${describe(value)})`);
|
|
66
|
+
}
|
|
67
|
+
return value;
|
|
68
|
+
}
|
|
69
|
+
export function requireOneOf(value, values, field) {
|
|
70
|
+
if (typeof value !== "string" || !values.includes(value)) {
|
|
71
|
+
throw new SinioValidationError(`${field} must be one of ${values.join(", ")} (got ${describe(value)})`);
|
|
72
|
+
}
|
|
73
|
+
return value;
|
|
74
|
+
}
|
|
75
|
+
export function requireList(value, field) {
|
|
76
|
+
if (!Array.isArray(value)) {
|
|
77
|
+
throw new SinioValidationError(`${field} must be an array (got ${describe(value)})`);
|
|
78
|
+
}
|
|
79
|
+
return value;
|
|
80
|
+
}
|
|
81
|
+
export function toWireMode(mode) {
|
|
82
|
+
return requireOneOf(mode, INGESTION_MODES, "mode");
|
|
83
|
+
}
|
|
84
|
+
function describe(value) {
|
|
85
|
+
if (value === undefined) {
|
|
86
|
+
return "undefined";
|
|
87
|
+
}
|
|
88
|
+
if (Array.isArray(value)) {
|
|
89
|
+
return "an array";
|
|
90
|
+
}
|
|
91
|
+
if (value instanceof Date) {
|
|
92
|
+
return "a Date";
|
|
93
|
+
}
|
|
94
|
+
return JSON.stringify(value) ?? String(value);
|
|
95
|
+
}
|
|
96
|
+
function toWireRoles(value, field) {
|
|
97
|
+
if (value === undefined) {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
const roles = requireItem(value, field);
|
|
101
|
+
for (const key of Object.keys(roles)) {
|
|
102
|
+
if (!EVENT_ROLES.includes(key)) {
|
|
103
|
+
throw new SinioValidationError(`${field}.${key} is not a role: roles are ${EVENT_ROLES.join(", ")}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return compact({
|
|
107
|
+
device: optionalNonEmptyString(roles["device"], `${field}.device`),
|
|
108
|
+
subject: optionalNonEmptyString(roles["subject"], `${field}.subject`),
|
|
109
|
+
location: optionalNonEmptyString(roles["location"], `${field}.location`),
|
|
110
|
+
actor: optionalNonEmptyString(roles["actor"], `${field}.actor`),
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
export function toWireEvent(event, index) {
|
|
114
|
+
const at = `events[${index}]`;
|
|
115
|
+
const item = requireItem(event, at);
|
|
116
|
+
const count = item["count"];
|
|
117
|
+
if (count !== undefined && (!Number.isInteger(count) || count < 1 || count > MAX_EVENT_COUNT)) {
|
|
118
|
+
throw new SinioValidationError(`${at}.count must be an integer between 1 and ${MAX_EVENT_COUNT} (got ${describe(count)})`);
|
|
119
|
+
}
|
|
120
|
+
return compact({
|
|
121
|
+
source_event_id: requireString(item["sourceEventId"], `${at}.sourceEventId`),
|
|
122
|
+
source_version: optionalString(item["sourceVersion"], `${at}.sourceVersion`),
|
|
123
|
+
project: optionalString(item["project"], `${at}.project`),
|
|
124
|
+
type: requireString(item["type"], `${at}.type`),
|
|
125
|
+
label: optionalString(item["label"], `${at}.label`),
|
|
126
|
+
occurred_at: toIso(requireTimestamp(item["occurredAt"], `${at}.occurredAt`), `${at}.occurredAt`),
|
|
127
|
+
roles: toWireRoles(item["roles"], `${at}.roles`),
|
|
128
|
+
payload: optionalObject(item["payload"], `${at}.payload`),
|
|
129
|
+
count: count,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
export function toWireEntity(entity, index) {
|
|
133
|
+
const at = `entities[${index}]`;
|
|
134
|
+
const item = requireItem(entity, at);
|
|
135
|
+
return compact({
|
|
136
|
+
external_id: requireString(item["externalId"], `${at}.externalId`),
|
|
137
|
+
kind: requireOneOf(item["kind"], ENTITY_KINDS, `${at}.kind`),
|
|
138
|
+
subkind: optionalNonEmptyString(item["subkind"], `${at}.subkind`),
|
|
139
|
+
label: optionalString(item["label"], `${at}.label`),
|
|
140
|
+
location: optionalString(item["location"], `${at}.location`),
|
|
141
|
+
attributes: optionalObject(item["attributes"], `${at}.attributes`),
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
export function toWireLocation(location, index) {
|
|
145
|
+
const at = `locations[${index}]`;
|
|
146
|
+
const item = requireItem(location, at);
|
|
147
|
+
return compact({
|
|
148
|
+
external_id: requireString(item["externalId"], `${at}.externalId`),
|
|
149
|
+
kind: requireOneOf(item["kind"], LOCATION_LEVELS, `${at}.kind`),
|
|
150
|
+
name: requireString(item["name"], `${at}.name`),
|
|
151
|
+
parent: optionalString(item["parent"], `${at}.parent`),
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
export function toWireAssignment(assignment, index) {
|
|
155
|
+
const at = `assignments[${index}]`;
|
|
156
|
+
const item = requireItem(assignment, at);
|
|
157
|
+
const relation = item["relation"];
|
|
158
|
+
const validFrom = toIso(requireTimestamp(item["validFrom"], `${at}.validFrom`), `${at}.validFrom`);
|
|
159
|
+
const rawValidTo = item["validTo"];
|
|
160
|
+
const validTo = rawValidTo === undefined || rawValidTo === null ? undefined : toIso(rawValidTo, `${at}.validTo`);
|
|
161
|
+
// The API's `invalid_validity_period`: an assignment has to end after it starts.
|
|
162
|
+
if (validTo !== undefined && Date.parse(validTo) <= Date.parse(validFrom)) {
|
|
163
|
+
throw new SinioValidationError(`${at}.validTo must be after validFrom (got ${validFrom} -> ${validTo})`);
|
|
164
|
+
}
|
|
165
|
+
return compact({
|
|
166
|
+
credential: requireString(item["credential"], `${at}.credential`),
|
|
167
|
+
subject: requireString(item["subject"], `${at}.subject`),
|
|
168
|
+
relation: relation === undefined ? undefined : requireOneOf(relation, ASSIGNMENT_RELATIONS, `${at}.relation`),
|
|
169
|
+
valid_from: validFrom,
|
|
170
|
+
valid_to: validTo,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
function requireTimestamp(value, field) {
|
|
174
|
+
if (value === undefined || value === null || value === "") {
|
|
175
|
+
throw new SinioValidationError(`${field} is required`);
|
|
176
|
+
}
|
|
177
|
+
return value;
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=serialize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serialize.js","sourceRoot":"","sources":["../../src/serialize.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import type { AssignmentRelation, EntityKind, EventRole, IngestionMode, LocationLevel, RejectionCode } from "./vocabularies.ts";
|
|
2
|
+
export type { AssignmentRelation, EntityKind, EventRole, IngestionMode, LocationLevel, RejectionCode };
|
|
3
|
+
/**
|
|
4
|
+
* A rejection code as read from a response: one of the known `RejectionCode`s (autocompleted), or
|
|
5
|
+
* any other string the API may add later, kept as is.
|
|
6
|
+
*/
|
|
7
|
+
export type RejectionCodeValue = RejectionCode | (string & {});
|
|
8
|
+
/** A JSON object: `payload` and `attributes` are never an array or a scalar. */
|
|
9
|
+
export type JsonObject = Readonly<Record<string, unknown>>;
|
|
10
|
+
/** An ISO 8601 timestamp *with* an offset, or a `Date`. */
|
|
11
|
+
export type Timestamp = string | Date;
|
|
12
|
+
/**
|
|
13
|
+
* The four structural roles the derivation engine resolves, each a raw, non-empty
|
|
14
|
+
* identifier from the source. Anything else (ticket number, firmware, ...)
|
|
15
|
+
* belongs in `payload`. The API refuses any other key.
|
|
16
|
+
*/
|
|
17
|
+
export type EventRoles = {
|
|
18
|
+
readonly [role in EventRole]?: string;
|
|
19
|
+
};
|
|
20
|
+
export interface SinioEvent {
|
|
21
|
+
/** Identity at the source, stable over time. Part of the idempotency key. */
|
|
22
|
+
readonly sourceEventId: string;
|
|
23
|
+
/** Source-side version, kept for tracing: it plays no part in deduplication. */
|
|
24
|
+
readonly sourceVersion?: string;
|
|
25
|
+
/** Project `external_id`. Only for organization-wide keys (issued on request), which cover several projects; a project key already carries its project. */
|
|
26
|
+
readonly project?: string;
|
|
27
|
+
/** `code` of an event type in the catalog. */
|
|
28
|
+
readonly type: string;
|
|
29
|
+
readonly label?: string;
|
|
30
|
+
/** ISO 8601 with offset. Without an offset the API rejects the event. */
|
|
31
|
+
readonly occurredAt: Timestamp;
|
|
32
|
+
readonly roles?: EventRoles;
|
|
33
|
+
/** Free-form, optional (`{}` when omitted); the readings (battery, signal, ...) are read from it as its source declares them. */
|
|
34
|
+
readonly payload?: JsonObject;
|
|
35
|
+
/** How many units this one event stands for (a button pressed ten times). An integer from 1 to 1,000,000; omitted = 1. */
|
|
36
|
+
readonly count?: number;
|
|
37
|
+
}
|
|
38
|
+
export interface EntityInput {
|
|
39
|
+
readonly externalId: string;
|
|
40
|
+
readonly kind: EntityKind;
|
|
41
|
+
/** Code of the entity's subkind; never empty when given. An unknown code is created undeclared. */
|
|
42
|
+
readonly subkind?: string;
|
|
43
|
+
readonly label?: string;
|
|
44
|
+
/** External id of the location the entity sits in. */
|
|
45
|
+
readonly location?: string;
|
|
46
|
+
/** Free-form JSON object. */
|
|
47
|
+
readonly attributes?: JsonObject;
|
|
48
|
+
}
|
|
49
|
+
export interface LocationInput {
|
|
50
|
+
readonly externalId: string;
|
|
51
|
+
readonly kind: LocationLevel;
|
|
52
|
+
readonly name: string;
|
|
53
|
+
/** External id of the parent location, if any. */
|
|
54
|
+
readonly parent?: string;
|
|
55
|
+
}
|
|
56
|
+
export interface AssignmentInput {
|
|
57
|
+
/** External id of the credential (badge, card, ...). */
|
|
58
|
+
readonly credential: string;
|
|
59
|
+
/** External id of the subject the credential is assigned to. */
|
|
60
|
+
readonly subject: string;
|
|
61
|
+
/** Defaults to `assigned_to`, the only relation today. */
|
|
62
|
+
readonly relation?: AssignmentRelation;
|
|
63
|
+
/** ISO 8601 with offset, or a `Date`. */
|
|
64
|
+
readonly validFrom: Timestamp;
|
|
65
|
+
/** Open-ended when omitted or `null`; otherwise strictly after `validFrom`. */
|
|
66
|
+
readonly validTo?: Timestamp | null;
|
|
67
|
+
}
|
|
68
|
+
export interface EventRejection {
|
|
69
|
+
readonly sourceEventId: string;
|
|
70
|
+
readonly code: RejectionCodeValue;
|
|
71
|
+
readonly message: string;
|
|
72
|
+
}
|
|
73
|
+
export interface ReferenceRejection {
|
|
74
|
+
readonly externalId: string;
|
|
75
|
+
readonly code: RejectionCodeValue;
|
|
76
|
+
readonly message: string;
|
|
77
|
+
}
|
|
78
|
+
export interface AssignmentRejection {
|
|
79
|
+
readonly credential: string;
|
|
80
|
+
readonly subject: string;
|
|
81
|
+
readonly code: RejectionCodeValue;
|
|
82
|
+
readonly message: string;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Outcome of `sendEvents`. `duplicates` and `revisions` are successes, not
|
|
86
|
+
* errors: replaying a batch is expected and never creates anything twice.
|
|
87
|
+
*/
|
|
88
|
+
export interface SendEventsResult {
|
|
89
|
+
/** Server-side batch ids, one per HTTP call the SDK made (batches are chunked at 500). */
|
|
90
|
+
readonly batchIds: readonly string[];
|
|
91
|
+
readonly accepted: number;
|
|
92
|
+
readonly pendingClassification: number;
|
|
93
|
+
readonly duplicates: number;
|
|
94
|
+
readonly revisions: number;
|
|
95
|
+
readonly rejected: number;
|
|
96
|
+
readonly rejections: readonly EventRejection[];
|
|
97
|
+
/** The key is in test mode: its events are checked and kept apart, never used for detection. */
|
|
98
|
+
readonly testMode: boolean;
|
|
99
|
+
}
|
|
100
|
+
export interface UpsertResult {
|
|
101
|
+
readonly accepted: number;
|
|
102
|
+
readonly rejected: number;
|
|
103
|
+
readonly rejections: readonly ReferenceRejection[];
|
|
104
|
+
}
|
|
105
|
+
export interface AssignmentsResult {
|
|
106
|
+
readonly accepted: number;
|
|
107
|
+
readonly rejected: number;
|
|
108
|
+
readonly rejections: readonly AssignmentRejection[];
|
|
109
|
+
}
|
|
110
|
+
export interface SendEventsOptions {
|
|
111
|
+
/** Defaults to `webhook`. */
|
|
112
|
+
readonly mode?: IngestionMode;
|
|
113
|
+
/**
|
|
114
|
+
* Overrides the client-level source code for this call. Only needed for keys not bound to a
|
|
115
|
+
* single source (organization-wide keys, issued on request).
|
|
116
|
+
*/
|
|
117
|
+
readonly sourceCode?: string;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Project override, only for organization-wide API keys (issued on request) covering several
|
|
121
|
+
* projects. A project key already carries its project.
|
|
122
|
+
*/
|
|
123
|
+
export interface ProjectOptions {
|
|
124
|
+
/** Project `external_id`. */
|
|
125
|
+
readonly project?: string;
|
|
126
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Ingestion modes. `backfill` persists history without triggering alerts. */
|
|
2
|
+
export declare const INGESTION_MODES: readonly ["webhook", "backfill"];
|
|
3
|
+
export type IngestionMode = (typeof INGESTION_MODES)[number];
|
|
4
|
+
/** Kinds accepted by `POST /v1/entities`. */
|
|
5
|
+
export declare const ENTITY_KINDS: readonly ["device", "subject", "asset", "actor", "credential"];
|
|
6
|
+
export type EntityKind = (typeof ENTITY_KINDS)[number];
|
|
7
|
+
/** Levels accepted by `POST /v1/locations`. */
|
|
8
|
+
export declare const LOCATION_LEVELS: readonly ["site", "zone", "point"];
|
|
9
|
+
export type LocationLevel = (typeof LOCATION_LEVELS)[number];
|
|
10
|
+
/** Relations accepted by `POST /v1/assignments`; `assigned_to` when omitted. */
|
|
11
|
+
export declare const ASSIGNMENT_RELATIONS: readonly ["assigned_to"];
|
|
12
|
+
export type AssignmentRelation = (typeof ASSIGNMENT_RELATIONS)[number];
|
|
13
|
+
/** The four structural roles an event may carry in `roles`. */
|
|
14
|
+
export declare const EVENT_ROLES: readonly ["device", "subject", "location", "actor"];
|
|
15
|
+
export type EventRole = (typeof EVENT_ROLES)[number];
|
|
16
|
+
/**
|
|
17
|
+
* Codes the API returns in `rejections[].code` today. The list may grow (additive changes): a
|
|
18
|
+
* response carrying a code missing here is passed through unchanged, never refused.
|
|
19
|
+
*/
|
|
20
|
+
export declare const REJECTION_CODES: readonly ["payload_too_large", "unknown_project", "unknown_source", "archived_source", "source_mismatch", "ambiguous_source", "invalid_occurred_at", "missing_required_field", "unknown_location", "unknown_parent_location", "overlapping_assignment", "invalid_validity_period"];
|
|
21
|
+
export type RejectionCode = (typeof REJECTION_CODES)[number];
|
|
22
|
+
/** Whether a rejection code is one this SDK version knows, narrowing it to `RejectionCode`. */
|
|
23
|
+
export declare function isKnownRejectionCode(code: string): code is RejectionCode;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// The closed vocabularies of the ingestion API, each defined once: the value list (used by the local
|
|
2
|
+
// checks) and the type derived from it. They mirror the API contract exactly.
|
|
3
|
+
/** Ingestion modes. `backfill` persists history without triggering alerts. */
|
|
4
|
+
export const INGESTION_MODES = ["webhook", "backfill"];
|
|
5
|
+
/** Kinds accepted by `POST /v1/entities`. */
|
|
6
|
+
export const ENTITY_KINDS = ["device", "subject", "asset", "actor", "credential"];
|
|
7
|
+
/** Levels accepted by `POST /v1/locations`. */
|
|
8
|
+
export const LOCATION_LEVELS = ["site", "zone", "point"];
|
|
9
|
+
/** Relations accepted by `POST /v1/assignments`; `assigned_to` when omitted. */
|
|
10
|
+
export const ASSIGNMENT_RELATIONS = ["assigned_to"];
|
|
11
|
+
/** The four structural roles an event may carry in `roles`. */
|
|
12
|
+
export const EVENT_ROLES = ["device", "subject", "location", "actor"];
|
|
13
|
+
/**
|
|
14
|
+
* Codes the API returns in `rejections[].code` today. The list may grow (additive changes): a
|
|
15
|
+
* response carrying a code missing here is passed through unchanged, never refused.
|
|
16
|
+
*/
|
|
17
|
+
export const REJECTION_CODES = [
|
|
18
|
+
"payload_too_large",
|
|
19
|
+
"unknown_project",
|
|
20
|
+
"unknown_source",
|
|
21
|
+
"archived_source",
|
|
22
|
+
"source_mismatch",
|
|
23
|
+
"ambiguous_source",
|
|
24
|
+
"invalid_occurred_at",
|
|
25
|
+
"missing_required_field",
|
|
26
|
+
"unknown_location",
|
|
27
|
+
"unknown_parent_location",
|
|
28
|
+
"overlapping_assignment",
|
|
29
|
+
"invalid_validity_period",
|
|
30
|
+
];
|
|
31
|
+
/** Whether a rejection code is one this SDK version knows, narrowing it to `RejectionCode`. */
|
|
32
|
+
export function isKnownRejectionCode(code) {
|
|
33
|
+
return REJECTION_CODES.includes(code);
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=vocabularies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vocabularies.js","sourceRoot":"","sources":["../../src/vocabularies.ts"],"names":[],"mappings":"AAAA,qGAAqG;AACrG,8EAA8E;AAE9E,8EAA8E;AAC9E,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,SAAS,EAAE,UAAU,CAAU,CAAC;AAGhE,6CAA6C;AAC7C,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,CAAU,CAAC;AAG3F,+CAA+C;AAC/C,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAU,CAAC;AAGlE,gFAAgF;AAChF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,aAAa,CAAU,CAAC;AAG7D,+DAA+D;AAC/D,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,CAAU,CAAC;AAG/E;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,mBAAmB;IACnB,iBAAiB;IACjB,gBAAgB;IAChB,iBAAiB;IACjB,iBAAiB;IACjB,kBAAkB;IAClB,qBAAqB;IACrB,wBAAwB;IACxB,kBAAkB;IAClB,yBAAyB;IACzB,wBAAwB;IACxB,yBAAyB;CACjB,CAAC;AAGX,+FAA+F;AAC/F,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,OAAQ,eAAqC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC/D,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,45 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sinio/sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Official Node.js SDK for the sinio.ai ingestion API (events, entities, locations, assignments).",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"homepage": "https://docs.sinio.ai/sdks",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/sinio-ai/sinio-node.git"
|
|
10
|
+
},
|
|
11
|
+
"bugs": "https://github.com/sinio-ai/sinio-node/issues",
|
|
12
|
+
"type": "module",
|
|
13
|
+
"main": "./dist/cjs/index.js",
|
|
14
|
+
"types": "./dist/esm/index.d.ts",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/esm/index.d.ts",
|
|
18
|
+
"import": "./dist/esm/index.js",
|
|
19
|
+
"require": "./dist/cjs/index.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"README.md",
|
|
25
|
+
"LICENSE"
|
|
26
|
+
],
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": ">=18"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.json && tsc -p tsconfig.cjs.json && echo '{\"type\":\"commonjs\"}' > dist/cjs/package.json",
|
|
32
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
33
|
+
"test": "tsc -p tsconfig.json --noEmit && node --test --experimental-strip-types test/*.test.ts"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@types/node": "^22.10.0",
|
|
37
|
+
"typescript": "^5.7.0"
|
|
38
|
+
},
|
|
39
|
+
"keywords": [
|
|
40
|
+
"sinio",
|
|
41
|
+
"events",
|
|
42
|
+
"ingestion",
|
|
43
|
+
"sdk"
|
|
44
|
+
]
|
|
45
|
+
}
|