From ac4afb4f927bf77d3a3e9812bcf5a5abccb6f598 Mon Sep 17 00:00:00 2001
From: Hunter Perrin
- The Nymph Node Client let's you do everything the Nymph Client does, but
- from Node.JS instead of the browser.
+ The Nymph Node Client lets you do everything the Nymph Client does, but from
+ Node.JS instead of the browser.
You can set limit, offset, sort, and reverse like this.
@@ -172,7 +172,7 @@ async function doQuery() {Check for a tag.
<tag>
or <!tag>
{''}
or {''}
{'name<{refclassname inner query}>'}
or
{'name!<{refclassname inner query}>'}
Check a prop's value is greater than a given value.
name>number
{'name>number'}
name>relative
+ {'name>relative'}
now
or
@@ -317,7 +317,7 @@ async function doQuery() {
name>"relative time value"
+ {'name>"relative time value"'}
Check a prop's value is greater than or equal to a given value.
- name>=number
+ {'name>=number'}
-
-
name>=relative
+ {'name>=relative'}
-
(A single relative time value like
now
or
@@ -348,7 +348,7 @@ async function doQuery() {
-
-
name>="relative time value"
+ {'name>="relative time value"'}
-
(Use this for a time value with a space like
Check a prop's value is less than a given value.
- name<number
+ {'name
-
-
name<relative
+ {'name
-
(A single relative time value like
now
or
@@ -379,7 +379,7 @@ async function doQuery() {
-
-
name<"relative time value"
+ {'name<"relative time value"'}
-
(Use this for a time value with a space like
Check a prop's value is less than or equal to a given value.
- name<=number
+ {'name<=number'}
-
-
name<=relative
+ {'name<=relative'}
-
(A single relative time value like
now
or
@@ -410,7 +410,7 @@ async function doQuery() {
-
-
name<="relative time value"
+ {'name<="relative time value"'}
-
(Use this for a time value with a space like
Here are some examples of nested selectors.
- Either enabled is truthy and abilities contains "subscriber", or abilities contains "lifelong-subscriber".
+ {`Either enabled is truthy and abilities contains "subscriber", or abilities contains "lifelong-subscriber".
-(| ([enabled] abilities<"subscriber">) abilities<"lifeline-subscriber">)
+(| ([enabled] abilities<"subscriber">) abilities<"lifeline-subscriber">)
Published is not truthy and cdate is not greater than 6 months ago.
-(! [published] cdate>"6 months ago")
+(! [published] cdate>"6 months ago")`}
Default Fields
diff --git a/src/routes/packages/server/+page.svelte b/src/routes/packages/server/+page.svelte
index 634f9ce..188690d 100644
--- a/src/routes/packages/server/+page.svelte
+++ b/src/routes/packages/server/+page.svelte
@@ -46,7 +46,7 @@ const nymph = new Nymph(
{},
new SQLite3Driver({
filename: ':memory:',
- })
+ }),
);
const MyEntity = nymph.addEntityClass(MyEntityClass);
@@ -68,8 +68,8 @@ app.listen(80);`}
- Now you can configure your client using your server's address
- (and the optional path, if set).
+ Now you can configure your client, using your server's
+ address (and the optional path, if set).
The Tilmeld client contains the client versions of the User
and
Group
- entities. It also contains helpers, getClientConfig
,
- login
, register
, and checkUsername
.
+ entities. It also contains helpers, login
,
+ register
, and checkUsername
.
diff --git a/src/routes/packages/tilmeld-components/+page.svelte b/src/routes/packages/tilmeld-components/+page.svelte
index fe68db1..8280af8 100644
--- a/src/routes/packages/tilmeld-components/+page.svelte
+++ b/src/routes/packages/tilmeld-components/+page.svelte
@@ -10,7 +10,7 @@
The Tilmeld Components are front end registration/login, account recovery,
- account details, and password change components build with Svelte
diff --git a/src/routes/packages/tilmeld-setup/+page.svelte b/src/routes/packages/tilmeld-setup/+page.svelte
index 0b0ee95..fed4ae7 100644
--- a/src/routes/packages/tilmeld-setup/+page.svelte
+++ b/src/routes/packages/tilmeld-setup/+page.svelte
@@ -70,7 +70,7 @@ const nymph = new Nymph(
verifyChangeRedirect: 'http://localhost',
cancelChangeRedirect: 'http://localhost',
jwtSecret: 'shhhhh',
- })
+ }),
);
// Create your Express app.
@@ -86,8 +86,8 @@ app.use(
{
restUrl: 'http://localhost/rest',
},
- nymph
- )
+ nymph,
+ ),
);
// Do anything else you need to do...
diff --git a/src/routes/packages/tilmeld/+page.svelte b/src/routes/packages/tilmeld/+page.svelte
index 9e031ac..9ee0ee8 100644
--- a/src/routes/packages/tilmeld/+page.svelte
+++ b/src/routes/packages/tilmeld/+page.svelte
@@ -57,7 +57,7 @@ const nymph = new Nymph(
new SQLite3Driver({
filename: ':memory:',
}),
- tilmeld
+ tilmeld,
);
// These are the classes specific to this instance of Tilmeld.
@@ -84,7 +84,8 @@ const { User, Group } = tilmeld;`}
-
-
system/admin
- A user with this ability has **all** abilities.
+ system/admin
- A user with this ability has
+ all abilities.
-
tilmeld/admin
- Allow the user to manage and edit other user's
diff --git a/src/routes/user-guide/defining-entities/+page.svelte b/src/routes/user-guide/defining-entities/+page.svelte
index 8f4b013..bd8034b 100644
--- a/src/routes/user-guide/defining-entities/+page.svelte
+++ b/src/routes/user-guide/defining-entities/+page.svelte
@@ -21,7 +21,11 @@
Extending Entity in Node.js
{
protected $protectedTags = ['archived'];
protected $allowlistTags? = [];
- static async factory(guid?: string): Promise {
- return (await super.factory(guid)) as Todo & TodoData;
- }
-
- static factorySync(): Todo & TodoData {
- return super.factorySync() as Todo & TodoData;
- }
-
constructor() {
super();
@@ -54,6 +50,11 @@ export class Todo extends Entity {
this.$data.done = false;
}
+ async $getUniques() {
+ // Make sure this isn't a duplicate Todo for this user.
+ return [\`\${this.$data.user.guid}:\${this.$data.name}\`];
+ }
+
async $archive() {
if (this.$hasTag('archived')) {
return true;
@@ -81,26 +82,14 @@ export class Todo extends Entity {
'Invalid Todo: '
);
- // Check that this is not a duplicate Todo.
- const selector: Selector = {
- type: '&',
- equal: ['name', this.$data.name],
- };
- if (this.guid) {
- selector['!guid'] = this.guid;
+ try {
+ return await super.$save();
+ } catch (e: any) {
+ if (e instanceof EntityUniqueConstraintError) {
+ throw new Error('There is already a todo for that.');
+ }
+ throw e;
}
- if (
- await this.$nymph.getEntity(
- {
- class: this.$nymph.getEntityClass(Todo),
- },
- selector
- )
- ) {
- throw new Error('There is already a todo for that.');
- }
-
- return await super.$save();
}
}
@@ -125,14 +114,6 @@ export class Todo extends Entity {
// The name of the server class
public static class = 'Todo';
- static async factory(guid?: string): Promise {
- return (await super.factory(guid)) as Todo & TodoData;
- }
-
- static factorySync(): Todo & TodoData {
- return super.factorySync() as Todo & TodoData;
- }
-
constructor() {
super();
@@ -197,6 +178,17 @@ const Todo = nymph.addEntityClass(TodoClass);`}
maps the client class to the Node.js class and vice versa.
+
+ Nymph provides a mechanism to ensure uniqueness among entities. Any strings
+ returned by the $getUniques
method will have a uniqueness
+ constraint enforced by the database across this entity's etype. The
+ Todo
class returns a string containing both the user's GUID and
+ the todo name. This ensures that the user can't have two todos with the same
+ name. The $save
method checks for a thrown
+ EntityUniqueConstraintError
+ when calling the super class' $save
.
+
+
Finally, in Node.js, the Todo
class validates all of its data
in the $save
method using