@govcore/schema 0.1.0 → 0.2.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/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @govcore/schema
2
2
 
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - d255afc: Operator-plane console mutations (#63). The org/user administration flows behind an instance console were rebuilt by every consumer (GovEA `actions/instance.ts`, GovCRM `lib/platform.ts`), and the user path is exactly where they diverged. Promote the mutations to core, composing the membership invariants from #65 so the guard and write-sync are identical everywhere.
8
+
9
+ `@govcore/tenancy` gains `createOrganization` (auto-slug via the new exported `slugify`; a duplicate slug returns a typed `slug-taken`), `renameOrganization` (name-only; audited before/after), and `updateUserAdministration` — the guard-heavy one: it enforces the last-active-admin invariant via `assertNotLastActiveAdmin` (inside the transaction) and an own-instance-admin lockout, updates the `users` row, and keeps the membership in lockstep via `upsertMembership`. All audited as `platform.org.*` / `platform.user.update` and generic over the app's admin role name; tenancy now depends on `@govcore/audit`.
10
+
11
+ `@govcore/auth` gains `provisionUser` — create a user with an initial password + primary membership. It lives here (not tenancy) because it hashes: validates against the policy, hashes, inserts, writes the membership through tenancy's `upsertMembership`, and audits `platform.user.create` without ever putting the password in the payload; a duplicate email returns a typed `email-taken`.
12
+
13
+ `@govcore/schema` gains `isUniqueViolation(err)` — a pure, edge-safe SQLSTATE-23505 predicate so operator flows turn a duplicate slug/email into a typed result instead of a 500.
14
+
15
+ All framework-agnostic (no FormData/redirect/revalidate — the consumer keeps the thin `'use server'` wrapper and the `instance_admin` gate) and returning typed results rather than throwing.
16
+
3
17
  ## 0.1.0
4
18
 
5
19
  ### Minor Changes
package/dist/index.d.ts CHANGED
@@ -6,6 +6,15 @@ export * from './schema';
6
6
  * app's `postgres-js` db, or a `tx` inside a transaction — which extends it).
7
7
  */
8
8
  export type GovcoreDb = PgDatabase<PgQueryResultHKT, any, any>;
9
+ /**
10
+ * True when `err` is (or wraps) a Postgres unique-constraint violation
11
+ * (SQLSTATE 23505). Pure and edge-safe — inspects `code`, touches no DB client.
12
+ * Lets operator flows turn a duplicate slug/email into a typed result instead of
13
+ * a 500. Walks the `cause` chain because Drizzle wraps the driver error in a
14
+ * `DrizzleQueryError` and puts the `postgres-js`/`pg` error (which carries the
15
+ * `code`) on `.cause` — so the top-level error's own `code` is undefined.
16
+ */
17
+ export declare function isUniqueViolation(err: unknown): boolean;
9
18
  /**
10
19
  * Bumped whenever the platform schema changes. Written to instance settings on
11
20
  * boot for observability ("this instance runs platform schema vN", design §5),
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAEvE,cAAc,UAAU,CAAA;AAExB;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,gBAAgB,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;AAE9D;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,UAAU,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAEvE,cAAc,UAAU,CAAA;AAExB;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,gBAAgB,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;AAE9D;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAMvD;AAED;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,UAAU,CAAA"}
package/dist/index.js CHANGED
@@ -1,6 +1,22 @@
1
1
  // @govcore/schema — platform table definitions + schema version.
2
2
  // Edge-safe entrypoint (no DB client). The migrate runner is ./migrate.
3
3
  export * from './schema';
4
+ /**
5
+ * True when `err` is (or wraps) a Postgres unique-constraint violation
6
+ * (SQLSTATE 23505). Pure and edge-safe — inspects `code`, touches no DB client.
7
+ * Lets operator flows turn a duplicate slug/email into a typed result instead of
8
+ * a 500. Walks the `cause` chain because Drizzle wraps the driver error in a
9
+ * `DrizzleQueryError` and puts the `postgres-js`/`pg` error (which carries the
10
+ * `code`) on `.cause` — so the top-level error's own `code` is undefined.
11
+ */
12
+ export function isUniqueViolation(err) {
13
+ for (let e = err, depth = 0; e && typeof e === 'object' && depth < 5; depth++) {
14
+ if (e.code === '23505')
15
+ return true;
16
+ e = e.cause;
17
+ }
18
+ return false;
19
+ }
4
20
  /**
5
21
  * Bumped whenever the platform schema changes. Written to instance settings on
6
22
  * boot for observability ("this instance runs platform schema vN", design §5),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@govcore/schema",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Platform tables, enums, migrations, and the govcore-migrate runner",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
package/src/index.ts CHANGED
@@ -12,6 +12,22 @@ export * from './schema'
12
12
  */
13
13
  export type GovcoreDb = PgDatabase<PgQueryResultHKT, any, any>
14
14
 
15
+ /**
16
+ * True when `err` is (or wraps) a Postgres unique-constraint violation
17
+ * (SQLSTATE 23505). Pure and edge-safe — inspects `code`, touches no DB client.
18
+ * Lets operator flows turn a duplicate slug/email into a typed result instead of
19
+ * a 500. Walks the `cause` chain because Drizzle wraps the driver error in a
20
+ * `DrizzleQueryError` and puts the `postgres-js`/`pg` error (which carries the
21
+ * `code`) on `.cause` — so the top-level error's own `code` is undefined.
22
+ */
23
+ export function isUniqueViolation(err: unknown): boolean {
24
+ for (let e: unknown = err, depth = 0; e && typeof e === 'object' && depth < 5; depth++) {
25
+ if ((e as { code?: string }).code === '23505') return true
26
+ e = (e as { cause?: unknown }).cause
27
+ }
28
+ return false
29
+ }
30
+
15
31
  /**
16
32
  * Bumped whenever the platform schema changes. Written to instance settings on
17
33
  * boot for observability ("this instance runs platform schema vN", design §5),