@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 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
@@ -0,0 +1,6 @@
1
+ declare const BROWSER: boolean;
2
+ declare const NOT_ON_BROWSER: boolean;
3
+ declare const ONLY_BROWSER: boolean;
4
+ declare const SERVER: boolean;
5
+ declare const NOT_ON_SERVER: boolean;
6
+ declare const ONLY_SERVER: boolean;
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
+ }