@almadar/server 2.1.1 → 2.1.3
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/dist/contracts.d.ts +174 -0
- package/dist/contracts.d.ts.map +1 -0
- package/dist/deepagent/memory.d.ts +16 -0
- package/dist/deepagent/memory.d.ts.map +1 -0
- package/dist/deepagent/session.d.ts +16 -0
- package/dist/deepagent/session.d.ts.map +1 -0
- package/dist/deepagent/skill-agent.d.ts +22 -0
- package/dist/deepagent/skill-agent.d.ts.map +1 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2616 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/db.d.ts +36 -0
- package/dist/lib/db.d.ts.map +1 -0
- package/dist/lib/debugRouter.d.ts +21 -0
- package/dist/lib/debugRouter.d.ts.map +1 -0
- package/dist/lib/env.d.ts +16 -0
- package/dist/lib/env.d.ts.map +1 -0
- package/dist/lib/eventBus.d.ts +44 -0
- package/dist/lib/eventBus.d.ts.map +1 -0
- package/dist/lib/eventBusTransport.d.ts +143 -0
- package/dist/lib/eventBusTransport.d.ts.map +1 -0
- package/dist/lib/eventPersistence.d.ts +151 -0
- package/dist/lib/eventPersistence.d.ts.map +1 -0
- package/dist/lib/index.d.ts +6 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +288 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/logger.d.ts +7 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/serviceDiscovery.d.ts +168 -0
- package/dist/lib/serviceDiscovery.d.ts.map +1 -0
- package/dist/lib/websocket.d.ts +41 -0
- package/dist/lib/websocket.d.ts.map +1 -0
- package/dist/middleware/authenticateFirebase.d.ts +4 -0
- package/dist/middleware/authenticateFirebase.d.ts.map +1 -0
- package/dist/middleware/errorHandler.d.ts +53 -0
- package/dist/middleware/errorHandler.d.ts.map +1 -0
- package/dist/middleware/index.d.ts +4 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +284 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/multi-user.d.ts +34 -0
- package/dist/middleware/multi-user.d.ts.map +1 -0
- package/dist/middleware/validation.d.ts +15 -0
- package/dist/middleware/validation.d.ts.map +1 -0
- package/dist/routes/observability.d.ts +11 -0
- package/dist/routes/observability.d.ts.map +1 -0
- package/dist/services/DataService.d.ts +70 -0
- package/dist/services/DataService.d.ts.map +1 -0
- package/dist/services/MockDataService.d.ts +110 -0
- package/dist/services/MockDataService.d.ts.map +1 -0
- package/dist/services/index.d.ts +8 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +735 -0
- package/dist/services/index.js.map +1 -0
- package/dist/stores/ChangeSetStore.d.ts +24 -0
- package/dist/stores/ChangeSetStore.d.ts.map +1 -0
- package/dist/stores/SchemaProtectionService.d.ts +23 -0
- package/dist/stores/SchemaProtectionService.d.ts.map +1 -0
- package/dist/stores/SchemaStore.d.ts +52 -0
- package/dist/stores/SchemaStore.d.ts.map +1 -0
- package/dist/stores/SnapshotStore.d.ts +26 -0
- package/dist/stores/SnapshotStore.d.ts.map +1 -0
- package/dist/stores/ValidationStore.d.ts +19 -0
- package/dist/stores/ValidationStore.d.ts.map +1 -0
- package/dist/stores/firestoreFormat.d.ts +21 -0
- package/dist/stores/firestoreFormat.d.ts.map +1 -0
- package/dist/stores/index.d.ts +14 -0
- package/dist/stores/index.d.ts.map +1 -0
- package/dist/stores/index.js +519 -0
- package/dist/stores/index.js.map +1 -0
- package/dist/utils/index.d.ts +9 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +106 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/queryFilters.d.ts +87 -0
- package/dist/utils/queryFilters.d.ts.map +1 -0
- package/dist/websocket/state-sync.d.ts +39 -0
- package/dist/websocket/state-sync.d.ts.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// src/utils/queryFilters.ts
|
|
2
|
+
var OPERATOR_MAP = {
|
|
3
|
+
"eq": "==",
|
|
4
|
+
"neq": "!=",
|
|
5
|
+
"gt": ">",
|
|
6
|
+
"gte": ">=",
|
|
7
|
+
"lt": "<",
|
|
8
|
+
"lte": "<=",
|
|
9
|
+
"contains": "array-contains",
|
|
10
|
+
"contains_any": "array-contains-any",
|
|
11
|
+
"in": "in",
|
|
12
|
+
"not_in": "not-in",
|
|
13
|
+
// Date operators map to same comparison operators
|
|
14
|
+
"date_eq": "==",
|
|
15
|
+
"date_gte": ">=",
|
|
16
|
+
"date_lte": "<="
|
|
17
|
+
};
|
|
18
|
+
var RESERVED_PARAMS = /* @__PURE__ */ new Set([
|
|
19
|
+
"page",
|
|
20
|
+
"pageSize",
|
|
21
|
+
"limit",
|
|
22
|
+
"offset",
|
|
23
|
+
"search",
|
|
24
|
+
"q",
|
|
25
|
+
"sortBy",
|
|
26
|
+
"sortOrder",
|
|
27
|
+
"orderBy",
|
|
28
|
+
"orderDirection"
|
|
29
|
+
]);
|
|
30
|
+
function parseQueryFilters(query) {
|
|
31
|
+
const filters = [];
|
|
32
|
+
for (const [key, value] of Object.entries(query)) {
|
|
33
|
+
if (RESERVED_PARAMS.has(key)) continue;
|
|
34
|
+
if (value === void 0 || value === null || value === "") continue;
|
|
35
|
+
const match = key.match(/^(.+)__(\w+)$/);
|
|
36
|
+
if (match) {
|
|
37
|
+
const [, field, op] = match;
|
|
38
|
+
const firestoreOp = OPERATOR_MAP[op];
|
|
39
|
+
if (firestoreOp) {
|
|
40
|
+
filters.push({
|
|
41
|
+
field,
|
|
42
|
+
operator: firestoreOp,
|
|
43
|
+
value: parseValue(value, op)
|
|
44
|
+
});
|
|
45
|
+
} else {
|
|
46
|
+
filters.push({
|
|
47
|
+
field: key,
|
|
48
|
+
operator: "==",
|
|
49
|
+
value: parseValue(value, "eq")
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
} else {
|
|
53
|
+
filters.push({
|
|
54
|
+
field: key,
|
|
55
|
+
operator: "==",
|
|
56
|
+
value: parseValue(value, "eq")
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return filters;
|
|
61
|
+
}
|
|
62
|
+
function parseValue(value, operator) {
|
|
63
|
+
if (operator === "in" || operator === "not_in" || operator === "contains_any") {
|
|
64
|
+
if (typeof value === "string") {
|
|
65
|
+
return value.split(",").map((v) => v.trim());
|
|
66
|
+
}
|
|
67
|
+
if (Array.isArray(value)) {
|
|
68
|
+
return value;
|
|
69
|
+
}
|
|
70
|
+
return [value];
|
|
71
|
+
}
|
|
72
|
+
if (typeof value === "string") {
|
|
73
|
+
if (/^-?\d+(\.\d+)?$/.test(value)) {
|
|
74
|
+
const num = parseFloat(value);
|
|
75
|
+
if (!isNaN(num)) {
|
|
76
|
+
return num;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (value === "true") return true;
|
|
80
|
+
if (value === "false") return false;
|
|
81
|
+
}
|
|
82
|
+
return value;
|
|
83
|
+
}
|
|
84
|
+
function applyFiltersToQuery(collection, filters) {
|
|
85
|
+
let query = collection;
|
|
86
|
+
for (const filter of filters) {
|
|
87
|
+
query = query.where(
|
|
88
|
+
filter.field,
|
|
89
|
+
filter.operator,
|
|
90
|
+
filter.value
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
return query;
|
|
94
|
+
}
|
|
95
|
+
function extractPaginationParams(query, defaults = {}) {
|
|
96
|
+
return {
|
|
97
|
+
page: parseInt(query.page, 10) || defaults.page || 1,
|
|
98
|
+
pageSize: parseInt(query.pageSize, 10) || parseInt(query.limit, 10) || defaults.pageSize || 20,
|
|
99
|
+
sortBy: query.sortBy || query.orderBy,
|
|
100
|
+
sortOrder: query.sortOrder || query.orderDirection || defaults.sortOrder || "asc"
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export { applyFiltersToQuery, extractPaginationParams, parseQueryFilters };
|
|
105
|
+
//# sourceMappingURL=index.js.map
|
|
106
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/queryFilters.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Query Filter Utilities\n *\n * Parses URL query parameters into Firestore-compatible filter objects.\n * Supports operator encoding in parameter names: field__operator=value\n *\n * @example\n * // URL: /api/tasks?status=active&date__gte=2025-01-01&tags__contains=urgent\n * const filters = parseQueryFilters(req.query);\n * // Returns:\n * // [\n * // { field: 'status', operator: '==', value: 'active' },\n * // { field: 'date', operator: '>=', value: '2025-01-01' },\n * // { field: 'tags', operator: 'array-contains', value: 'urgent' }\n * // ]\n *\n * @packageDocumentation\n */\n\n/**\n * Parsed filter ready for Firestore query\n */\nexport interface ParsedFilter {\n field: string;\n operator: FirestoreWhereFilterOp;\n value: unknown;\n}\n\n/**\n * Firestore where filter operators\n */\nexport type FirestoreWhereFilterOp =\n | '=='\n | '!='\n | '>'\n | '>='\n | '<'\n | '<='\n | 'array-contains'\n | 'array-contains-any'\n | 'in'\n | 'not-in';\n\n/**\n * Map of URL operator suffixes to Firestore operators\n */\nconst OPERATOR_MAP: Record<string, FirestoreWhereFilterOp> = {\n 'eq': '==',\n 'neq': '!=',\n 'gt': '>',\n 'gte': '>=',\n 'lt': '<',\n 'lte': '<=',\n 'contains': 'array-contains',\n 'contains_any': 'array-contains-any',\n 'in': 'in',\n 'not_in': 'not-in',\n // Date operators map to same comparison operators\n 'date_eq': '==',\n 'date_gte': '>=',\n 'date_lte': '<=',\n};\n\n/**\n * Reserved query parameters that should not be treated as filters\n */\nconst RESERVED_PARAMS = new Set([\n 'page',\n 'pageSize',\n 'limit',\n 'offset',\n 'search',\n 'q',\n 'sortBy',\n 'sortOrder',\n 'orderBy',\n 'orderDirection',\n]);\n\n/**\n * Parse query parameters into Firestore-compatible filters.\n *\n * Supports operator encoding: field__operator=value\n *\n * @param query - Express req.query object\n * @returns Array of parsed filters ready for Firestore .where() calls\n *\n * @example\n * ```typescript\n * // In Express route handler:\n * const filters = parseQueryFilters(req.query);\n *\n * let query = db.collection('tasks');\n * for (const filter of filters) {\n * query = query.where(filter.field, filter.operator, filter.value);\n * }\n * ```\n */\nexport function parseQueryFilters(\n query: Record<string, unknown>\n): ParsedFilter[] {\n const filters: ParsedFilter[] = [];\n\n for (const [key, value] of Object.entries(query)) {\n // Skip reserved pagination/sort params\n if (RESERVED_PARAMS.has(key)) continue;\n\n // Skip empty values\n if (value === undefined || value === null || value === '') continue;\n\n // Parse operator from key: field__operator → { field, operator }\n const match = key.match(/^(.+)__(\\w+)$/);\n\n if (match) {\n const [, field, op] = match;\n const firestoreOp = OPERATOR_MAP[op];\n\n if (firestoreOp) {\n filters.push({\n field,\n operator: firestoreOp,\n value: parseValue(value, op),\n });\n } else {\n // Unknown operator - treat as field name with double underscore\n filters.push({\n field: key,\n operator: '==',\n value: parseValue(value, 'eq'),\n });\n }\n } else {\n // No operator suffix → equals\n filters.push({\n field: key,\n operator: '==',\n value: parseValue(value, 'eq'),\n });\n }\n }\n\n return filters;\n}\n\n/**\n * Parse and coerce value based on operator type\n */\nfunction parseValue(value: unknown, operator: string): unknown {\n // Handle array values for 'in' operator\n if (operator === 'in' || operator === 'not_in' || operator === 'contains_any') {\n if (typeof value === 'string') {\n // Parse comma-separated values: \"a,b,c\" → ['a', 'b', 'c']\n return value.split(',').map(v => v.trim());\n }\n if (Array.isArray(value)) {\n return value;\n }\n return [value];\n }\n\n // Handle numeric values\n if (typeof value === 'string') {\n // Try to parse as number if it looks like one\n if (/^-?\\d+(\\.\\d+)?$/.test(value)) {\n const num = parseFloat(value);\n if (!isNaN(num)) {\n return num;\n }\n }\n\n // Handle boolean strings\n if (value === 'true') return true;\n if (value === 'false') return false;\n }\n\n return value;\n}\n\n/**\n * Build a Firestore query with filters applied.\n *\n * @param collection - Base Firestore collection reference or query\n * @param filters - Parsed filters from parseQueryFilters\n * @returns Query with all filters applied\n *\n * @example\n * ```typescript\n * const filters = parseQueryFilters(req.query);\n * const baseQuery = db.collection('tasks');\n * const filteredQuery = applyFiltersToQuery(baseQuery, filters);\n * const snapshot = await filteredQuery.get();\n * ```\n */\nexport function applyFiltersToQuery<T>(\n collection: FirebaseFirestore.Query<T>,\n filters: ParsedFilter[]\n): FirebaseFirestore.Query<T> {\n let query = collection;\n\n for (const filter of filters) {\n query = query.where(\n filter.field,\n filter.operator as FirebaseFirestore.WhereFilterOp,\n filter.value\n );\n }\n\n return query;\n}\n\n/**\n * Extract pagination parameters from query\n */\nexport interface PaginationParams {\n page: number;\n pageSize: number;\n sortBy?: string;\n sortOrder: 'asc' | 'desc';\n}\n\n/**\n * Extract pagination parameters from a query object.\n *\n * Parses page, pageSize/limit, sortBy/orderBy, and sortOrder/orderDirection\n * from query parameters with sensible defaults.\n *\n * @param {Record<string, unknown>} query - Query object containing pagination params\n * @param {Partial<PaginationParams>} [defaults] - Default values for pagination\n * @returns {PaginationParams} Extracted pagination parameters\n */\nexport function extractPaginationParams(\n query: Record<string, unknown>,\n defaults: Partial<PaginationParams> = {}\n): PaginationParams {\n return {\n page: parseInt(query.page as string, 10) || defaults.page || 1,\n pageSize: parseInt(query.pageSize as string, 10) || parseInt(query.limit as string, 10) || defaults.pageSize || 20,\n sortBy: (query.sortBy || query.orderBy) as string | undefined,\n sortOrder: ((query.sortOrder || query.orderDirection) as 'asc' | 'desc') || defaults.sortOrder || 'asc',\n };\n}\n"]}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Query Filter Utilities
|
|
3
|
+
*
|
|
4
|
+
* Parses URL query parameters into Firestore-compatible filter objects.
|
|
5
|
+
* Supports operator encoding in parameter names: field__operator=value
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* // URL: /api/tasks?status=active&date__gte=2025-01-01&tags__contains=urgent
|
|
9
|
+
* const filters = parseQueryFilters(req.query);
|
|
10
|
+
* // Returns:
|
|
11
|
+
* // [
|
|
12
|
+
* // { field: 'status', operator: '==', value: 'active' },
|
|
13
|
+
* // { field: 'date', operator: '>=', value: '2025-01-01' },
|
|
14
|
+
* // { field: 'tags', operator: 'array-contains', value: 'urgent' }
|
|
15
|
+
* // ]
|
|
16
|
+
*
|
|
17
|
+
* @packageDocumentation
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Parsed filter ready for Firestore query
|
|
21
|
+
*/
|
|
22
|
+
export interface ParsedFilter {
|
|
23
|
+
field: string;
|
|
24
|
+
operator: FirestoreWhereFilterOp;
|
|
25
|
+
value: unknown;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Firestore where filter operators
|
|
29
|
+
*/
|
|
30
|
+
export type FirestoreWhereFilterOp = '==' | '!=' | '>' | '>=' | '<' | '<=' | 'array-contains' | 'array-contains-any' | 'in' | 'not-in';
|
|
31
|
+
/**
|
|
32
|
+
* Parse query parameters into Firestore-compatible filters.
|
|
33
|
+
*
|
|
34
|
+
* Supports operator encoding: field__operator=value
|
|
35
|
+
*
|
|
36
|
+
* @param query - Express req.query object
|
|
37
|
+
* @returns Array of parsed filters ready for Firestore .where() calls
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* // In Express route handler:
|
|
42
|
+
* const filters = parseQueryFilters(req.query);
|
|
43
|
+
*
|
|
44
|
+
* let query = db.collection('tasks');
|
|
45
|
+
* for (const filter of filters) {
|
|
46
|
+
* query = query.where(filter.field, filter.operator, filter.value);
|
|
47
|
+
* }
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare function parseQueryFilters(query: Record<string, unknown>): ParsedFilter[];
|
|
51
|
+
/**
|
|
52
|
+
* Build a Firestore query with filters applied.
|
|
53
|
+
*
|
|
54
|
+
* @param collection - Base Firestore collection reference or query
|
|
55
|
+
* @param filters - Parsed filters from parseQueryFilters
|
|
56
|
+
* @returns Query with all filters applied
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* const filters = parseQueryFilters(req.query);
|
|
61
|
+
* const baseQuery = db.collection('tasks');
|
|
62
|
+
* const filteredQuery = applyFiltersToQuery(baseQuery, filters);
|
|
63
|
+
* const snapshot = await filteredQuery.get();
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export declare function applyFiltersToQuery<T>(collection: FirebaseFirestore.Query<T>, filters: ParsedFilter[]): FirebaseFirestore.Query<T>;
|
|
67
|
+
/**
|
|
68
|
+
* Extract pagination parameters from query
|
|
69
|
+
*/
|
|
70
|
+
export interface PaginationParams {
|
|
71
|
+
page: number;
|
|
72
|
+
pageSize: number;
|
|
73
|
+
sortBy?: string;
|
|
74
|
+
sortOrder: 'asc' | 'desc';
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Extract pagination parameters from a query object.
|
|
78
|
+
*
|
|
79
|
+
* Parses page, pageSize/limit, sortBy/orderBy, and sortOrder/orderDirection
|
|
80
|
+
* from query parameters with sensible defaults.
|
|
81
|
+
*
|
|
82
|
+
* @param {Record<string, unknown>} query - Query object containing pagination params
|
|
83
|
+
* @param {Partial<PaginationParams>} [defaults] - Default values for pagination
|
|
84
|
+
* @returns {PaginationParams} Extracted pagination parameters
|
|
85
|
+
*/
|
|
86
|
+
export declare function extractPaginationParams(query: Record<string, unknown>, defaults?: Partial<PaginationParams>): PaginationParams;
|
|
87
|
+
//# sourceMappingURL=queryFilters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queryFilters.d.ts","sourceRoot":"","sources":["../../src/utils/queryFilters.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,sBAAsB,CAAC;IACjC,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAC9B,IAAI,GACJ,IAAI,GACJ,GAAG,GACH,IAAI,GACJ,GAAG,GACH,IAAI,GACJ,gBAAgB,GAChB,oBAAoB,GACpB,IAAI,GACJ,QAAQ,CAAC;AAsCb;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,YAAY,EAAE,CA0ChB;AAoCD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EACnC,UAAU,EAAE,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC,EACtC,OAAO,EAAE,YAAY,EAAE,GACtB,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC,CAY5B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,KAAK,GAAG,MAAM,CAAC;CAC3B;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,QAAQ,GAAE,OAAO,CAAC,gBAAgB,CAAM,GACvC,gBAAgB,CAOlB"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State Sync WebSocket Handler
|
|
3
|
+
*
|
|
4
|
+
* Provides real-time state synchronization using Socket.IO.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
interface Socket {
|
|
9
|
+
data: {
|
|
10
|
+
user: {
|
|
11
|
+
uid: string;
|
|
12
|
+
roles: string[];
|
|
13
|
+
orgId?: string;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
handshake: {
|
|
17
|
+
auth: {
|
|
18
|
+
token: string;
|
|
19
|
+
clientId: string;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
join: (room: string) => void;
|
|
23
|
+
leave: (room: string) => void;
|
|
24
|
+
on: (event: string, handler: (...args: unknown[]) => void) => void;
|
|
25
|
+
emit: (event: string, ...args: unknown[]) => void;
|
|
26
|
+
to: (room: string) => {
|
|
27
|
+
emit: (event: string, ...args: unknown[]) => void;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
interface SocketServer {
|
|
31
|
+
use: (middleware: (socket: Socket, next: (err?: Error) => void) => void) => void;
|
|
32
|
+
on: (event: string, handler: (socket: Socket) => void) => void;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Set up state sync WebSocket with Firebase Auth
|
|
36
|
+
*/
|
|
37
|
+
export declare function setupStateSyncWebSocket(io: SocketServer): Promise<void>;
|
|
38
|
+
export {};
|
|
39
|
+
//# sourceMappingURL=state-sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-sync.d.ts","sourceRoot":"","sources":["../../src/websocket/state-sync.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,UAAU,MAAM;IACd,IAAI,EAAE;QAAE,IAAI,EAAE;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,EAAE,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IACjE,SAAS,EAAE;QAAE,IAAI,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IACzD,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,KAAK,IAAI,CAAC;IACnE,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAClD,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK;QAAE,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;KAAE,CAAC;CAC7E;AAED,UAAU,YAAY;IACpB,GAAG,EAAE,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,CAAC;IACjF,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,KAAK,IAAI,CAAC;CAChE;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,EAAE,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAqE7E"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@almadar/server",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.3",
|
|
4
4
|
"description": "Shared server infrastructure for Almadar applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
],
|
|
89
89
|
"homepage": "https://github.com/almadar-io/almadar#readme",
|
|
90
90
|
"scripts": {
|
|
91
|
-
"build": "tsup && tsc
|
|
91
|
+
"build": "tsup && tsc -p tsconfig.decl.json",
|
|
92
92
|
"build:watch": "tsup --watch",
|
|
93
93
|
"lint": "eslint src/",
|
|
94
94
|
"typecheck": "tsc --noEmit",
|