@palbase/backend 22.1.0 → 23.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/dist/bin/palbase-backend.cjs +750 -40
- package/dist/bin/palbase-backend.cjs.map +1 -1
- package/dist/bin/palbase-backend.js +5 -5
- package/dist/{chunk-YL4C5NRY.js → chunk-HQRJDARQ.js} +2 -2
- package/dist/{chunk-74XDEF5J.js → chunk-M5MCBWJI.js} +723 -37
- package/dist/chunk-M5MCBWJI.js.map +1 -0
- package/dist/{chunk-W5ODXPY3.js → chunk-NS5V43YQ.js} +14 -1
- package/dist/chunk-NS5V43YQ.js.map +1 -0
- package/dist/{chunk-SQC5EIWY.js → chunk-OHALWEOG.js} +19 -9
- package/dist/chunk-OHALWEOG.js.map +1 -0
- package/dist/{chunk-I3ON7MYF.js → chunk-PY7YJDCT.js} +129 -18
- package/dist/chunk-PY7YJDCT.js.map +1 -0
- package/dist/{chunk-N32VDWKH.js → chunk-R3KN6RHD.js} +4 -59
- package/dist/chunk-R3KN6RHD.js.map +1 -0
- package/dist/{chunk-QMVK4X3V.js → chunk-RCLNBJCM.js} +98 -98
- package/dist/chunk-RCLNBJCM.js.map +1 -0
- package/dist/db/env.cjs.map +1 -1
- package/dist/db/env.d.cts +3 -21
- package/dist/db/env.d.ts +3 -21
- package/dist/db/index.cjs +140 -16
- package/dist/db/index.cjs.map +1 -1
- package/dist/db/index.d.cts +3 -2
- package/dist/db/index.d.ts +3 -2
- package/dist/db/index.js +2 -2
- package/dist/{endpoint-BVT6jcVW.d.cts → endpoint-CVWXh6oG.d.ts} +147 -15
- package/dist/{endpoint-BVT6jcVW.d.ts → endpoint-c9h5jriX.d.cts} +147 -15
- package/dist/engine/index.cjs +750 -40
- package/dist/engine/index.cjs.map +1 -1
- package/dist/engine/index.d.cts +6 -5
- package/dist/engine/index.d.ts +6 -5
- package/dist/engine/index.js +4 -4
- package/dist/{index-BS1gW4nV.d.cts → index-BZrJXnVh.d.ts} +142 -72
- package/dist/{index-BqCiHao8.d.cts → index-By8Dle5U.d.cts} +196 -21
- package/dist/{index-vwHoS0l2.d.ts → index-CwAJ7HEe.d.ts} +196 -21
- package/dist/{index-CCZqzych.d.ts → index-CxeQSfJP.d.cts} +142 -72
- package/dist/index.cjs +388 -1101
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +89 -1134
- package/dist/index.d.ts +89 -1134
- package/dist/index.js +133 -902
- package/dist/index.js.map +1 -1
- package/dist/openapi/index.cjs +32 -61
- package/dist/openapi/index.cjs.map +1 -1
- package/dist/openapi/index.d.cts +6 -2
- package/dist/openapi/index.d.ts +6 -2
- package/dist/openapi/index.js +34 -26
- package/dist/openapi/index.js.map +1 -1
- package/dist/{registry-Bsuf-orT.d.ts → registry-B3niOVYp.d.ts} +108 -170
- package/dist/{registry-BWttGlaT.d.cts → registry-CqPK2Qby.d.cts} +108 -170
- package/dist/{purchases/keys.cjs → stack.cjs} +4 -4
- package/dist/stack.cjs.map +1 -0
- package/dist/stack.d.cts +76 -0
- package/dist/stack.d.ts +76 -0
- package/dist/stack.js +1 -0
- package/dist/test/index.cjs +482 -9
- package/dist/test/index.cjs.map +1 -1
- package/dist/test/index.d.cts +35 -3
- package/dist/test/index.d.ts +35 -3
- package/dist/test/index.js +480 -8
- package/dist/test/index.js.map +1 -1
- package/docs/README.md +7 -6
- package/docs/llms-full.txt +7 -260
- package/docs/llms.txt +0 -2
- package/package.json +9 -8
- package/stager/return_types.js +23 -0
- package/template/package.json +1 -1
- package/dist/chunk-74XDEF5J.js.map +0 -1
- package/dist/chunk-I3ON7MYF.js.map +0 -1
- package/dist/chunk-N32VDWKH.js.map +0 -1
- package/dist/chunk-QMVK4X3V.js.map +0 -1
- package/dist/chunk-SQC5EIWY.js.map +0 -1
- package/dist/chunk-W5ODXPY3.js.map +0 -1
- package/dist/purchases/keys.cjs.map +0 -1
- package/dist/purchases/keys.d.cts +0 -42
- package/dist/purchases/keys.d.ts +0 -42
- package/dist/purchases/keys.js +0 -1
- package/docs/config.md +0 -147
- package/docs/resources.md +0 -97
- package/template/config/secrets.ts +0 -24
- /package/dist/{chunk-YL4C5NRY.js.map → chunk-HQRJDARQ.js.map} +0 -0
- /package/dist/{purchases/keys.js.map → stack.js.map} +0 -0
package/dist/db/env.d.cts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export { BucketTypes, Buckets } from '../stack.cjs';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* `@palbase/backend/env` — the controlled global augmentation target for the
|
|
3
5
|
* project's schema.
|
|
@@ -55,25 +57,5 @@ interface TableTypes {
|
|
|
55
57
|
*/
|
|
56
58
|
interface Tables {
|
|
57
59
|
}
|
|
58
|
-
/**
|
|
59
|
-
* One typed bucket: which renditions `config/storage.ts` declared for it.
|
|
60
|
-
*
|
|
61
|
-
* `variants` is a UNION of the declared names, so asking for one the bucket
|
|
62
|
-
* does not have is a compile error rather than a 404 somebody finds in
|
|
63
|
-
* production. The generated `palbase-env.d.ts` fills it; the default `never`
|
|
64
|
-
* means a bucket declared without variants accepts no variant name at all,
|
|
65
|
-
* which is exactly right.
|
|
66
|
-
*/
|
|
67
|
-
interface BucketTypes {
|
|
68
|
-
variants: string;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* The project's storage buckets, keyed by bucket name. EMPTY by default; the
|
|
72
|
-
* generated `palbase-env.d.ts` augments it, so `Storage.buckets` is typed
|
|
73
|
-
* everywhere with no per-file import — the same mechanism `Tables` uses, and
|
|
74
|
-
* deliberately so: an author learns one pattern.
|
|
75
|
-
*/
|
|
76
|
-
interface Buckets {
|
|
77
|
-
}
|
|
78
60
|
|
|
79
|
-
export type {
|
|
61
|
+
export type { TableTypes, Tables };
|
package/dist/db/env.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export { BucketTypes, Buckets } from '../stack.js';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* `@palbase/backend/env` — the controlled global augmentation target for the
|
|
3
5
|
* project's schema.
|
|
@@ -55,25 +57,5 @@ interface TableTypes {
|
|
|
55
57
|
*/
|
|
56
58
|
interface Tables {
|
|
57
59
|
}
|
|
58
|
-
/**
|
|
59
|
-
* One typed bucket: which renditions `config/storage.ts` declared for it.
|
|
60
|
-
*
|
|
61
|
-
* `variants` is a UNION of the declared names, so asking for one the bucket
|
|
62
|
-
* does not have is a compile error rather than a 404 somebody finds in
|
|
63
|
-
* production. The generated `palbase-env.d.ts` fills it; the default `never`
|
|
64
|
-
* means a bucket declared without variants accepts no variant name at all,
|
|
65
|
-
* which is exactly right.
|
|
66
|
-
*/
|
|
67
|
-
interface BucketTypes {
|
|
68
|
-
variants: string;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* The project's storage buckets, keyed by bucket name. EMPTY by default; the
|
|
72
|
-
* generated `palbase-env.d.ts` augments it, so `Storage.buckets` is typed
|
|
73
|
-
* everywhere with no per-file import — the same mechanism `Tables` uses, and
|
|
74
|
-
* deliberately so: an author learns one pattern.
|
|
75
|
-
*/
|
|
76
|
-
interface Buckets {
|
|
77
|
-
}
|
|
78
60
|
|
|
79
|
-
export type {
|
|
61
|
+
export type { TableTypes, Tables };
|
package/dist/db/index.cjs
CHANGED
|
@@ -47,6 +47,9 @@ __export(db_exports, {
|
|
|
47
47
|
module.exports = __toCommonJS(db_exports);
|
|
48
48
|
|
|
49
49
|
// src/db/policy.ts
|
|
50
|
+
function quote(name) {
|
|
51
|
+
return `"${name.replace(/"/g, '""')}"`;
|
|
52
|
+
}
|
|
50
53
|
var PolicyBuilder = class {
|
|
51
54
|
_def;
|
|
52
55
|
constructor(name) {
|
|
@@ -82,6 +85,41 @@ var PolicyBuilder = class {
|
|
|
82
85
|
this._def.using = sqlExpr;
|
|
83
86
|
return this;
|
|
84
87
|
}
|
|
88
|
+
/**
|
|
89
|
+
* "Rows of THIS table whose owner the caller is a member of" — the membership
|
|
90
|
+
* pattern, written so it cannot recurse.
|
|
91
|
+
*
|
|
92
|
+
* THE TRAP IT EXISTS FOR. Written by hand, membership policies point at each
|
|
93
|
+
* other: `channels` is visible to members, so its policy reads
|
|
94
|
+
* `channel_members`; `channel_members` is visible to members, so its policy
|
|
95
|
+
* reads `channels`. Postgres refuses the pair at query time with `infinite
|
|
96
|
+
* recursion detected in policy for relation ...`, and the error names the
|
|
97
|
+
* relation but not the cycle. The way out is asymmetry — the MEMBERSHIP table
|
|
98
|
+
* is protected by `user_id = auth.uid()` and nothing else, and every other
|
|
99
|
+
* table subqueries INTO it. That shape was in the platform's own schema and
|
|
100
|
+
* written down nowhere; a customer recovered it by reading that schema.
|
|
101
|
+
*
|
|
102
|
+
* `(select auth.uid())` rather than a bare call: the scalar subquery is
|
|
103
|
+
* evaluated ONCE per statement instead of per row.
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* // channels: visible to members. The membership table gets the simple one.
|
|
107
|
+
* policy("member_read").for("select").to("authenticated")
|
|
108
|
+
* .memberOf("channel_members", "channel_id")
|
|
109
|
+
* // → id IN (SELECT "channel_id" FROM "channel_members"
|
|
110
|
+
* // WHERE "user_id" = (select auth.uid()))
|
|
111
|
+
*/
|
|
112
|
+
memberOf(membershipTable, foreignKey, options = {}) {
|
|
113
|
+
if (this._def.using !== null) {
|
|
114
|
+
throw new Error(
|
|
115
|
+
`policy(${this._def.name}).memberOf(): this policy already has a using() expression. Write one or the other \u2014 memberOf IS the using expression.`
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
const column = options.column ?? "id";
|
|
119
|
+
const userColumn = options.userColumn ?? "user_id";
|
|
120
|
+
this._def.using = `${quote(column)} IN (SELECT ${quote(foreignKey)} FROM ${quote(membershipTable)} WHERE ${quote(userColumn)} = (select auth.uid()))`;
|
|
121
|
+
return this;
|
|
122
|
+
}
|
|
85
123
|
/** Set the `WITH CHECK (...)` write-validation expression (raw SQL). */
|
|
86
124
|
withCheck(sqlExpr) {
|
|
87
125
|
this._def.withCheck = sqlExpr;
|
|
@@ -121,27 +159,81 @@ function defineSchema(input) {
|
|
|
121
159
|
if (table.checks !== void 0 && table.checks.length > 0) tableDef.checks = table.checks.slice();
|
|
122
160
|
if (table.indexes !== void 0 && table.indexes.length > 0) tableDef.indexes = table.indexes.slice();
|
|
123
161
|
if (table.search !== void 0) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
if (
|
|
135
|
-
throw new Error(
|
|
162
|
+
const s = table.search;
|
|
163
|
+
if (s.from !== void 0) {
|
|
164
|
+
if (s.vector !== void 0) {
|
|
165
|
+
throw new Error(
|
|
166
|
+
`table ${String(name)}: search beyan\u0131nda tek bi\xE7im kullan\u0131n \u2014 'from' (yeni) ile 'vector' (eski) birlikte olamaz`
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
if (s.from.length === 0) {
|
|
170
|
+
throw new Error(`table ${String(name)}: search.from bo\u015F olamaz`);
|
|
171
|
+
}
|
|
172
|
+
if (s.model === void 0) {
|
|
173
|
+
throw new Error(
|
|
174
|
+
`table ${String(name)}: search.from model'siz anlams\u0131z \u2014 auto-embed i\xE7in model verin (BYO i\xE7in eski 'vector' bi\xE7imini kullan\u0131n)`
|
|
175
|
+
);
|
|
136
176
|
}
|
|
137
|
-
if (
|
|
138
|
-
throw new Error(`table ${String(name)}: search.
|
|
177
|
+
if (Array.isArray(s.text) && s.text.length === 0) {
|
|
178
|
+
throw new Error(`table ${String(name)}: search.text bo\u015F dizi olamaz \u2014 FTS istemiyorsan text: false yaz\u0131n`);
|
|
139
179
|
}
|
|
180
|
+
} else {
|
|
181
|
+
if (typeof s.text === "boolean") {
|
|
182
|
+
throw new Error(`table ${String(name)}: text:${String(s.text)} yaln\u0131z yeni bi\xE7imde ('from' ile) ge\xE7erli`);
|
|
183
|
+
}
|
|
184
|
+
if (s.text === void 0 && s.vector === void 0) {
|
|
185
|
+
throw new Error(
|
|
186
|
+
`table ${String(name)}: search beyan\u0131 bo\u015F \u2014 en az bir kol (text ya da vector) verin, yoksa alan\u0131 hi\xE7 yazmay\u0131n`
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
if (s.text !== void 0 && s.text.length === 0) {
|
|
190
|
+
throw new Error(`table ${String(name)}: search.text bo\u015F olamaz \u2014 FTS kolu istemiyorsan alan\u0131 hi\xE7 yazma`);
|
|
191
|
+
}
|
|
192
|
+
const legs = s.vector === void 0 ? [] : Array.isArray(s.vector) ? s.vector : [s.vector];
|
|
193
|
+
for (const leg of legs) {
|
|
194
|
+
if (leg.model !== void 0 && (leg.from === void 0 || leg.from.length === 0)) {
|
|
195
|
+
throw new Error(`table ${String(name)}: search.vector.model beyan edildi ama 'from' yok \u2014 embed kayna\u011F\u0131 kolonlar zorunlu (C-2)`);
|
|
196
|
+
}
|
|
197
|
+
if (leg.model === void 0 && leg.from !== void 0) {
|
|
198
|
+
throw new Error(`table ${String(name)}: search.vector.from model'siz anlams\u0131z \u2014 auto-embed i\xE7in model verin`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
tableDef.search = s;
|
|
203
|
+
}
|
|
204
|
+
if (table.memory !== void 0) {
|
|
205
|
+
if (table.memory.from.length === 0) {
|
|
206
|
+
throw new Error(`table ${String(name)}: memory.from bo\u015F olamaz`);
|
|
140
207
|
}
|
|
141
|
-
tableDef.
|
|
208
|
+
tableDef.memory = table.memory;
|
|
142
209
|
}
|
|
143
210
|
tables[name] = tableDef;
|
|
144
211
|
}
|
|
212
|
+
for (const [name, def] of Object.entries(tables)) {
|
|
213
|
+
const m = def.memory;
|
|
214
|
+
if (m === void 0) continue;
|
|
215
|
+
const target = Object.values(tables).find((t) => t.name === m.into);
|
|
216
|
+
if (target === void 0) {
|
|
217
|
+
throw new Error(`table ${name}: memory.into "${m.into}" \u015Femada declared de\u011Fil`);
|
|
218
|
+
}
|
|
219
|
+
const subject = m.subject ?? "owner";
|
|
220
|
+
if (!(subject in def.columns)) {
|
|
221
|
+
throw new Error(`table ${name}: memory.subject "${subject}" kolonu kaynak tabloda yok`);
|
|
222
|
+
}
|
|
223
|
+
if (!(subject in target.columns)) {
|
|
224
|
+
throw new Error(`table ${name}: memory.subject "${subject}" kolonu hedef "${m.into}" tablosunda yok`);
|
|
225
|
+
}
|
|
226
|
+
const factCol = target.columns["fact"];
|
|
227
|
+
const factDef = factCol !== void 0 && "_def" in factCol ? factCol._def : factCol;
|
|
228
|
+
if (factDef === void 0 || factDef.type !== "text") {
|
|
229
|
+
throw new Error(`table ${name}: memory.into "${m.into}" tablosunda "fact" (text) kolonu zorunlu`);
|
|
230
|
+
}
|
|
231
|
+
for (const c of m.from) {
|
|
232
|
+
if (!(c in def.columns)) {
|
|
233
|
+
throw new Error(`table ${name}: memory.from kolonu "${c}" kaynak tabloda yok`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
145
237
|
const extensions = [...new Set(input.extensions ?? [])];
|
|
146
238
|
return { tables, extensions };
|
|
147
239
|
}
|
|
@@ -235,6 +327,21 @@ var ColumnBuilder = class _ColumnBuilder {
|
|
|
235
327
|
this._def.defaultNow = true;
|
|
236
328
|
return new _ColumnBuilder(this._def.type, this._def);
|
|
237
329
|
}
|
|
330
|
+
/**
|
|
331
|
+
* The DATABASE assigns this column's value — a trigger, a rule, an identity.
|
|
332
|
+
*
|
|
333
|
+
* The column becomes optional on INSERT (the author has nothing to send) while
|
|
334
|
+
* the DDL stays free of a DEFAULT this schema would not honour. It is NOT
|
|
335
|
+
* `default()`: that declares a value the schema promises to write.
|
|
336
|
+
*
|
|
337
|
+
* Naming: deliberately not `generated()`. Postgres has GENERATED columns and
|
|
338
|
+
* they are a different thing; borrowing the word would send a reader — or a
|
|
339
|
+
* model writing a schema — to the wrong feature.
|
|
340
|
+
*/
|
|
341
|
+
dbAssigned() {
|
|
342
|
+
this._def.dbAssigned = true;
|
|
343
|
+
return new _ColumnBuilder(this._def.type, this._def);
|
|
344
|
+
}
|
|
238
345
|
/** Add a foreign key reference. */
|
|
239
346
|
/**
|
|
240
347
|
* Declares that this column used to be called `previous`.
|
|
@@ -369,6 +476,9 @@ var openai = {
|
|
|
369
476
|
...opts?.dimensions !== void 0 ? { dimensions: opts.dimensions } : {},
|
|
370
477
|
...opts?.baseURL !== void 0 ? { baseURL: opts.baseURL } : {}
|
|
371
478
|
};
|
|
479
|
+
},
|
|
480
|
+
chat(model) {
|
|
481
|
+
return { provider: "openai", model };
|
|
372
482
|
}
|
|
373
483
|
};
|
|
374
484
|
|
|
@@ -611,6 +721,19 @@ var TxPlanBuilder = class {
|
|
|
611
721
|
}
|
|
612
722
|
return this.push({ op: "insert", table: name, values: encoded }, `${name}.insert()`);
|
|
613
723
|
},
|
|
724
|
+
upsert: (values, options) => {
|
|
725
|
+
const encoded = encodeMap(values, false);
|
|
726
|
+
if (Object.keys(encoded).length === 0) {
|
|
727
|
+
throw new TxPlanError(`${name}.upsert() needs at least one column`);
|
|
728
|
+
}
|
|
729
|
+
if (options.onConflict.length === 0) {
|
|
730
|
+
throw new TxPlanError(`${name}.upsert() needs at least one onConflict column`);
|
|
731
|
+
}
|
|
732
|
+
return this.push(
|
|
733
|
+
{ op: "upsert", table: name, values: encoded, onConflict: options.onConflict },
|
|
734
|
+
`${name}.upsert()`
|
|
735
|
+
);
|
|
736
|
+
},
|
|
614
737
|
insertMany: (rows) => {
|
|
615
738
|
if (rows.length === 0) {
|
|
616
739
|
return new TxRowsImpl(this, SKIPPED_OP, `${name}.insertMany()`);
|
|
@@ -784,10 +907,11 @@ function translateRejection(err, builder) {
|
|
|
784
907
|
function makeTypedTable(name, raw2) {
|
|
785
908
|
return {
|
|
786
909
|
insert: (data) => raw2.insert(name, data),
|
|
910
|
+
upsert: (data, opts) => raw2.upsert(name, data, opts),
|
|
787
911
|
update: (id, data) => raw2.update(name, id, data),
|
|
788
912
|
delete: (id) => raw2.delete(name, id),
|
|
789
913
|
findById: (id) => raw2.findById(name, id),
|
|
790
|
-
findMany: (query) => raw2.findMany(name, query)
|
|
914
|
+
findMany: (query, opts) => raw2.findMany(name, query, opts)
|
|
791
915
|
};
|
|
792
916
|
}
|
|
793
917
|
function makeTypedDB(schema, raw2) {
|