@arcote.tech/arc-utils 0.4.1
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/package.json +16 -0
- package/src/arc.d.ts +6 -0
- package/src/index.ts +1 -0
- package/src/simple-aggregate.ts +65 -0
package/package.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@arcote.tech/arc-utils",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.4.1",
|
|
5
|
+
"private": false,
|
|
6
|
+
"description": "Reusable helpers for Arc framework — simpleAggregate and more",
|
|
7
|
+
"main": "./src/index.ts",
|
|
8
|
+
"types": "./src/index.ts",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"type-check": "tsc --noEmit"
|
|
11
|
+
},
|
|
12
|
+
"peerDependencies": {
|
|
13
|
+
"@arcote.tech/arc": "workspace:*",
|
|
14
|
+
"typescript": "^5.0.0"
|
|
15
|
+
}
|
|
16
|
+
}
|
package/src/arc.d.ts
ADDED
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { simpleAggregate } from "./simple-aggregate";
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { aggregate, ArcOptional } from "@arcote.tech/arc";
|
|
2
|
+
import type { ArcIdAny, ArcElement } from "@arcote.tech/arc";
|
|
3
|
+
import type { ArcRawShape } from "@arcote.tech/arc";
|
|
4
|
+
|
|
5
|
+
/** Make all schema fields optional by wrapping in ArcOptional */
|
|
6
|
+
type OptionalShape<S extends ArcRawShape> = {
|
|
7
|
+
[K in keyof S]: ArcOptional<S[K]>;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
function makeOptional<S extends ArcRawShape>(schema: S): OptionalShape<S> {
|
|
11
|
+
const result = {} as Record<string, ArcElement>;
|
|
12
|
+
for (const [key, field] of Object.entries(schema)) {
|
|
13
|
+
result[key] = field instanceof ArcOptional
|
|
14
|
+
? field
|
|
15
|
+
: new ArcOptional(field);
|
|
16
|
+
}
|
|
17
|
+
return result as OptionalShape<S>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Create a simple CRUD aggregate with auto-generated upsert event and update method.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* const Task = simpleAggregate("task", taskId, {
|
|
26
|
+
* title: string(),
|
|
27
|
+
* done: boolean(),
|
|
28
|
+
* });
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export function simpleAggregate<
|
|
32
|
+
const Name extends string,
|
|
33
|
+
Id extends ArcIdAny,
|
|
34
|
+
SchemaShape extends ArcRawShape,
|
|
35
|
+
>(name: Name, id: Id, schema: SchemaShape) {
|
|
36
|
+
const eventName = `${name}Updated`;
|
|
37
|
+
const optionalSchema = makeOptional(schema);
|
|
38
|
+
|
|
39
|
+
return aggregate(name, id, schema)
|
|
40
|
+
.publicEvent(
|
|
41
|
+
eventName,
|
|
42
|
+
{ _id: id, ...optionalSchema },
|
|
43
|
+
async (ctx, event) => {
|
|
44
|
+
const p = event.payload as Record<string, unknown>;
|
|
45
|
+
const idValue = p._id as any;
|
|
46
|
+
const partial: Record<string, unknown> = {};
|
|
47
|
+
for (const key of Object.keys(schema)) {
|
|
48
|
+
if (p[key] !== undefined) partial[key] = p[key];
|
|
49
|
+
}
|
|
50
|
+
if (await ctx.findOne({ _id: idValue })) {
|
|
51
|
+
await ctx.modify(idValue, partial as any);
|
|
52
|
+
} else {
|
|
53
|
+
await ctx.set(idValue, partial as any);
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
)
|
|
57
|
+
.mutateMethod(
|
|
58
|
+
"update",
|
|
59
|
+
{ params: { _id: id, ...optionalSchema } },
|
|
60
|
+
ONLY_SERVER &&
|
|
61
|
+
(async (ctx, params) => {
|
|
62
|
+
await (ctx as any)[eventName].emit(params);
|
|
63
|
+
}),
|
|
64
|
+
);
|
|
65
|
+
}
|