(
options?: AdminListSubjectsOptions,
)
| 7008 | }; |
| 7009 | |
| 7010 | const listSubjects = ( |
| 7011 | options?: AdminListSubjectsOptions, |
| 7012 | ): Effect.Effect<readonly AdminSubject[], StorageFailure> => { |
| 7013 | // Always both, always integers — see `normalizeAdminPaging`. Passing |
| 7014 | // them through independently produced a bare OFFSET, which SQLite |
| 7015 | // rejects outright. |
| 7016 | const { limit, offset } = normalizeAdminPaging(options); |
| 7017 | const externalIds = options?.externalIds; |
| 7018 | // An empty id set is a query that cannot match; answer it without a |
| 7019 | // round trip rather than emitting `in ()`, which some drivers reject. |
| 7020 | if (externalIds !== undefined && externalIds.length === 0) return Effect.succeed([]); |
| 7021 | return platformCore |
| 7022 | .findMany("subject", { |
| 7023 | // The id filter is the ONLY predicate here; the tenant clause is |
| 7024 | // the policy's, added to every read the same way `getSubject` |
| 7025 | // relies on it. |
| 7026 | ...(externalIds === undefined |
| 7027 | ? {} |
| 7028 | : { where: (b: AnyCb) => b("external_id", "in", [...externalIds]) }), |
| 7029 | // Oldest first, ties broken on the unique key so the order is |
| 7030 | // total and paging can't repeat or skip a row. |
| 7031 | orderBy: [ |
| 7032 | ["created_at", "asc"], |
| 7033 | ["external_id", "asc"], |
| 7034 | ], |
| 7035 | limit, |
| 7036 | offset, |
| 7037 | }) |
| 7038 | .pipe(Effect.map((rows) => rows.map(rowToAdminSubject))); |
| 7039 | }; |
| 7040 | |
| 7041 | // Keyed on `(tenant, external_id)` — the table's unique index. No |
| 7042 | // `tenant` clause here: the tenant policy adds it to every read, the |
no test coverage detected