You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/developers/applications/README.md
+46-16Lines changed: 46 additions & 16 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -249,9 +249,13 @@ To define custom (JavaScript) resources as endpoints, we need to create a `resou
249
249
const { Dog } = tables; // get the Dog table from the Harper provided set of tables (in the default database)
250
250
251
251
export class DogWithHumanAge extends Dog {
252
-
get(query) {
253
-
this.humanAge = 15 + this.age * 5; // silly calculation of human age equivalent
254
-
return super.get(query);
252
+
static loadAsInstance = false;
253
+
async get(target) {
254
+
const record = await super.get(target);
255
+
return {
256
+
...record, // include all properties from the record
257
+
humanAge: 15 + record.age * 5 // silly calculation of human age equivalent
258
+
};
255
259
}
256
260
}
257
261
```
@@ -269,16 +273,28 @@ type Breed @table {
269
273
}
270
274
```
271
275
272
-
Andnextwewillusethistableinour `get()` method. Wewillcallthenewtable's (static) `get()` methodtoretrieveabreedbyid. Todothiscorrectly, weaccessthetableusingourcurrentcontextbypassingin `this` asthesecondargument. Thisisimportantbecauseitensuresthatweareaccessingthedataatomically, inaconsistentsnapshotacrosstables. Thisprovidesautomaticallytrackingofmostrecentlyupdatedtimestampsacrossresourcesforcachingpurposes. Thisallowsforsharingofcontextualmetadata (like user who requested the data), andensuretransactionalatomicityforanywrites (not needed in this get operation, but important for other operations). Theresourcemethodsareautomaticallywrappedwithatransaction (will commit/finish when the method completes), andthisallowsustofullyutilizemultipleresourcesinourcurrenttransaction. WithourownsnapshotofthedatabasefortheDogandBreedtablewecanthenaccessdatalikethis:
@@ -289,9 +305,12 @@ Here we have focused on customizing how we retrieve data, but we may also want t
289
305
290
306
```javascript
291
307
exportclassCustomDogextendsDog {
292
-
asyncpost(data) {
293
-
if (data.action==='add-trick')
294
-
this.tricks.push(data.trick);
308
+
static loadAsInstance =false;
309
+
asyncpost(target, data) {
310
+
if (data.action==='add-trick') {
311
+
constrecord=this.update(target);
312
+
record.tricks.push(data.trick);
313
+
}
295
314
}
296
315
}
297
316
```
@@ -300,12 +319,23 @@ And a POST request to /CustomDog/ would call this `post` method. The Resource cl
300
319
301
320
The `post` method automatically marks the current instance as being update. However, you can also explicitly specify that you are changing a resource by calling the `update()` method. If you want to modify a resource instance that you retrieved through a `get()` call (like `Breed.get()` call above), you can call its `update()` method to ensure changes are saved (and will be committed in the current transaction).
302
321
303
-
We can also define custom authorization capabilities. For example, we might want to specify that only the owner of a dog can make updates to a dog. We could add logic to our `post` method or `put` method to do this, but we may want to separate the logic so these methods can be called separately without authorization checks. The [Resource API](../../technical-details/reference/resource.md) defines `allowRead`, `allowUpdate`, `allowCreate`, and `allowDelete`, or to easily configure individual capabilities. For example, we might do this:
322
+
We can also define custom authorization capabilities. For example, we might want to specify that only the owner of a dog can make updates to a dog. We could add logic to our `post()` method or `put()` method to do this. For example, we might do this:
304
323
305
324
```javascript
306
325
exportclassCustomDogextendsDog {
307
-
allowUpdate(user) {
308
-
returnthis.owner===user.username;
326
+
static loadAsInstance =false;
327
+
asyncpost(target, data) {
328
+
if (data.action==='add-trick') {
329
+
constcontext=this.getContext();
330
+
// if we want to skip the default permission checks, we can turn off checkPermissions:
331
+
target.checkPermissions=false;
332
+
constrecord=this.update(target);
333
+
// and do our own/custom permission check:
334
+
if (record.owner!==context.user?.username) {
335
+
thrownewError('Can not update this record');
336
+
}
337
+
record.tricks.push(data.trick);
338
+
}
309
339
}
310
340
}
311
341
```
@@ -329,8 +359,8 @@ We can also directly implement the Resource class and use it to create new data
329
359
```javascript
330
360
const { Breed } = tables; // our Breed table
331
361
classBreedSourceextendsResource { // define a data source
0 commit comments