@gencow/core 0.1.27 → 0.1.28
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/dist/document-types.d.ts +65 -0
- package/dist/document-types.js +15 -0
- package/dist/grounded-answer-types.d.ts +62 -0
- package/dist/grounded-answer-types.js +6 -0
- package/dist/index.d.ts +10 -1
- package/dist/index.js +4 -0
- package/dist/rag-ingest-types.d.ts +39 -0
- package/dist/rag-ingest-types.js +1 -0
- package/dist/rag-operations-types.d.ts +81 -0
- package/dist/rag-operations-types.js +1 -0
- package/dist/rag-schema.d.ts +1557 -0
- package/dist/rag-schema.js +87 -0
- package/dist/reactive.d.ts +13 -0
- package/dist/rls-db.d.ts +9 -2
- package/dist/runtime-env-policy.d.ts +5 -0
- package/dist/runtime-env-policy.js +56 -0
- package/dist/search-types.d.ts +83 -0
- package/dist/search-types.js +1 -0
- package/dist/server.d.ts +1 -2
- package/dist/server.js +0 -1
- package/dist/storage-shared.d.ts +36 -0
- package/dist/storage-shared.js +39 -0
- package/dist/storage.d.ts +2 -26
- package/dist/storage.js +19 -15
- package/dist/workflow-types.d.ts +3 -1
- package/package.json +8 -7
- package/src/document-types.ts +95 -0
- package/src/grounded-answer-types.ts +78 -0
- package/src/index.ts +66 -1
- package/src/rag-ingest-types.ts +52 -0
- package/src/rag-operations-types.ts +90 -0
- package/src/rag-schema.ts +94 -0
- package/src/reactive.ts +13 -0
- package/src/rls-db.ts +9 -4
- package/src/runtime-env-policy.ts +66 -0
- package/src/search-types.ts +91 -0
- package/src/server.ts +1 -2
- package/src/storage-shared.ts +74 -0
- package/src/storage.ts +29 -46
- package/src/workflow-types.ts +3 -1
- package/src/__tests__/auth.test.ts +0 -118
- package/src/__tests__/crons.test.ts +0 -83
- package/src/__tests__/crud-codegen-integration.test.ts +0 -246
- package/src/__tests__/crud-owner-rls.test.ts +0 -387
- package/src/__tests__/crud.test.ts +0 -930
- package/src/__tests__/dist-exports.test.ts +0 -176
- package/src/__tests__/fixtures/basic/auth.ts +0 -32
- package/src/__tests__/fixtures/basic/drizzle.config.ts +0 -12
- package/src/__tests__/fixtures/basic/index.ts +0 -6
- package/src/__tests__/fixtures/basic/migrations/0000_last_warstar.sql +0 -75
- package/src/__tests__/fixtures/basic/migrations/meta/0000_snapshot.json +0 -497
- package/src/__tests__/fixtures/basic/migrations/meta/_journal.json +0 -13
- package/src/__tests__/fixtures/basic/schema.ts +0 -51
- package/src/__tests__/fixtures/basic/tasks.ts +0 -15
- package/src/__tests__/fixtures/common/auth-schema.ts +0 -67
- package/src/__tests__/helpers/basic-rls-fixture.ts +0 -135
- package/src/__tests__/helpers/pglite-migrations.ts +0 -32
- package/src/__tests__/helpers/pglite-rls-session.ts +0 -51
- package/src/__tests__/helpers/seed-like-fill.ts +0 -202
- package/src/__tests__/helpers/test-gencow-ctx-rls.ts +0 -50
- package/src/__tests__/httpaction.test.ts +0 -122
- package/src/__tests__/image-optimization.test.ts +0 -648
- package/src/__tests__/load.test.ts +0 -389
- package/src/__tests__/network-sim.test.ts +0 -319
- package/src/__tests__/reactive.test.ts +0 -479
- package/src/__tests__/retry.test.ts +0 -113
- package/src/__tests__/rls-crud-basic.test.ts +0 -317
- package/src/__tests__/rls-crud-no-owner-rls-pglite.test.ts +0 -117
- package/src/__tests__/rls-custom-mutation-handlers.test.ts +0 -142
- package/src/__tests__/rls-custom-query-handlers.test.ts +0 -128
- package/src/__tests__/rls-db-leased-connection.test.ts +0 -118
- package/src/__tests__/rls-session-and-policies.test.ts +0 -228
- package/src/__tests__/scheduler-durable-v2.test.ts +0 -288
- package/src/__tests__/scheduler-durable.test.ts +0 -173
- package/src/__tests__/scheduler-exec.test.ts +0 -328
- package/src/__tests__/scheduler.test.ts +0 -187
- package/src/__tests__/storage.test.ts +0 -334
- package/src/__tests__/tsconfig.json +0 -8
- package/src/__tests__/validator.test.ts +0 -323
- package/src/__tests__/workflow.test.ts +0 -606
- package/src/__tests__/ws-integration.test.ts +0 -309
- package/src/__tests__/ws-scale.test.ts +0 -241
- package/src/auth.ts +0 -155
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* packages/core/src/__tests__/dist-exports.test.ts
|
|
3
|
-
*
|
|
4
|
-
* dist/ 빌드 산출물의 필수 export 검증 — npm publish 전 안전망.
|
|
5
|
-
*
|
|
6
|
-
* 이 테스트의 존재 이유:
|
|
7
|
-
* 2026-04-02 사고: 소스코드에 crud v2가 완전 구현되어 있었으나,
|
|
8
|
-
* dist/index.js에 `crud` export가 누락된 구버전이 npm에 배포됨.
|
|
9
|
-
* crud.test.ts(16 pass)가 src/crud.ts를 직접 import하므로
|
|
10
|
-
* dist/ 빌드 결과물의 정합성은 검증하지 못했음.
|
|
11
|
-
*
|
|
12
|
-
* 검증 항목:
|
|
13
|
-
* 1. dist/index.js 파일 존재
|
|
14
|
-
* 2. 필수 named export 존재 (crud, query, mutation, v, ...)
|
|
15
|
-
* 3. gencowCrud deprecated alias 존재 (하위호환)
|
|
16
|
-
* 4. crud가 실제 함수인지 (typeof === "function")
|
|
17
|
-
* 5. dist/index.js의 crud와 src/crud.ts의 crud가 동일 함수인지
|
|
18
|
-
*
|
|
19
|
-
* Run: bun test packages/core/src/__tests__/dist-exports.test.ts
|
|
20
|
-
*
|
|
21
|
-
* @see docs/analysis/analysis-test032-gencow-crud-api-mismatch.md
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
import { describe, it, expect } from "bun:test";
|
|
25
|
-
import { existsSync } from "fs";
|
|
26
|
-
import { resolve, dirname } from "path";
|
|
27
|
-
import { fileURLToPath } from "url";
|
|
28
|
-
|
|
29
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
30
|
-
const CORE_ROOT = resolve(__dirname, "../..");
|
|
31
|
-
const DIST_INDEX = resolve(CORE_ROOT, "dist/index.js");
|
|
32
|
-
|
|
33
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
34
|
-
// 1. dist/ 파일 존재 확인
|
|
35
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
36
|
-
|
|
37
|
-
describe("dist/ 빌드 산출물 존재", () => {
|
|
38
|
-
it("dist/index.js 파일이 존재한다", () => {
|
|
39
|
-
expect(existsSync(DIST_INDEX)).toBe(true);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it("dist/crud.js 파일이 존재한다", () => {
|
|
43
|
-
expect(existsSync(resolve(CORE_ROOT, "dist/crud.js"))).toBe(true);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it("dist/reactive.js 파일이 존재한다", () => {
|
|
47
|
-
expect(existsSync(resolve(CORE_ROOT, "dist/reactive.js"))).toBe(true);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it("dist/v.js 파일이 존재한다", () => {
|
|
51
|
-
expect(existsSync(resolve(CORE_ROOT, "dist/v.js"))).toBe(true);
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
56
|
-
// 2. 필수 named export 존재 확인
|
|
57
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
58
|
-
|
|
59
|
-
describe("dist/index.js 필수 export", () => {
|
|
60
|
-
let distModule: Record<string, unknown>;
|
|
61
|
-
|
|
62
|
-
// dist/index.js를 dynamic import (빌드 결과물 검증)
|
|
63
|
-
it("dist/index.js를 import할 수 있다", async () => {
|
|
64
|
-
distModule = await import(DIST_INDEX);
|
|
65
|
-
expect(distModule).toBeDefined();
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
// ── Core API exports ──────────────────────────────────────
|
|
69
|
-
|
|
70
|
-
it("crud export가 존재하고 함수이다", async () => {
|
|
71
|
-
if (!distModule) distModule = await import(DIST_INDEX);
|
|
72
|
-
expect(distModule.crud).toBeDefined();
|
|
73
|
-
expect(typeof distModule.crud).toBe("function");
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it("gencowCrud deprecated alias가 존재하고 crud와 동일하다", async () => {
|
|
77
|
-
if (!distModule) distModule = await import(DIST_INDEX);
|
|
78
|
-
expect(distModule.gencowCrud).toBeDefined();
|
|
79
|
-
expect(distModule.gencowCrud).toBe(distModule.crud);
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it("query export가 존재하고 함수이다", async () => {
|
|
83
|
-
if (!distModule) distModule = await import(DIST_INDEX);
|
|
84
|
-
expect(distModule.query).toBeDefined();
|
|
85
|
-
expect(typeof distModule.query).toBe("function");
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
it("mutation export가 존재하고 함수이다", async () => {
|
|
89
|
-
if (!distModule) distModule = await import(DIST_INDEX);
|
|
90
|
-
expect(distModule.mutation).toBeDefined();
|
|
91
|
-
expect(typeof distModule.mutation).toBe("function");
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
it("workflow export가 존재하고 함수이다", async () => {
|
|
95
|
-
if (!distModule) distModule = await import(DIST_INDEX);
|
|
96
|
-
expect(distModule.workflow).toBeDefined();
|
|
97
|
-
expect(typeof distModule.workflow).toBe("function");
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
it("v export가 존재하고 객체이다", async () => {
|
|
101
|
-
if (!distModule) distModule = await import(DIST_INDEX);
|
|
102
|
-
expect(distModule.v).toBeDefined();
|
|
103
|
-
expect(typeof distModule.v).toBe("object");
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
it("httpAction export가 존재하고 함수이다", async () => {
|
|
107
|
-
if (!distModule) distModule = await import(DIST_INDEX);
|
|
108
|
-
expect(distModule.httpAction).toBeDefined();
|
|
109
|
-
expect(typeof distModule.httpAction).toBe("function");
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
// ── Registry exports (codegen 의존) ────────────────────────
|
|
113
|
-
|
|
114
|
-
it("getRegisteredQueries export가 존재한다", async () => {
|
|
115
|
-
if (!distModule) distModule = await import(DIST_INDEX);
|
|
116
|
-
expect(distModule.getRegisteredQueries).toBeDefined();
|
|
117
|
-
expect(typeof distModule.getRegisteredQueries).toBe("function");
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
it("getRegisteredMutations export가 존재한다", async () => {
|
|
121
|
-
if (!distModule) distModule = await import(DIST_INDEX);
|
|
122
|
-
expect(distModule.getRegisteredMutations).toBeDefined();
|
|
123
|
-
expect(typeof distModule.getRegisteredMutations).toBe("function");
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
// ── RLS + Auth exports ─────────────────────────────────────
|
|
127
|
-
|
|
128
|
-
it("ownerRls export가 존재한다", async () => {
|
|
129
|
-
if (!distModule) distModule = await import(DIST_INDEX);
|
|
130
|
-
expect(distModule.ownerRls).toBeDefined();
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
it("defineAuth export가 존재한다", async () => {
|
|
134
|
-
if (!distModule) distModule = await import(DIST_INDEX);
|
|
135
|
-
expect(distModule.defineAuth).toBeDefined();
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
it("cronJobs export가 존재한다", async () => {
|
|
139
|
-
if (!distModule) distModule = await import(DIST_INDEX);
|
|
140
|
-
expect(distModule.cronJobs).toBeDefined();
|
|
141
|
-
});
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
145
|
-
// 3. dist/crud.js가 v2 구현인지 확인 (커링 구조가 아닌지)
|
|
146
|
-
// ═══════════════════════════════════════════════════════════════════════════════
|
|
147
|
-
|
|
148
|
-
describe("dist/crud.js — v2 구현 검증", () => {
|
|
149
|
-
it("crud(table) 시그니처이다 (커링 gencowCrud(db)(table) 아님)", async () => {
|
|
150
|
-
const distModule = await import(DIST_INDEX);
|
|
151
|
-
const { crud } = distModule;
|
|
152
|
-
|
|
153
|
-
// v2: crud(table, options?) → { list, get, create, update, remove }
|
|
154
|
-
// 구버전: gencowCrud(db) → (table, options?) → { create, findById, list, ... }
|
|
155
|
-
|
|
156
|
-
// 실제 Drizzle 테이블로 테스트
|
|
157
|
-
const { pgTable, serial, text } = await import("drizzle-orm/pg-core");
|
|
158
|
-
const testTable = pgTable("dist_smoke_test", {
|
|
159
|
-
id: serial("id").primaryKey(),
|
|
160
|
-
name: text("name"),
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
const result = crud(testTable, { public: true });
|
|
164
|
-
|
|
165
|
-
// v2는 { list, get, create, update, remove } 반환
|
|
166
|
-
expect(result).toHaveProperty("list");
|
|
167
|
-
expect(result).toHaveProperty("get");
|
|
168
|
-
expect(result).toHaveProperty("create");
|
|
169
|
-
expect(result).toHaveProperty("update");
|
|
170
|
-
expect(result).toHaveProperty("remove");
|
|
171
|
-
|
|
172
|
-
// 구버전(커링)은 함수를 반환하므로 이 검증이 실패함
|
|
173
|
-
expect(typeof result).toBe("object");
|
|
174
|
-
expect(typeof result.list).not.toBe("undefined");
|
|
175
|
-
});
|
|
176
|
-
});
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* gencow/auth.ts
|
|
3
|
-
*
|
|
4
|
-
* Auth 설정 파일. 이 파일을 수정하여 인증 동작을 커스터마이즈할 수 있습니다.
|
|
5
|
-
* shadcn처럼 이 파일은 사용자가 소유합니다 — 자유롭게 수정하세요.
|
|
6
|
-
*
|
|
7
|
-
* @example Email Verification 활성화:
|
|
8
|
-
* 1. `bun add resend`
|
|
9
|
-
* 2. 아래 emailVerification 블록 주석 해제
|
|
10
|
-
* 3. `gencow env set RESEND_API_KEY re_xxxx`
|
|
11
|
-
*
|
|
12
|
-
* @see https://docs.gencow.com/auth
|
|
13
|
-
*/
|
|
14
|
-
import { defineAuth } from "../../../auth-config.js";
|
|
15
|
-
|
|
16
|
-
export default defineAuth({
|
|
17
|
-
// ── Email Verification (선택) ──────────────────────
|
|
18
|
-
// 아래 주석을 해제하면 가입 시 이메일 인증이 활성화됩니다.
|
|
19
|
-
//
|
|
20
|
-
// emailVerification: {
|
|
21
|
-
// sendVerificationEmail: async ({ user, url }) => {
|
|
22
|
-
// const { Resend } = await import("resend");
|
|
23
|
-
// const resend = new Resend(process.env.RESEND_API_KEY);
|
|
24
|
-
// await resend.emails.send({
|
|
25
|
-
// from: "noreply@yourapp.com",
|
|
26
|
-
// to: user.email,
|
|
27
|
-
// subject: "이메일 인증",
|
|
28
|
-
// html: `<a href="${url}">인증하기</a>`,
|
|
29
|
-
// });
|
|
30
|
-
// },
|
|
31
|
-
// },
|
|
32
|
-
});
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from "drizzle-kit";
|
|
2
|
-
import { dirname, resolve } from "node:path";
|
|
3
|
-
import { fileURLToPath } from "node:url";
|
|
4
|
-
|
|
5
|
-
/** Config dir — schema/out paths must not depend on process.cwd (pnpm exec uses package root). */
|
|
6
|
-
const here = dirname(fileURLToPath(import.meta.url));
|
|
7
|
-
|
|
8
|
-
export default defineConfig({
|
|
9
|
-
dialect: "postgresql",
|
|
10
|
-
schema: [resolve(here, "schema.ts"), resolve(here, "../common/auth-schema.ts")],
|
|
11
|
-
out: resolve(here, "migrations"),
|
|
12
|
-
});
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
CREATE TABLE "news" (
|
|
2
|
-
"id" text PRIMARY KEY NOT NULL,
|
|
3
|
-
"title" text NOT NULL,
|
|
4
|
-
"user_id" text NOT NULL,
|
|
5
|
-
"created_at" timestamp DEFAULT now() NOT NULL,
|
|
6
|
-
"updated_at" timestamp DEFAULT now() NOT NULL
|
|
7
|
-
);
|
|
8
|
-
--> statement-breakpoint
|
|
9
|
-
CREATE TABLE "tasks" (
|
|
10
|
-
"id" text PRIMARY KEY NOT NULL,
|
|
11
|
-
"title" text NOT NULL,
|
|
12
|
-
"description" text,
|
|
13
|
-
"done" boolean DEFAULT false NOT NULL,
|
|
14
|
-
"user_id" text NOT NULL,
|
|
15
|
-
"created_at" timestamp DEFAULT now() NOT NULL,
|
|
16
|
-
"updated_at" timestamp DEFAULT now() NOT NULL
|
|
17
|
-
);
|
|
18
|
-
--> statement-breakpoint
|
|
19
|
-
ALTER TABLE "tasks" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint
|
|
20
|
-
CREATE TABLE "user" (
|
|
21
|
-
"id" text PRIMARY KEY NOT NULL,
|
|
22
|
-
"name" text NOT NULL,
|
|
23
|
-
"email" text NOT NULL,
|
|
24
|
-
"email_verified" boolean DEFAULT false NOT NULL,
|
|
25
|
-
"image" text,
|
|
26
|
-
"created_at" timestamp DEFAULT now() NOT NULL,
|
|
27
|
-
"updated_at" timestamp DEFAULT now() NOT NULL,
|
|
28
|
-
CONSTRAINT "user_email_unique" UNIQUE("email")
|
|
29
|
-
);
|
|
30
|
-
--> statement-breakpoint
|
|
31
|
-
CREATE TABLE "account" (
|
|
32
|
-
"id" text PRIMARY KEY NOT NULL,
|
|
33
|
-
"account_id" text NOT NULL,
|
|
34
|
-
"provider_id" text NOT NULL,
|
|
35
|
-
"user_id" text NOT NULL,
|
|
36
|
-
"access_token" text,
|
|
37
|
-
"refresh_token" text,
|
|
38
|
-
"id_token" text,
|
|
39
|
-
"access_token_expires_at" timestamp,
|
|
40
|
-
"refresh_token_expires_at" timestamp,
|
|
41
|
-
"scope" text,
|
|
42
|
-
"password" text,
|
|
43
|
-
"created_at" timestamp DEFAULT now() NOT NULL,
|
|
44
|
-
"updated_at" timestamp DEFAULT now() NOT NULL
|
|
45
|
-
);
|
|
46
|
-
--> statement-breakpoint
|
|
47
|
-
CREATE TABLE "session" (
|
|
48
|
-
"id" text PRIMARY KEY NOT NULL,
|
|
49
|
-
"expires_at" timestamp NOT NULL,
|
|
50
|
-
"token" text NOT NULL,
|
|
51
|
-
"created_at" timestamp DEFAULT now() NOT NULL,
|
|
52
|
-
"updated_at" timestamp DEFAULT now() NOT NULL,
|
|
53
|
-
"ip_address" text,
|
|
54
|
-
"user_agent" text,
|
|
55
|
-
"user_id" text NOT NULL,
|
|
56
|
-
CONSTRAINT "session_token_unique" UNIQUE("token")
|
|
57
|
-
);
|
|
58
|
-
--> statement-breakpoint
|
|
59
|
-
CREATE TABLE "verification" (
|
|
60
|
-
"id" text PRIMARY KEY NOT NULL,
|
|
61
|
-
"identifier" text NOT NULL,
|
|
62
|
-
"value" text NOT NULL,
|
|
63
|
-
"expires_at" timestamp NOT NULL,
|
|
64
|
-
"created_at" timestamp DEFAULT now(),
|
|
65
|
-
"updated_at" timestamp DEFAULT now()
|
|
66
|
-
);
|
|
67
|
-
--> statement-breakpoint
|
|
68
|
-
ALTER TABLE "news" ADD CONSTRAINT "news_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
69
|
-
ALTER TABLE "tasks" ADD CONSTRAINT "tasks_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
70
|
-
ALTER TABLE "account" ADD CONSTRAINT "account_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
71
|
-
ALTER TABLE "session" ADD CONSTRAINT "session_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
72
|
-
CREATE POLICY "rls-select" ON "tasks" AS PERMISSIVE FOR SELECT TO public USING ("tasks"."user_id" = current_setting('app.current_user_id', true));--> statement-breakpoint
|
|
73
|
-
CREATE POLICY "rls-insert" ON "tasks" AS PERMISSIVE FOR INSERT TO public WITH CHECK ("tasks"."user_id" = current_setting('app.current_user_id', true));--> statement-breakpoint
|
|
74
|
-
CREATE POLICY "rls-update" ON "tasks" AS PERMISSIVE FOR UPDATE TO public USING ("tasks"."user_id" = current_setting('app.current_user_id', true)) WITH CHECK ("tasks"."user_id" = current_setting('app.current_user_id', true));--> statement-breakpoint
|
|
75
|
-
CREATE POLICY "rls-delete" ON "tasks" AS PERMISSIVE FOR DELETE TO public USING ("tasks"."user_id" = current_setting('app.current_user_id', true));
|