Skip to content

Commit b4adb0a

Browse files
committed
Special fieldName for keys
This diff introduces a special fieldName when we want to create an index that involves the key. For example, imagine a collection where the keys are `K`, and the values are `{field1: V1, field2: V2}` and we want to create an index `V2:K`, the way we would do it would be with: ``` .map(IndexMapper, 'field2', '$key') ``` The `$key` is treated as a special keyword that will be interpreted as the key. Of course, the unfortunate scenario, is if one of the fields is actually named '$key', in which case the user will have to roll out their own index, or apply some kind of transformation before the map, for example: ``` .map(TranformDollarKeyFieldToSomethingElse) .map(IndexMapper, 'field2', 'theNewNameOfTheDollarKeyField' ```
1 parent 23d1302 commit b4adb0a

4 files changed

Lines changed: 29 additions & 20 deletions

File tree

skipruntime-ts/examples/skipsocial-client.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,10 @@ await fetchJSON(
9191
);
9292

9393
const friends2 = await fetchJSON(`${url}/friend/${userID1}`, "GET", header);
94+
const areFriends = await fetchJSON(`${url}/friend-index/${userID1}:${userID2}`, "GET", header);
9495

9596
console.log(friends2);
97+
console.log(areFriends);
9698

9799
/*****************************************************************************/
98100
/* Testing messages */

skipruntime-ts/examples/skipsocial-server.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,7 @@ createPUT("friend-request", "friendRequests", async (runtime, id, object) => {
376376
/*****************************************************************************/
377377

378378
createGET("friend", "friends");
379+
createGET("friend-index", "friendIndex");
379380

380381
/*****************************************************************************/
381382
/* Messages */
@@ -470,7 +471,7 @@ createPUT("group-member", "groupMembers", async (runtime, id, object) => {
470471
await checkIsNotTakenID({
471472
runtime,
472473
desc: "The groupID:memberID",
473-
resource: "groupMemberPairs",
474+
resource: "groupMemberIndex",
474475
id: groupID + ":" + userID,
475476
});
476477
});

skipruntime-ts/examples/skipsocial-utils.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@ export function makeID<T>(x: T): ID<T> {
1616
return JSON.stringify(x);
1717
}
1818

19-
export class IndexMapper implements Mapper<string, TJSON, string, boolean> {
19+
const keyName: string = "$key";
20+
21+
export class IndexMapper implements Mapper<TJSON, TJSON, string, boolean> {
2022
private fieldNames: string[];
2123
constructor(...fieldNames: string[]) {
2224
this.fieldNames = fieldNames;
2325
}
2426
mapElement(
25-
_key: string,
27+
key: TJSON,
2628
values: NonEmptyIterator<unknown>,
2729
): Iterable<[string, boolean]> {
2830
let result: Array<[string, boolean]> = [];
@@ -35,6 +37,26 @@ export class IndexMapper implements Mapper<string, TJSON, string, boolean> {
3537
}
3638
const fieldValues = [];
3739
for (const fieldName of this.fieldNames) {
40+
if(fieldName === keyName) {
41+
if (typeof key !== "string") {
42+
throw new Error(
43+
"Object field is not a string " +
44+
fieldName +
45+
": " +
46+
JSON.stringify(value),
47+
);
48+
}
49+
if (key.includes(":")) {
50+
throw new Error(
51+
"Malformed key (it contains a ':')" +
52+
fieldName +
53+
": " +
54+
JSON.stringify(value),
55+
);
56+
}
57+
fieldValues.push(key);
58+
continue;
59+
}
3860
if (!(fieldName in value)) {
3961
throw new Error(
4062
"Object does not define the field " +

skipruntime-ts/examples/skipsocial.ts

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import type {
1111
import { runService } from "@skipruntime/server";
1212
import {
1313
type ID,
14-
makeID,
1514
makeRequestCollection,
1615
IndexMapper,
1716
} from "./skipsocial-utils.js";
@@ -161,21 +160,6 @@ class FriendIndexResource implements Resource {
161160
}
162161
}
163162

164-
class FriendIndexMapper implements Mapper<ID<User>, Friend, string, boolean> {
165-
mapElement(
166-
userID: ID<User>,
167-
friends: NonEmptyIterator<Friend>,
168-
): Iterable<[ID<[User, User]>, boolean]> {
169-
let result: Array<[string, boolean]> = [];
170-
for (const friend of friends) {
171-
if (userID < friend.friendID) {
172-
result.push([makeID([userID, friend.friendID]), true]);
173-
}
174-
}
175-
return result;
176-
}
177-
}
178-
179163
/*****************************************************************************/
180164
// Messages and channels
181165
/*****************************************************************************/
@@ -407,7 +391,7 @@ class Service implements SkipService {
407391
const friendRequests = inputCollections.friendRequests;
408392
const friendRequestsIndex = friendRequests.map(IndexMapper, "from", "to");
409393
const friends = makeRequestCollection(friendRequests).map(FriendMapper);
410-
const friendIndex = friends.map(FriendIndexMapper);
394+
const friendIndex = friends.map(IndexMapper, "$key", 'friendID');
411395
const groupMemberIndex = inputCollections.groupMembers.map(
412396
IndexMapper,
413397
"groupID",

0 commit comments

Comments
 (0)