@open-aih/payload-ddb 3.1.0 → 4.1.0
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/README.md +141 -18
- package/dist/count.d.ts.map +1 -1
- package/dist/count.js +4 -2
- package/dist/count.js.map +1 -1
- package/dist/countGlobalVersions.d.ts.map +1 -1
- package/dist/countGlobalVersions.js +6 -1
- package/dist/countGlobalVersions.js.map +1 -1
- package/dist/countVersions.d.ts.map +1 -1
- package/dist/countVersions.js +6 -1
- package/dist/countVersions.js.map +1 -1
- package/dist/create.d.ts.map +1 -1
- package/dist/create.js +31 -15
- package/dist/create.js.map +1 -1
- package/dist/createGlobal.d.ts.map +1 -1
- package/dist/createGlobal.js +2 -14
- package/dist/createGlobal.js.map +1 -1
- package/dist/createGlobalVersion.d.ts +1 -1
- package/dist/createGlobalVersion.d.ts.map +1 -1
- package/dist/createGlobalVersion.js +3 -41
- package/dist/createGlobalVersion.js.map +1 -1
- package/dist/createVersion.d.ts +6 -5
- package/dist/createVersion.d.ts.map +1 -1
- package/dist/createVersion.js +8 -48
- package/dist/createVersion.js.map +1 -1
- package/dist/deleteMany.d.ts +1 -6
- package/dist/deleteMany.d.ts.map +1 -1
- package/dist/deleteMany.js +8 -19
- package/dist/deleteMany.js.map +1 -1
- package/dist/deleteOne.d.ts.map +1 -1
- package/dist/deleteOne.js +20 -24
- package/dist/deleteOne.js.map +1 -1
- package/dist/deleteVersions.d.ts.map +1 -1
- package/dist/deleteVersions.js +8 -14
- package/dist/deleteVersions.js.map +1 -1
- package/dist/find.d.ts.map +1 -1
- package/dist/find.js +15 -2
- package/dist/find.js.map +1 -1
- package/dist/findDistinct.d.ts.map +1 -1
- package/dist/findDistinct.js +3 -1
- package/dist/findDistinct.js.map +1 -1
- package/dist/findGlobal.d.ts.map +1 -1
- package/dist/findGlobal.js +3 -2
- package/dist/findGlobal.js.map +1 -1
- package/dist/findGlobalVersions.d.ts.map +1 -1
- package/dist/findGlobalVersions.js +10 -2
- package/dist/findGlobalVersions.js.map +1 -1
- package/dist/findOne.d.ts.map +1 -1
- package/dist/findOne.js +17 -6
- package/dist/findOne.js.map +1 -1
- package/dist/findVersions.d.ts.map +1 -1
- package/dist/findVersions.js +10 -2
- package/dist/findVersions.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/queryDrafts.d.ts.map +1 -1
- package/dist/queryDrafts.js +24 -4
- package/dist/queryDrafts.js.map +1 -1
- package/dist/updateGlobal.d.ts +5 -4
- package/dist/updateGlobal.d.ts.map +1 -1
- package/dist/updateGlobal.js +22 -36
- package/dist/updateGlobal.js.map +1 -1
- package/dist/updateGlobalVersion.d.ts.map +1 -1
- package/dist/updateGlobalVersion.js +3 -49
- package/dist/updateGlobalVersion.js.map +1 -1
- package/dist/updateJobs.d.ts +21 -0
- package/dist/updateJobs.d.ts.map +1 -0
- package/dist/updateJobs.js +83 -0
- package/dist/updateJobs.js.map +1 -0
- package/dist/updateMany.d.ts +9 -3
- package/dist/updateMany.d.ts.map +1 -1
- package/dist/updateMany.js +47 -30
- package/dist/updateMany.js.map +1 -1
- package/dist/updateOne.d.ts +6 -1
- package/dist/updateOne.d.ts.map +1 -1
- package/dist/updateOne.js +49 -49
- package/dist/updateOne.js.map +1 -1
- package/dist/updateVersion.d.ts.map +1 -1
- package/dist/updateVersion.js +3 -52
- package/dist/updateVersion.js.map +1 -1
- package/dist/upsert.d.ts +6 -0
- package/dist/upsert.d.ts.map +1 -1
- package/dist/upsert.js +57 -41
- package/dist/upsert.js.map +1 -1
- package/dist/utilities/backfillUniqueGuards.d.ts +42 -0
- package/dist/utilities/backfillUniqueGuards.d.ts.map +1 -0
- package/dist/utilities/backfillUniqueGuards.js +39 -0
- package/dist/utilities/backfillUniqueGuards.js.map +1 -0
- package/dist/utilities/buildFilterExpression.d.ts +29 -14
- package/dist/utilities/buildFilterExpression.d.ts.map +1 -1
- package/dist/utilities/buildFilterExpression.js +55 -14
- package/dist/utilities/buildFilterExpression.js.map +1 -1
- package/dist/utilities/castWhere.d.ts +84 -0
- package/dist/utilities/castWhere.d.ts.map +1 -0
- package/dist/utilities/castWhere.js +254 -0
- package/dist/utilities/castWhere.js.map +1 -0
- package/dist/utilities/findFirst.d.ts +3 -2
- package/dist/utilities/findFirst.d.ts.map +1 -1
- package/dist/utilities/findFirst.js +14 -46
- package/dist/utilities/findFirst.js.map +1 -1
- package/dist/utilities/geo.d.ts +36 -0
- package/dist/utilities/geo.d.ts.map +1 -0
- package/dist/utilities/geo.js +108 -0
- package/dist/utilities/geo.js.map +1 -0
- package/dist/utilities/mapWithConcurrency.d.ts +12 -0
- package/dist/utilities/mapWithConcurrency.d.ts.map +1 -0
- package/dist/utilities/mapWithConcurrency.js +32 -0
- package/dist/utilities/mapWithConcurrency.js.map +1 -0
- package/dist/utilities/matchesWhere.d.ts +25 -5
- package/dist/utilities/matchesWhere.d.ts.map +1 -1
- package/dist/utilities/matchesWhere.js +150 -38
- package/dist/utilities/matchesWhere.js.map +1 -1
- package/dist/utilities/operators.d.ts +22 -12
- package/dist/utilities/operators.d.ts.map +1 -1
- package/dist/utilities/operators.js +36 -31
- package/dist/utilities/operators.js.map +1 -1
- package/dist/utilities/optimistic.d.ts +29 -0
- package/dist/utilities/optimistic.d.ts.map +1 -0
- package/dist/utilities/optimistic.js +58 -0
- package/dist/utilities/optimistic.js.map +1 -0
- package/dist/utilities/prepareWhere.d.ts +63 -0
- package/dist/utilities/prepareWhere.d.ts.map +1 -0
- package/dist/utilities/prepareWhere.js +198 -0
- package/dist/utilities/prepareWhere.js.map +1 -0
- package/dist/utilities/queryCount.d.ts +6 -3
- package/dist/utilities/queryCount.d.ts.map +1 -1
- package/dist/utilities/queryCount.js +16 -45
- package/dist/utilities/queryCount.js.map +1 -1
- package/dist/utilities/queryMatching.d.ts +8 -7
- package/dist/utilities/queryMatching.d.ts.map +1 -1
- package/dist/utilities/queryMatching.js +17 -54
- package/dist/utilities/queryMatching.js.map +1 -1
- package/dist/utilities/queryPartition.d.ts +26 -0
- package/dist/utilities/queryPartition.d.ts.map +1 -0
- package/dist/utilities/queryPartition.js +55 -0
- package/dist/utilities/queryPartition.js.map +1 -0
- package/dist/utilities/resolveJoins.d.ts +37 -0
- package/dist/utilities/resolveJoins.d.ts.map +1 -0
- package/dist/utilities/resolveJoins.js +195 -0
- package/dist/utilities/resolveJoins.js.map +1 -0
- package/dist/utilities/stripInternalKeys.d.ts +17 -3
- package/dist/utilities/stripInternalKeys.d.ts.map +1 -1
- package/dist/utilities/stripInternalKeys.js +25 -4
- package/dist/utilities/stripInternalKeys.js.map +1 -1
- package/dist/utilities/uniqueGuards.d.ts +39 -0
- package/dist/utilities/uniqueGuards.d.ts.map +1 -0
- package/dist/utilities/uniqueGuards.js +106 -0
- package/dist/utilities/uniqueGuards.js.map +1 -0
- package/dist/utilities/updateVersionRow.d.ts +19 -0
- package/dist/utilities/updateVersionRow.d.ts.map +1 -0
- package/dist/utilities/updateVersionRow.js +40 -0
- package/dist/utilities/updateVersionRow.js.map +1 -0
- package/dist/utilities/writeErrors.d.ts +11 -0
- package/dist/utilities/writeErrors.d.ts.map +1 -0
- package/dist/utilities/writeErrors.js +27 -0
- package/dist/utilities/writeErrors.js.map +1 -0
- package/dist/utilities/writeItems.d.ts +124 -0
- package/dist/utilities/writeItems.d.ts.map +1 -0
- package/dist/utilities/writeItems.js +383 -0
- package/dist/utilities/writeItems.js.map +1 -0
- package/package.json +21 -14
package/README.md
CHANGED
|
@@ -3,22 +3,35 @@
|
|
|
3
3
|
An unofficial database adapter for [PayloadCMS](https://payloadcms.com) that
|
|
4
4
|
stores data in [Amazon DynamoDB](https://aws.amazon.com/dynamodb/).
|
|
5
5
|
|
|
6
|
-
> **Status:** all `BaseDatabaseAdapter` methods are implemented end-to-end
|
|
7
|
-
>
|
|
8
|
-
>
|
|
9
|
-
> shared table with a `Query`-per-collection access pattern
|
|
10
|
-
>
|
|
11
|
-
>
|
|
12
|
-
|
|
6
|
+
> **Status:** all `BaseDatabaseAdapter` methods are implemented end-to-end:
|
|
7
|
+
> CRUD, drafts, versions, globals, localization, every `where` operator, join
|
|
8
|
+
> fields and unique fields. The current strategy is "correct first, optimize
|
|
9
|
+
> later" — a single shared table with a `Query`-per-collection access pattern
|
|
10
|
+
> and no GSIs. Suitable for development and small-to-medium workloads; large
|
|
11
|
+
> collections will want the optimizations listed under *Known limits*.
|
|
12
|
+
|
|
13
|
+
## Requirements
|
|
14
|
+
|
|
15
|
+
- **Payload 3.x.** The peer range is `payload >=3.0.0`; the test suite runs
|
|
16
|
+
against 3.93.
|
|
17
|
+
- **Node.js as your Payload version requires.** Payload 3.92 and later need
|
|
18
|
+
Node 22.23.4+ or 24.22.1+. This repo's CI runs on Node 24.
|
|
13
19
|
|
|
14
20
|
## Installation
|
|
15
21
|
|
|
22
|
+
The package is published under two names with the same contents:
|
|
23
|
+
|
|
16
24
|
```bash
|
|
25
|
+
# Public npm registry — minor and major releases
|
|
26
|
+
pnpm add @open-aih/payload-ddb
|
|
27
|
+
|
|
28
|
+
# GitHub Packages — every release, including patches
|
|
17
29
|
pnpm add @aih-software/payload-ddb
|
|
18
|
-
# or
|
|
19
|
-
npm install @aih-software/payload-ddb
|
|
20
30
|
```
|
|
21
31
|
|
|
32
|
+
The examples below import from `@aih-software/payload-ddb`; use
|
|
33
|
+
`@open-aih/payload-ddb` instead if that is the one you installed.
|
|
34
|
+
|
|
22
35
|
## Quick start (DynamoDB Local)
|
|
23
36
|
|
|
24
37
|
```ts
|
|
@@ -75,6 +88,7 @@ value in the same physical table.
|
|
|
75
88
|
| `translateConfig` | `TranslateConfig` | `removeUndefinedValues: true`, `convertClassInstanceToMap: true` | Marshalling options forwarded to `DynamoDBDocumentClient.from`. |
|
|
76
89
|
| `tableName` | `string` | `'payload'` | The single DynamoDB table backing every collection, global, and versions stream. |
|
|
77
90
|
| `ensureTables` | `boolean` | `false` | When true, auto-creates the table at init if it doesn't exist. Dev-loop convenience; turn off in production. |
|
|
91
|
+
| `migrationDir` | `string` | `'migrations'` | Directory Payload reads and writes migration files in. |
|
|
78
92
|
|
|
79
93
|
## Data layout
|
|
80
94
|
|
|
@@ -88,7 +102,12 @@ value in the same physical table.
|
|
|
88
102
|
- **Sort key is always String.** Number-typed collection ids are coerced to
|
|
89
103
|
strings for `sk` while the original numeric `id` attribute is preserved on
|
|
90
104
|
the row.
|
|
91
|
-
- **
|
|
105
|
+
- **Revision counter.** Every row also carries `_rev`, bumped on each write
|
|
106
|
+
and stripped on read. Updates are conditional on it, so two writers can't
|
|
107
|
+
silently overwrite each other.
|
|
108
|
+
- **Unique guards:** `pk = "<slug>#unique#<field path>"`, `sk = "<value>"`,
|
|
109
|
+
one small row per value of a `unique: true` field. See *Unique fields*.
|
|
110
|
+
- **No GSIs or LSIs.** Per-collection reads are `Query`s scoped by `pk`;
|
|
92
111
|
predicates beyond `pk` get pushed to `FilterExpression` (DynamoDB still
|
|
93
112
|
reads every row in the partition before filtering).
|
|
94
113
|
|
|
@@ -97,14 +116,91 @@ value in the same physical table.
|
|
|
97
116
|
All `BaseDatabaseAdapter` methods: `create`, `find`, `findOne`, `findDistinct`,
|
|
98
117
|
`count`, `updateOne`, `updateMany`, `deleteOne`, `deleteMany`, `upsert`,
|
|
99
118
|
`createGlobal`/`findGlobal`/`updateGlobal`, the five collection version methods,
|
|
100
|
-
the four global version methods, and `
|
|
119
|
+
the four global version methods, `queryDrafts`, and `updateJobs`.
|
|
120
|
+
|
|
121
|
+
### Queries
|
|
122
|
+
|
|
123
|
+
Every Payload `where` operator is supported: `equals`, `not_equals`,
|
|
124
|
+
`greater_than`, `greater_than_equal`, `less_than`, `less_than_equal`, `in`,
|
|
125
|
+
`not_in`, `all`, `exists`, `like`, `not_like`, `contains`, `near`, `within`,
|
|
126
|
+
`intersects`, plus `and` / `or` composition.
|
|
127
|
+
|
|
128
|
+
- **Pushdown where possible, JS for the rest.** Clauses DynamoDB can express
|
|
129
|
+
go into a `FilterExpression`. The others — the case-insensitive text
|
|
130
|
+
operators (`like`, `not_like`, `contains`), `all`, the geo operators, and
|
|
131
|
+
any path that runs through a list — are evaluated in JS on the rows that
|
|
132
|
+
come back. A `where` that mixes both kinds still narrows the read
|
|
133
|
+
server-side.
|
|
134
|
+
- **Lists behave as in MongoDB.** A `hasMany` field, an `array` or `blocks`
|
|
135
|
+
field, or a list inside `json` is transparent in a path: `tags equals 'x'`
|
|
136
|
+
matches when any element is `'x'`, `items.label equals 'x'` when any row
|
|
137
|
+
has that label. Negative operators hold only when no element matches.
|
|
138
|
+
- **Relationship paths.** `author.name equals 'Ada'` is resolved by querying
|
|
139
|
+
the related collection and filtering on the ids it returns; multi-hop paths
|
|
140
|
+
work the same way.
|
|
141
|
+
- **Localized fields.** With localization enabled, filters and sorts on a
|
|
142
|
+
localized field address the request's locale (`title` → `title.en`), or the
|
|
143
|
+
locale written into the path.
|
|
144
|
+
- **Operand casting.** Operands are cast to the field's stored type, so
|
|
145
|
+
filters sent as strings (REST query strings, admin list filters) behave:
|
|
146
|
+
numeric strings on `number` fields, `'true'`/`'false'` on `checkbox` fields,
|
|
147
|
+
date strings on `date` fields, ids on relationships to numeric-id
|
|
148
|
+
collections, and comma-delimited lists for `in` / `not_in` / `all`.
|
|
149
|
+
DynamoDB compares strictly by type, so an operand the adapter can't cast
|
|
150
|
+
(an unknown path) is compared as given.
|
|
151
|
+
- **`exists`** treats a field stored as `null` the same as a missing one, and
|
|
152
|
+
for text-like fields an empty string as well.
|
|
153
|
+
- **Geo operators** work on `point` fields. Distances are great-circle
|
|
154
|
+
metres; polygon tests are planar.
|
|
155
|
+
|
|
156
|
+
### Join fields
|
|
157
|
+
|
|
158
|
+
`join` fields are resolved for `find`, `findByID` and draft queries: one query
|
|
159
|
+
per target collection for all returned documents, grouped in memory, with
|
|
160
|
+
`limit`, `page`, `sort`, `where` and `count` applied per parent document.
|
|
161
|
+
Polymorphic joins (`collection: [...]`) return `{ relationTo, value }` entries.
|
|
162
|
+
Joined documents are read from the target's published rows.
|
|
163
|
+
|
|
164
|
+
### Write guarantees
|
|
165
|
+
|
|
166
|
+
- **`create` is insert-only.** An id that is already taken is rejected with a
|
|
167
|
+
`ValidationError` on `id` rather than replacing the existing document.
|
|
168
|
+
- **No lost updates.** Updates are read-merge-write, conditional on the row's
|
|
169
|
+
revision. If another writer gets in first, the patch is re-applied to the
|
|
170
|
+
fresh row, so concurrent updates to different fields both land. This holds
|
|
171
|
+
per adapter call: Payload's own `update` operation fills the fields missing
|
|
172
|
+
from a patch with the values it read beforehand, so two concurrent
|
|
173
|
+
`payload.update` calls on one document can still overwrite each other.
|
|
174
|
+
- **Jobs are claimed once.** `updateJobs` uses the same check, so two workers
|
|
175
|
+
polling the queue can't both take the same job.
|
|
176
|
+
- **Bulk writes are bounded.** `updateMany`, `deleteMany` and `deleteVersions`
|
|
177
|
+
keep at most 25 requests in flight.
|
|
178
|
+
- **Oversized documents fail clearly.** DynamoDB caps an item at 400 KB;
|
|
179
|
+
exceeding it raises a 413 naming the document instead of a bare
|
|
180
|
+
`ValidationException`.
|
|
101
181
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
`
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
182
|
+
### Unique fields
|
|
183
|
+
|
|
184
|
+
`unique: true` is enforced for scalar fields at the top level or inside groups
|
|
185
|
+
and named tabs, including localized fields (per locale) and an auth
|
|
186
|
+
collection's `email` / `username`. Each value is claimed by a guard row
|
|
187
|
+
written in the same transaction as the document, so a duplicate is rejected
|
|
188
|
+
with a `ValidationError` on the field — also under concurrent writes. Blank
|
|
189
|
+
values (`null`, `''`) are not guarded. Unique fields inside arrays or blocks,
|
|
190
|
+
and `hasMany` fields, are not enforced.
|
|
191
|
+
|
|
192
|
+
Writes to a collection with unique fields are transactional and cost twice the
|
|
193
|
+
write units; collections without them are unaffected.
|
|
194
|
+
|
|
195
|
+
Documents written before this was enforced have no guards until they are next
|
|
196
|
+
saved. To cover them in one pass:
|
|
197
|
+
|
|
198
|
+
```ts
|
|
199
|
+
import { backfillUniqueGuards } from '@aih-software/payload-ddb'
|
|
200
|
+
|
|
201
|
+
const report = await backfillUniqueGuards(payload)
|
|
202
|
+
// report.collections[slug].conflicts lists pre-existing duplicates
|
|
203
|
+
```
|
|
108
204
|
|
|
109
205
|
## Known limits / future work
|
|
110
206
|
|
|
@@ -118,12 +214,22 @@ down).
|
|
|
118
214
|
commit/rollback do nothing. Per-method atomicity (e.g. `createVersion`'s
|
|
119
215
|
flip+put) uses DynamoDB `TransactWriteItems` already; full Payload-context
|
|
120
216
|
transaction buffering across multiple adapter calls is its own milestone.
|
|
217
|
+
- **Filters cost a partition read.** Clauses evaluated in JS, relationship
|
|
218
|
+
paths and joins all read the partitions involved in full (a relationship
|
|
219
|
+
path or join adds one read of the related collection). Fine at CMS scale;
|
|
220
|
+
the GSI milestone is what removes it.
|
|
221
|
+
- **Joins don't see unpublished drafts** of the joined collection.
|
|
222
|
+
- **`locale: 'all'`** in a filter or sort falls back to the default locale.
|
|
223
|
+
- **`like` matches its operand as one substring.** Payload's Mongo adapter
|
|
224
|
+
splits the operand into words and requires each of them to match.
|
|
225
|
+
- **Items are limited to 400 KB**, including a version row's full snapshot.
|
|
121
226
|
|
|
122
227
|
## Development
|
|
123
228
|
|
|
124
229
|
The package ships with a vitest integration test harness that boots Payload
|
|
125
230
|
against DynamoDB Local. Each spec file uses a unique table name so vitest
|
|
126
|
-
workers can run in parallel against a single shared container
|
|
231
|
+
workers can run in parallel against a single shared container, which listens
|
|
232
|
+
on port 8001. Use Node 24, the version CI runs.
|
|
127
233
|
|
|
128
234
|
```bash
|
|
129
235
|
pnpm install
|
|
@@ -141,6 +247,23 @@ reachable. Override the host/port with `PAYLOAD_DDB_TEST_HOST` /
|
|
|
141
247
|
See [`test/README.md`](./test/README.md) for the harness layout and how to
|
|
142
248
|
add a new spec.
|
|
143
249
|
|
|
250
|
+
### Releasing
|
|
251
|
+
|
|
252
|
+
Releases are cut by CI on every push to `main` that carries a
|
|
253
|
+
[changeset](https://github.com/changesets/changesets) (`pnpm changeset`):
|
|
254
|
+
|
|
255
|
+
1. The integration tests run.
|
|
256
|
+
2. The version is bumped, committed as `chore(release): vX.Y.Z` and tagged.
|
|
257
|
+
3. The package is published to GitHub Packages as
|
|
258
|
+
`@aih-software/payload-ddb`, and a GitHub Release is created.
|
|
259
|
+
4. For minor and major bumps, the same build is published to the public npm
|
|
260
|
+
registry as `@open-aih/payload-ddb`.
|
|
261
|
+
|
|
262
|
+
The public publish uses npm
|
|
263
|
+
[trusted publishing](https://docs.npmjs.com/trusted-publishers), so there is
|
|
264
|
+
no npm token to rotate. The trusted publisher configured on npmjs.com must
|
|
265
|
+
name this repository and the workflow file `release.yml`.
|
|
266
|
+
|
|
144
267
|
## License
|
|
145
268
|
|
|
146
269
|
MIT
|
package/dist/count.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"count.d.ts","sourceRoot":"","sources":["../src/count.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"count.d.ts","sourceRoot":"","sources":["../src/count.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAOpC,eAAO,MAAM,KAAK,EAAE,KAInB,CAAA"}
|
package/dist/count.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { prepareCollectionWhere } from './utilities/prepareWhere.js';
|
|
1
2
|
import { queryCount } from './utilities/queryCount.js';
|
|
2
|
-
export const count = async function count({ collection, where }) {
|
|
3
|
-
const
|
|
3
|
+
export const count = async function count({ collection, locale, where }) {
|
|
4
|
+
const cast = await prepareCollectionWhere(this, collection, where, locale);
|
|
5
|
+
const totalDocs = await queryCount(this, this.resolvePartition(collection), cast);
|
|
4
6
|
return {
|
|
5
7
|
totalDocs
|
|
6
8
|
};
|
package/dist/count.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/count.ts"],"sourcesContent":["import type { Count } from 'payload'\n\nimport type { DynamoAdapter } from './types.js'\n\nimport { queryCount } from './utilities/queryCount.js'\n\nexport const count: Count = async function count(this: DynamoAdapter, { collection, where }) {\n const totalDocs = await queryCount(this, this.resolvePartition(collection),
|
|
1
|
+
{"version":3,"sources":["../src/count.ts"],"sourcesContent":["import type { Count } from 'payload'\n\nimport type { DynamoAdapter } from './types.js'\n\nimport { prepareCollectionWhere } from './utilities/prepareWhere.js'\nimport { queryCount } from './utilities/queryCount.js'\n\nexport const count: Count = async function count(this: DynamoAdapter, { collection, locale, where }) {\n const cast = await prepareCollectionWhere(this, collection, where, locale)\n const totalDocs = await queryCount(this, this.resolvePartition(collection), cast)\n return { totalDocs }\n}\n"],"names":["prepareCollectionWhere","queryCount","count","collection","locale","where","cast","totalDocs","resolvePartition"],"mappings":"AAIA,SAASA,sBAAsB,QAAQ,8BAA6B;AACpE,SAASC,UAAU,QAAQ,4BAA2B;AAEtD,OAAO,MAAMC,QAAe,eAAeA,MAA2B,EAAEC,UAAU,EAAEC,MAAM,EAAEC,KAAK,EAAE;IACjG,MAAMC,OAAO,MAAMN,uBAAuB,IAAI,EAAEG,YAAYE,OAAOD;IACnE,MAAMG,YAAY,MAAMN,WAAW,IAAI,EAAE,IAAI,CAACO,gBAAgB,CAACL,aAAaG;IAC5E,OAAO;QAAEC;IAAU;AACrB,EAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"countGlobalVersions.d.ts","sourceRoot":"","sources":["../src/countGlobalVersions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"countGlobalVersions.d.ts","sourceRoot":"","sources":["../src/countGlobalVersions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAA;AAOlD,eAAO,MAAM,mBAAmB,EAAE,mBAOjC,CAAA"}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
import { prepareVersionsWhere } from './utilities/prepareWhere.js';
|
|
1
2
|
import { queryCount } from './utilities/queryCount.js';
|
|
2
|
-
export const countGlobalVersions = async function countGlobalVersions({ global, where }) {
|
|
3
|
+
export const countGlobalVersions = async function countGlobalVersions({ global, locale, where: rawWhere }) {
|
|
4
|
+
const where = await prepareVersionsWhere(this, {
|
|
5
|
+
kind: 'global',
|
|
6
|
+
slug: global
|
|
7
|
+
}, rawWhere, locale);
|
|
3
8
|
const totalDocs = await queryCount(this, this.resolveVersionsPartition(global), where);
|
|
4
9
|
return {
|
|
5
10
|
totalDocs
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/countGlobalVersions.ts"],"sourcesContent":["import type { CountGlobalVersions } from 'payload'\n\nimport type { DynamoAdapter } from './types.js'\n\nimport { queryCount } from './utilities/queryCount.js'\n\nexport const countGlobalVersions: CountGlobalVersions = async function countGlobalVersions(\n this: DynamoAdapter,\n { global, where },\n) {\n const totalDocs = await queryCount(this, this.resolveVersionsPartition(global), where)\n return { totalDocs }\n}\n"],"names":["queryCount","countGlobalVersions","global","where","totalDocs","resolveVersionsPartition"],"mappings":"AAIA,SAASA,UAAU,QAAQ,4BAA2B;AAEtD,OAAO,MAAMC,sBAA2C,eAAeA,oBAErE,EAAEC,MAAM,EAAEC,
|
|
1
|
+
{"version":3,"sources":["../src/countGlobalVersions.ts"],"sourcesContent":["import type { CountGlobalVersions } from 'payload'\n\nimport type { DynamoAdapter } from './types.js'\n\nimport { prepareVersionsWhere } from './utilities/prepareWhere.js'\nimport { queryCount } from './utilities/queryCount.js'\n\nexport const countGlobalVersions: CountGlobalVersions = async function countGlobalVersions(\n this: DynamoAdapter,\n { global, locale, where: rawWhere },\n) {\n const where = await prepareVersionsWhere(this, { kind: 'global', slug: global }, rawWhere, locale)\n const totalDocs = await queryCount(this, this.resolveVersionsPartition(global), where)\n return { totalDocs }\n}\n"],"names":["prepareVersionsWhere","queryCount","countGlobalVersions","global","locale","where","rawWhere","kind","slug","totalDocs","resolveVersionsPartition"],"mappings":"AAIA,SAASA,oBAAoB,QAAQ,8BAA6B;AAClE,SAASC,UAAU,QAAQ,4BAA2B;AAEtD,OAAO,MAAMC,sBAA2C,eAAeA,oBAErE,EAAEC,MAAM,EAAEC,MAAM,EAAEC,OAAOC,QAAQ,EAAE;IAEnC,MAAMD,QAAQ,MAAML,qBAAqB,IAAI,EAAE;QAAEO,MAAM;QAAUC,MAAML;IAAO,GAAGG,UAAUF;IAC3F,MAAMK,YAAY,MAAMR,WAAW,IAAI,EAAE,IAAI,CAACS,wBAAwB,CAACP,SAASE;IAChF,OAAO;QAAEI;IAAU;AACrB,EAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"countVersions.d.ts","sourceRoot":"","sources":["../src/countVersions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"countVersions.d.ts","sourceRoot":"","sources":["../src/countVersions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAO5C,eAAO,MAAM,aAAa,EAAE,aAO3B,CAAA"}
|
package/dist/countVersions.js
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
import { prepareVersionsWhere } from './utilities/prepareWhere.js';
|
|
1
2
|
import { queryCount } from './utilities/queryCount.js';
|
|
2
|
-
export const countVersions = async function countVersions({ collection, where }) {
|
|
3
|
+
export const countVersions = async function countVersions({ collection, locale, where: rawWhere }) {
|
|
4
|
+
const where = await prepareVersionsWhere(this, {
|
|
5
|
+
kind: 'collection',
|
|
6
|
+
slug: collection
|
|
7
|
+
}, rawWhere, locale);
|
|
3
8
|
const totalDocs = await queryCount(this, this.resolveVersionsPartition(collection), where);
|
|
4
9
|
return {
|
|
5
10
|
totalDocs
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/countVersions.ts"],"sourcesContent":["import type { CountVersions } from 'payload'\n\nimport type { DynamoAdapter } from './types.js'\n\nimport { queryCount } from './utilities/queryCount.js'\n\nexport const countVersions: CountVersions = async function countVersions(\n this: DynamoAdapter,\n { collection, where },\n) {\n const totalDocs = await queryCount(this, this.resolveVersionsPartition(collection), where)\n return { totalDocs }\n}\n"],"names":["queryCount","countVersions","collection","where","totalDocs","resolveVersionsPartition"],"mappings":"AAIA,SAASA,UAAU,QAAQ,4BAA2B;AAEtD,OAAO,MAAMC,gBAA+B,eAAeA,cAEzD,EAAEC,UAAU,EAAEC,
|
|
1
|
+
{"version":3,"sources":["../src/countVersions.ts"],"sourcesContent":["import type { CountVersions } from 'payload'\n\nimport type { DynamoAdapter } from './types.js'\n\nimport { prepareVersionsWhere } from './utilities/prepareWhere.js'\nimport { queryCount } from './utilities/queryCount.js'\n\nexport const countVersions: CountVersions = async function countVersions(\n this: DynamoAdapter,\n { collection, locale, where: rawWhere },\n) {\n const where = await prepareVersionsWhere(this, { kind: 'collection', slug: collection }, rawWhere, locale)\n const totalDocs = await queryCount(this, this.resolveVersionsPartition(collection), where)\n return { totalDocs }\n}\n"],"names":["prepareVersionsWhere","queryCount","countVersions","collection","locale","where","rawWhere","kind","slug","totalDocs","resolveVersionsPartition"],"mappings":"AAIA,SAASA,oBAAoB,QAAQ,8BAA6B;AAClE,SAASC,UAAU,QAAQ,4BAA2B;AAEtD,OAAO,MAAMC,gBAA+B,eAAeA,cAEzD,EAAEC,UAAU,EAAEC,MAAM,EAAEC,OAAOC,QAAQ,EAAE;IAEvC,MAAMD,QAAQ,MAAML,qBAAqB,IAAI,EAAE;QAAEO,MAAM;QAAcC,MAAML;IAAW,GAAGG,UAAUF;IACnG,MAAMK,YAAY,MAAMR,WAAW,IAAI,EAAE,IAAI,CAACS,wBAAwB,CAACP,aAAaE;IACpF,OAAO;QAAEI;IAAU;AACrB,EAAC"}
|
package/dist/create.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../src/create.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../src/create.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAWrC,eAAO,MAAM,MAAM,EAAE,MA+CpB,CAAA"}
|
package/dist/create.js
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
import { PutCommand } from '@aws-sdk/lib-dynamodb';
|
|
2
1
|
import { randomUUID } from 'node:crypto';
|
|
3
|
-
import {
|
|
2
|
+
import { backoff, conflictError, getById, MAX_WRITE_ATTEMPTS } from './utilities/optimistic.js';
|
|
4
3
|
import { projectForCollection } from './utilities/resolveSchema.js';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
throw new Error('payload-ddb: docClient is not initialized — call connect() first.');
|
|
9
|
-
}
|
|
4
|
+
import { mustBeUniqueError, rethrowUniqueViolation } from './utilities/writeErrors.js';
|
|
5
|
+
import { isConditionalCheckFailed, putItem } from './utilities/writeItems.js';
|
|
6
|
+
export const create = async function create({ collection, customID, data, req, returning }) {
|
|
10
7
|
const id = customID ?? data['id'] ?? randomUUID();
|
|
11
8
|
const now = new Date().toISOString();
|
|
12
9
|
// Spread `data` first, then nullish-coalesce timestamps. Explicit values
|
|
@@ -24,14 +21,33 @@ export const create = async function create({ collection, customID, data, return
|
|
|
24
21
|
// layer, so without this any stray request-body key (notoriously the
|
|
25
22
|
// registration form's `confirm-password`) would persist verbatim.
|
|
26
23
|
const projected = projectForCollection(this, collection, item);
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
24
|
+
const partition = this.resolvePartition(collection);
|
|
25
|
+
for(let attempt = 1;; attempt++){
|
|
26
|
+
try {
|
|
27
|
+
// Insert-only: a plain `PutItem` would replace whatever row already
|
|
28
|
+
// sits at this id, so a caller-supplied id that collides with an
|
|
29
|
+
// existing doc would silently destroy it. `unique` adds a guard row per
|
|
30
|
+
// unique field in the same transaction.
|
|
31
|
+
await putItem(this, partition, projected, {
|
|
32
|
+
mustNotExist: true,
|
|
33
|
+
unique: {
|
|
34
|
+
collection
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
break;
|
|
38
|
+
} catch (err) {
|
|
39
|
+
rethrowUniqueViolation(err, collection, req);
|
|
40
|
+
if (!isConditionalCheckFailed(err)) throw err;
|
|
41
|
+
// Either the id is taken, or this write collided with a concurrent one
|
|
42
|
+
// over a unique value. Surface the first the way the Mongo and Postgres
|
|
43
|
+
// adapters surface a duplicate primary key — a `ValidationError` on
|
|
44
|
+
// `id` — and retry the second, which resolves to a clean success or a
|
|
45
|
+
// unique violation.
|
|
46
|
+
if (await getById(this, partition, id)) throw mustBeUniqueError('id', collection, req);
|
|
47
|
+
if (attempt >= MAX_WRITE_ATTEMPTS) throw conflictError();
|
|
48
|
+
await backoff(attempt);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
35
51
|
return returning === false ? null : projected;
|
|
36
52
|
};
|
|
37
53
|
|
package/dist/create.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/create.ts"],"sourcesContent":["import type { Create } from 'payload'\n\nimport {
|
|
1
|
+
{"version":3,"sources":["../src/create.ts"],"sourcesContent":["import type { Create } from 'payload'\n\nimport { randomUUID } from 'node:crypto'\n\nimport type { DynamoAdapter } from './types.js'\n\nimport { backoff, conflictError, getById, MAX_WRITE_ATTEMPTS } from './utilities/optimistic.js'\nimport { projectForCollection } from './utilities/resolveSchema.js'\nimport { mustBeUniqueError, rethrowUniqueViolation } from './utilities/writeErrors.js'\nimport { isConditionalCheckFailed, putItem } from './utilities/writeItems.js'\n\nexport const create: Create = async function create(\n this: DynamoAdapter,\n { collection, customID, data, req, returning },\n) {\n const id = customID ?? data['id'] ?? randomUUID()\n const now = new Date().toISOString()\n // Spread `data` first, then nullish-coalesce timestamps. Explicit values\n // in `data` (versions/restore, migrations backdating) still win, but a\n // payload-passed `data.createdAt = undefined` no longer wipes the default\n // back to undefined — which the marshaller would then drop with\n // `removeUndefinedValues: true`, leaving the row without timestamps.\n const item: Record<string, unknown> = {\n ...data,\n id,\n createdAt: data['createdAt'] ?? now,\n updatedAt: data['updatedAt'] ?? now,\n }\n // Project against the collection's declared fields. DDB has no schema\n // layer, so without this any stray request-body key (notoriously the\n // registration form's `confirm-password`) would persist verbatim.\n const projected = projectForCollection(this, collection, item)\n const partition = this.resolvePartition(collection)\n\n for (let attempt = 1; ; attempt++) {\n try {\n // Insert-only: a plain `PutItem` would replace whatever row already\n // sits at this id, so a caller-supplied id that collides with an\n // existing doc would silently destroy it. `unique` adds a guard row per\n // unique field in the same transaction.\n await putItem(this, partition, projected, { mustNotExist: true, unique: { collection } })\n break\n } catch (err) {\n rethrowUniqueViolation(err, collection, req)\n if (!isConditionalCheckFailed(err)) throw err\n\n // Either the id is taken, or this write collided with a concurrent one\n // over a unique value. Surface the first the way the Mongo and Postgres\n // adapters surface a duplicate primary key — a `ValidationError` on\n // `id` — and retry the second, which resolves to a clean success or a\n // unique violation.\n if (await getById(this, partition, id)) throw mustBeUniqueError('id', collection, req)\n if (attempt >= MAX_WRITE_ATTEMPTS) throw conflictError()\n await backoff(attempt)\n }\n }\n\n return returning === false ? (null as never) : projected\n}\n"],"names":["randomUUID","backoff","conflictError","getById","MAX_WRITE_ATTEMPTS","projectForCollection","mustBeUniqueError","rethrowUniqueViolation","isConditionalCheckFailed","putItem","create","collection","customID","data","req","returning","id","now","Date","toISOString","item","createdAt","updatedAt","projected","partition","resolvePartition","attempt","mustNotExist","unique","err"],"mappings":"AAEA,SAASA,UAAU,QAAQ,cAAa;AAIxC,SAASC,OAAO,EAAEC,aAAa,EAAEC,OAAO,EAAEC,kBAAkB,QAAQ,4BAA2B;AAC/F,SAASC,oBAAoB,QAAQ,+BAA8B;AACnE,SAASC,iBAAiB,EAAEC,sBAAsB,QAAQ,6BAA4B;AACtF,SAASC,wBAAwB,EAAEC,OAAO,QAAQ,4BAA2B;AAE7E,OAAO,MAAMC,SAAiB,eAAeA,OAE3C,EAAEC,UAAU,EAAEC,QAAQ,EAAEC,IAAI,EAAEC,GAAG,EAAEC,SAAS,EAAE;IAE9C,MAAMC,KAAKJ,YAAYC,IAAI,CAAC,KAAK,IAAIb;IACrC,MAAMiB,MAAM,IAAIC,OAAOC,WAAW;IAClC,yEAAyE;IACzE,uEAAuE;IACvE,0EAA0E;IAC1E,gEAAgE;IAChE,qEAAqE;IACrE,MAAMC,OAAgC;QACpC,GAAGP,IAAI;QACPG;QACAK,WAAWR,IAAI,CAAC,YAAY,IAAII;QAChCK,WAAWT,IAAI,CAAC,YAAY,IAAII;IAClC;IACA,sEAAsE;IACtE,qEAAqE;IACrE,kEAAkE;IAClE,MAAMM,YAAYlB,qBAAqB,IAAI,EAAEM,YAAYS;IACzD,MAAMI,YAAY,IAAI,CAACC,gBAAgB,CAACd;IAExC,IAAK,IAAIe,UAAU,IAAKA,UAAW;QACjC,IAAI;YACF,oEAAoE;YACpE,iEAAiE;YACjE,wEAAwE;YACxE,wCAAwC;YACxC,MAAMjB,QAAQ,IAAI,EAAEe,WAAWD,WAAW;gBAAEI,cAAc;gBAAMC,QAAQ;oBAAEjB;gBAAW;YAAE;YACvF;QACF,EAAE,OAAOkB,KAAK;YACZtB,uBAAuBsB,KAAKlB,YAAYG;YACxC,IAAI,CAACN,yBAAyBqB,MAAM,MAAMA;YAE1C,uEAAuE;YACvE,wEAAwE;YACxE,oEAAoE;YACpE,sEAAsE;YACtE,oBAAoB;YACpB,IAAI,MAAM1B,QAAQ,IAAI,EAAEqB,WAAWR,KAAK,MAAMV,kBAAkB,MAAMK,YAAYG;YAClF,IAAIY,WAAWtB,oBAAoB,MAAMF;YACzC,MAAMD,QAAQyB;QAChB;IACF;IAEA,OAAOX,cAAc,QAAS,OAAiBQ;AACjD,EAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createGlobal.d.ts","sourceRoot":"","sources":["../src/createGlobal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"createGlobal.d.ts","sourceRoot":"","sources":["../src/createGlobal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAO3C;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE,YAU1B,CAAA"}
|
package/dist/createGlobal.js
CHANGED
|
@@ -1,28 +1,16 @@
|
|
|
1
|
-
import { PutCommand } from '@aws-sdk/lib-dynamodb';
|
|
2
|
-
import { normalizeForDynamo } from './utilities/normalizeForDynamo.js';
|
|
3
1
|
import { projectForGlobal } from './utilities/resolveSchema.js';
|
|
2
|
+
import { putItem } from './utilities/writeItems.js';
|
|
4
3
|
/**
|
|
5
4
|
* Insert a global's singleton row. The slug is forced as the row's `id` —
|
|
6
5
|
* this is what makes `findGlobal`/`updateGlobal` deterministic single-key
|
|
7
6
|
* reads (`pk = slug`, `sk = slug`).
|
|
8
7
|
*/ export const createGlobal = async function createGlobal({ slug, data, returning }) {
|
|
9
|
-
const docClient = this.docClient;
|
|
10
|
-
if (!docClient) {
|
|
11
|
-
throw new Error('payload-ddb: docClient is not initialized — call connect() first.');
|
|
12
|
-
}
|
|
13
8
|
const item = {
|
|
14
9
|
...data,
|
|
15
10
|
id: slug
|
|
16
11
|
};
|
|
17
12
|
const projected = projectForGlobal(this, slug, item);
|
|
18
|
-
await
|
|
19
|
-
TableName: this.tableName,
|
|
20
|
-
Item: normalizeForDynamo({
|
|
21
|
-
...projected,
|
|
22
|
-
pk: this.resolvePartition(slug),
|
|
23
|
-
sk: slug
|
|
24
|
-
})
|
|
25
|
-
}));
|
|
13
|
+
await putItem(this, this.resolvePartition(slug), projected);
|
|
26
14
|
return returning === false ? null : projected;
|
|
27
15
|
};
|
|
28
16
|
|
package/dist/createGlobal.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/createGlobal.ts"],"sourcesContent":["import type { CreateGlobal } from 'payload'\n\nimport
|
|
1
|
+
{"version":3,"sources":["../src/createGlobal.ts"],"sourcesContent":["import type { CreateGlobal } from 'payload'\n\nimport type { DynamoAdapter } from './types.js'\n\nimport { projectForGlobal } from './utilities/resolveSchema.js'\nimport { putItem } from './utilities/writeItems.js'\n\n/**\n * Insert a global's singleton row. The slug is forced as the row's `id` —\n * this is what makes `findGlobal`/`updateGlobal` deterministic single-key\n * reads (`pk = slug`, `sk = slug`).\n */\nexport const createGlobal: CreateGlobal = async function createGlobal(\n this: DynamoAdapter,\n { slug, data, returning },\n) {\n const item: Record<string, unknown> = { ...data, id: slug }\n const projected = projectForGlobal(this, slug, item)\n\n await putItem(this, this.resolvePartition(slug), projected)\n\n return returning === false ? (null as never) : (projected as never)\n}\n"],"names":["projectForGlobal","putItem","createGlobal","slug","data","returning","item","id","projected","resolvePartition"],"mappings":"AAIA,SAASA,gBAAgB,QAAQ,+BAA8B;AAC/D,SAASC,OAAO,QAAQ,4BAA2B;AAEnD;;;;CAIC,GACD,OAAO,MAAMC,eAA6B,eAAeA,aAEvD,EAAEC,IAAI,EAAEC,IAAI,EAAEC,SAAS,EAAE;IAEzB,MAAMC,OAAgC;QAAE,GAAGF,IAAI;QAAEG,IAAIJ;IAAK;IAC1D,MAAMK,YAAYR,iBAAiB,IAAI,EAAEG,MAAMG;IAE/C,MAAML,QAAQ,IAAI,EAAE,IAAI,CAACQ,gBAAgB,CAACN,OAAOK;IAEjD,OAAOH,cAAc,QAAS,OAAkBG;AAClD,EAAC"}
|
|
@@ -2,7 +2,7 @@ import type { CreateGlobalVersion } from 'payload';
|
|
|
2
2
|
/**
|
|
3
3
|
* Like `createVersion` but for global singletons: there's no `parent`, and
|
|
4
4
|
* the "latest" scope is the entire global's versions partition. Same atomic
|
|
5
|
-
* flip+put via `
|
|
5
|
+
* flip+put via `putVersionAsLatest`. See `createVersion` for rationale.
|
|
6
6
|
*/
|
|
7
7
|
export declare const createGlobalVersion: CreateGlobalVersion;
|
|
8
8
|
//# sourceMappingURL=createGlobalVersion.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createGlobalVersion.d.ts","sourceRoot":"","sources":["../src/createGlobalVersion.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"createGlobalVersion.d.ts","sourceRoot":"","sources":["../src/createGlobalVersion.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAA;AAUlD;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,mBAwCjC,CAAA"}
|
|
@@ -1,17 +1,12 @@
|
|
|
1
|
-
import { TransactWriteCommand } from '@aws-sdk/lib-dynamodb';
|
|
2
1
|
import { randomUUID } from 'node:crypto';
|
|
3
2
|
import { findFirst } from './utilities/findFirst.js';
|
|
4
|
-
import { normalizeForDynamo } from './utilities/normalizeForDynamo.js';
|
|
5
3
|
import { projectVersionSnapshot } from './utilities/resolveSchema.js';
|
|
4
|
+
import { putVersionAsLatest } from './utilities/writeItems.js';
|
|
6
5
|
/**
|
|
7
6
|
* Like `createVersion` but for global singletons: there's no `parent`, and
|
|
8
7
|
* the "latest" scope is the entire global's versions partition. Same atomic
|
|
9
|
-
* flip+put via `
|
|
8
|
+
* flip+put via `putVersionAsLatest`. See `createVersion` for rationale.
|
|
10
9
|
*/ export const createGlobalVersion = async function createGlobalVersion({ autosave, createdAt, globalSlug, publishedLocale, returning, snapshot, updatedAt, versionData }) {
|
|
11
|
-
const docClient = this.docClient;
|
|
12
|
-
if (!docClient) {
|
|
13
|
-
throw new Error('payload-ddb: docClient is not initialized — call connect() first.');
|
|
14
|
-
}
|
|
15
10
|
const partition = this.resolveVersionsPartition(globalSlug);
|
|
16
11
|
const previousLatest = await findFirst(this, {
|
|
17
12
|
partition,
|
|
@@ -40,40 +35,7 @@ import { projectVersionSnapshot } from './utilities/resolveSchema.js';
|
|
|
40
35
|
publishedLocale
|
|
41
36
|
} : {}
|
|
42
37
|
};
|
|
43
|
-
|
|
44
|
-
...item,
|
|
45
|
-
pk: partition,
|
|
46
|
-
sk: id
|
|
47
|
-
});
|
|
48
|
-
const transactItems = [];
|
|
49
|
-
if (previousLatest) {
|
|
50
|
-
transactItems.push({
|
|
51
|
-
Update: {
|
|
52
|
-
TableName: this.tableName,
|
|
53
|
-
Key: {
|
|
54
|
-
pk: partition,
|
|
55
|
-
sk: String(previousLatest['id'])
|
|
56
|
-
},
|
|
57
|
-
UpdateExpression: 'SET #latest = :false',
|
|
58
|
-
ExpressionAttributeNames: {
|
|
59
|
-
'#latest': 'latest'
|
|
60
|
-
},
|
|
61
|
-
ExpressionAttributeValues: {
|
|
62
|
-
':false': false
|
|
63
|
-
},
|
|
64
|
-
ConditionExpression: 'attribute_exists(pk)'
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
transactItems.push({
|
|
69
|
-
Put: {
|
|
70
|
-
TableName: this.tableName,
|
|
71
|
-
Item: putItem
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
await docClient.send(new TransactWriteCommand({
|
|
75
|
-
TransactItems: transactItems
|
|
76
|
-
}));
|
|
38
|
+
await putVersionAsLatest(this, partition, item, previousLatest);
|
|
77
39
|
return returning === false ? null : item;
|
|
78
40
|
};
|
|
79
41
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/createGlobalVersion.ts"],"sourcesContent":["import type { CreateGlobalVersion } from 'payload'\n\nimport {
|
|
1
|
+
{"version":3,"sources":["../src/createGlobalVersion.ts"],"sourcesContent":["import type { CreateGlobalVersion } from 'payload'\n\nimport { randomUUID } from 'node:crypto'\n\nimport type { DynamoAdapter } from './types.js'\n\nimport { findFirst } from './utilities/findFirst.js'\nimport { projectVersionSnapshot } from './utilities/resolveSchema.js'\nimport { putVersionAsLatest } from './utilities/writeItems.js'\n\n/**\n * Like `createVersion` but for global singletons: there's no `parent`, and\n * the \"latest\" scope is the entire global's versions partition. Same atomic\n * flip+put via `putVersionAsLatest`. See `createVersion` for rationale.\n */\nexport const createGlobalVersion: CreateGlobalVersion = async function createGlobalVersion(\n this: DynamoAdapter,\n {\n autosave,\n createdAt,\n globalSlug,\n publishedLocale,\n returning,\n snapshot,\n updatedAt,\n versionData,\n },\n) {\n const partition = this.resolveVersionsPartition(globalSlug)\n\n const previousLatest = await findFirst(this, {\n partition,\n where: { latest: { equals: true } },\n })\n\n const id = randomUUID()\n const sanitizedVersionData = projectVersionSnapshot(\n this,\n { kind: 'global', slug: globalSlug },\n versionData as Record<string, unknown>,\n )\n const item: Record<string, unknown> = {\n id,\n version: sanitizedVersionData,\n createdAt,\n updatedAt,\n latest: true,\n autosave,\n ...(snapshot ? { snapshot: true } : {}),\n ...(publishedLocale !== undefined ? { publishedLocale } : {}),\n }\n\n await putVersionAsLatest(this, partition, item, previousLatest)\n\n return returning === false ? (null as never) : (item as never)\n}\n"],"names":["randomUUID","findFirst","projectVersionSnapshot","putVersionAsLatest","createGlobalVersion","autosave","createdAt","globalSlug","publishedLocale","returning","snapshot","updatedAt","versionData","partition","resolveVersionsPartition","previousLatest","where","latest","equals","id","sanitizedVersionData","kind","slug","item","version","undefined"],"mappings":"AAEA,SAASA,UAAU,QAAQ,cAAa;AAIxC,SAASC,SAAS,QAAQ,2BAA0B;AACpD,SAASC,sBAAsB,QAAQ,+BAA8B;AACrE,SAASC,kBAAkB,QAAQ,4BAA2B;AAE9D;;;;CAIC,GACD,OAAO,MAAMC,sBAA2C,eAAeA,oBAErE,EACEC,QAAQ,EACRC,SAAS,EACTC,UAAU,EACVC,eAAe,EACfC,SAAS,EACTC,QAAQ,EACRC,SAAS,EACTC,WAAW,EACZ;IAED,MAAMC,YAAY,IAAI,CAACC,wBAAwB,CAACP;IAEhD,MAAMQ,iBAAiB,MAAMd,UAAU,IAAI,EAAE;QAC3CY;QACAG,OAAO;YAAEC,QAAQ;gBAAEC,QAAQ;YAAK;QAAE;IACpC;IAEA,MAAMC,KAAKnB;IACX,MAAMoB,uBAAuBlB,uBAC3B,IAAI,EACJ;QAAEmB,MAAM;QAAUC,MAAMf;IAAW,GACnCK;IAEF,MAAMW,OAAgC;QACpCJ;QACAK,SAASJ;QACTd;QACAK;QACAM,QAAQ;QACRZ;QACA,GAAIK,WAAW;YAAEA,UAAU;QAAK,IAAI,CAAC,CAAC;QACtC,GAAIF,oBAAoBiB,YAAY;YAAEjB;QAAgB,IAAI,CAAC,CAAC;IAC9D;IAEA,MAAML,mBAAmB,IAAI,EAAEU,WAAWU,MAAMR;IAEhD,OAAON,cAAc,QAAS,OAAkBc;AAClD,EAAC"}
|
package/dist/createVersion.d.ts
CHANGED
|
@@ -5,11 +5,12 @@ import type { CreateVersion } from 'payload';
|
|
|
5
5
|
*
|
|
6
6
|
* Two round trips:
|
|
7
7
|
* 1. `Query` the versions partition for the previous `latest=true` row.
|
|
8
|
-
* 2. `
|
|
9
|
-
* new row in one atomic call. If a crash occurs
|
|
10
|
-
* mutation lands, so we never end up with two
|
|
11
|
-
* zero. The
|
|
12
|
-
* fails cleanly if the previous row was deleted between
|
|
8
|
+
* 2. `putVersionAsLatest` flips that row's `latest` to false and puts the
|
|
9
|
+
* new row in one atomic `TransactWriteItems` call. If a crash occurs
|
|
10
|
+
* mid-flow neither mutation lands, so we never end up with two
|
|
11
|
+
* `latest=true` rows or zero. The flip carries `attribute_exists(pk)` so
|
|
12
|
+
* the transaction fails cleanly if the previous row was deleted between
|
|
13
|
+
* (1) and (2).
|
|
13
14
|
*
|
|
14
15
|
* `autosave` is persisted on the row even though it isn't surfaced in
|
|
15
16
|
* `TypeWithVersion` — `findVersions` filters by it.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createVersion.d.ts","sourceRoot":"","sources":["../src/createVersion.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"createVersion.d.ts","sourceRoot":"","sources":["../src/createVersion.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAU5C;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,aAAa,EAAE,aA6C3B,CAAA"}
|