Skip to content

Commit 80b3e23

Browse files
authored
feat(js-sdk): add support for write conflict settings (#646)
2 parents 19d1271 + 4517ab8 commit 80b3e23

3 files changed

Lines changed: 83 additions & 3 deletions

File tree

config/clients/js/config.overrides.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"supportsES6": true,
1212
"modelPropertyNaming": "original",
1313
"openTelemetryDocumentation": "docs/opentelemetry.md",
14+
"enumNameSuffix": "",
1415
"files": {
1516
"constants.mustache": {
1617
"destinationFilename": "constants/index.ts",

config/clients/js/template/README_calling_api.mustache

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,85 @@ response = {
267267
*/
268268
```
269269

270+
#### Conflict Options for Write Operations
271+
272+
The SDK supports conflict options for write operations, allowing you to control how the API handles duplicate writes and missing deletes.
273+
274+
> **Note**: This requires OpenFGA [v1.10.0](https://github.com/openfga/openfga/releases/tag/v1.10.0) or later.
275+
276+
##### Using Conflict Options with Write
277+
```javascript
278+
const options = {
279+
conflict: {
280+
// Control what happens when writing a tuple that already exists
281+
onDuplicateWrites: ClientWriteRequestOnDuplicateWrites.Ignore, // or ClientWriteRequestOnDuplicateWrites.Error (the current default behavior)
282+
// Control what happens when deleting a tuple that doesn't exist
283+
onMissingDeletes: ClientWriteRequestOnMissingDeletes.Ignore, // or ClientWriteRequestOnMissingDeletes.Error (the current default behavior)
284+
}
285+
};
286+
287+
const body = {
288+
writes: [{
289+
user: 'user:anne',
290+
relation: 'writer',
291+
object: 'document:2021-budget',
292+
}],
293+
deletes: [{
294+
user: 'user:bob',
295+
relation: 'reader',
296+
object: 'document:2021-budget',
297+
}],
298+
};
299+
300+
const response = await fgaClient.write(body, options);
301+
```
302+
303+
##### Using Conflict Options with WriteTuples
304+
```javascript
305+
const tuples = [{
306+
user: 'user:anne',
307+
relation: 'writer',
308+
object: 'document:2021-budget',
309+
}];
310+
311+
const options = {
312+
conflict: {
313+
onDuplicateWrites: ClientWriteRequestOnDuplicateWrites.Ignore,
314+
}
315+
};
316+
317+
const response = await fgaClient.writeTuples(tuples, options);
318+
```
319+
320+
##### Using Conflict Options with DeleteTuples
321+
```javascript
322+
const tuples = [{
323+
user: 'user:bob',
324+
relation: 'reader',
325+
object: 'document:2021-budget',
326+
}];
327+
328+
const options = {
329+
conflict: {
330+
onMissingDeletes: OnMissingDelete.Ignore,
331+
}
332+
};
333+
334+
const response = await fgaClient.deleteTuples(tuples, options);
335+
```
336+
337+
##### Conflict Options Behavior
338+
339+
- **`onDuplicateWrites`**:
340+
- `ClientWriteRequestOnDuplicateWrites.Error` (default): Returns an error if an identical tuple already exists (matching on user, relation, object, and condition)
341+
- `ClientWriteRequestOnDuplicateWrites.Ignore`: Treats duplicate writes as no-ops, allowing idempotent write operations
342+
343+
- **`onMissingDeletes`**:
344+
- `ClientWriteRequestOnMissingDeletes.Error` (default): Returns an error when attempting to delete a tuple that doesn't exist
345+
- `ClientWriteRequestOnMissingDeletes.Ignore`: Treats deletes of non-existent tuples as no-ops, allowing idempotent delete operations
346+
347+
> **Important**: If a Write request contains both idempotent (ignore) and non-idempotent (error) operations, the most restrictive action (error) will take precedence. If a condition fails for a sub-request with an error flag, the entire transaction will be rolled back.
348+
270349
#### Relationship Queries
271350
272351
##### Check

config/clients/js/template/modelGeneric.mustache

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ export interface {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{
2424
{{#vars}}
2525
{{#isEnum}}
2626
/**
27-
* @export
28-
* @enum {string}
29-
*/
27+
* @export
28+
* @enum {string}
29+
*/
3030
export enum {{enumName}} {
3131
{{#allowableValues}}
3232
{{#enumVars}}

0 commit comments

Comments
 (0)