Skip to content

Releases: OpenSaasAU/stack

@opensaas/stack-ui@0.26.0

Choose a tag to compare

@github-actions github-actions released this 28 Jun 05:06
6df14c6
@opensaas/stack-ui@0.26.0

@opensaas/stack-tiptap@0.26.0

Choose a tag to compare

@github-actions github-actions released this 28 Jun 05:06
6df14c6
@opensaas/stack-tiptap@0.26.0

@opensaas/stack-storage@0.26.0

Choose a tag to compare

@github-actions github-actions released this 28 Jun 05:06
6df14c6

Patch Changes

  • #619 29ca3a9 Thanks @borisno2! - Fix file()/image() fields being required on create/update: their Zod schema now uses key-optionality (.nullish()) so an omitted field validates and stores null (Zod 4).

@opensaas/stack-storage-vercel@0.26.0

Choose a tag to compare

@github-actions github-actions released this 28 Jun 05:06
6df14c6
@opensaas/stack-storage-vercel@0.26.0

@opensaas/stack-storage-s3@0.26.0

Choose a tag to compare

@github-actions github-actions released this 28 Jun 05:06
6df14c6
@opensaas/stack-storage-s3@0.26.0

@opensaas/stack-rag@0.26.0

Choose a tag to compare

@github-actions github-actions released this 28 Jun 05:05
6df14c6
@opensaas/stack-rag@0.26.0

@opensaas/stack-core@0.26.0

Choose a tag to compare

@github-actions github-actions released this 28 Jun 05:06
6df14c6

Minor Changes

  • #616 322d5b6 Thanks @borisno2! - Add context.transaction() — an interactive, hook-firing transaction

    You can now run multiple access-checked context.db.* operations atomically in one transaction while preserving the access/hook boundary (unlike raw prisma.$transaction, which bypasses both). The callback receives a full context whose db.* operations enforce access control and run list/field hooks, but persist against a single interactive transaction — so a throw anywhere rolls the whole transaction back.

    Options (notably isolationLevel, plus maxWait/timeout) pass through to Prisma, and serialization failures (Prisma P2034) propagate to the caller so you own the retry loop. This makes concurrency-sensitive invariants such as a capacity gate enforceable:

    async function bookSlot(context, slotId) {
      for (let attempt = 0; attempt < 5; attempt++) {
        try {
          return await context.transaction(
            async (tx) => {
              const count = await tx.db.booking.count({ where: { slotId } })
              if (count >= CAPACITY) return { booked: false }
              return { booked: true, item: await tx.db.booking.create({ data: { slotId } }) }
            },
            { isolationLevel: 'Serializable' },
          )
        } catch (err) {
          // Serialization failures propagate — retry is caller-owned.
          if (err && typeof err === 'object' && 'code' in err && err.code === 'P2034') continue
          throw err
        }
      }
      throw new Error('exceeded retry budget')
    }

    Nested context.db writes inside the callback join the outer transaction. New StackContext, TransactionOptions, and TransactionIsolationLevel types are exported from @opensaas/stack-core. See ADR-0012.

Patch Changes

  • #620 0be254e Thanks @borisno2! - Apply a field's defaultValue to omitted inputs before create validation (resolve-then-validate, matching Keystone), so isRequired + defaultValue no longer fails on create.

    Note: because an omitted-but-defaulted field is now filled into resolvedData before validation, that field's create-side field-level beforeOperation/afterOperation hooks (gated on the field key being present in resolvedData) now fire for defaulted fields where they previously would not.

@opensaas/stack-cli@0.26.0

Choose a tag to compare

@github-actions github-actions released this 28 Jun 05:05
6df14c6

Patch Changes

  • Updated dependencies [322d5b6, 0be254e]:
    • @opensaas/stack-core@0.26.0

@opensaas/stack-auth@0.26.0

Choose a tag to compare

@github-actions github-actions released this 28 Jun 05:05
6df14c6
@opensaas/stack-auth@0.26.0

@opensaas/stack-ui@0.25.0

Choose a tag to compare

@github-actions github-actions released this 27 Jun 23:20
f9d020c

Patch Changes

  • #607 61547be Thanks @borisno2! - Fix ui.listView.initialSort applying sort client-side instead of as a DB-level orderBy

    Previously, initialSort was applied to the already-fetched page in memory, meaning a 500-row list with initialSort: { field: 'sentAt', direction: 'desc' } would only show the 50 most recent rows of the current page rather than the 50 most recent rows overall. The sort is now passed as orderBy to findMany so pagination and sorting compose correctly.

    Column-header clicks also now navigate with a ?sort=field:direction URL param (instead of mutating local state), so subsequent sorts are also DB-level and work correctly across pages.