@palbase/backend 30.0.0 → 32.0.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 +136 -3
- package/dist/bin/palbase-backend.cjs.map +1 -1
- package/dist/bin/palbase-backend.js +7 -7
- package/dist/{chunk-TWX6JTGJ.js → chunk-26GH54D2.js} +3 -5
- package/dist/{chunk-TWX6JTGJ.js.map → chunk-26GH54D2.js.map} +1 -1
- package/dist/{chunk-5J5W75A6.js → chunk-5C5UCILO.js} +27 -325
- package/dist/chunk-5C5UCILO.js.map +1 -0
- package/dist/{chunk-VN7NMDUH.js → chunk-AZJIKCOR.js} +113 -15
- package/dist/chunk-AZJIKCOR.js.map +1 -0
- package/dist/{chunk-VVMJEVQP.js → chunk-BRLJOXWS.js} +2 -2
- package/dist/{chunk-3TUJWHC2.js → chunk-IXAX5CON.js} +378 -19
- package/dist/chunk-IXAX5CON.js.map +1 -0
- package/dist/{chunk-CGNN2PUH.js → chunk-KATPXCJ5.js} +37 -4
- package/dist/{chunk-CGNN2PUH.js.map → chunk-KATPXCJ5.js.map} +1 -1
- package/dist/chunk-KGP6ALIU.js +361 -0
- package/dist/chunk-KGP6ALIU.js.map +1 -0
- package/dist/chunk-XEGZ3S2Q.js +346 -0
- package/dist/chunk-XEGZ3S2Q.js.map +1 -0
- package/dist/{chunk-ENZ2RFFJ.js → chunk-Z4CZRMNF.js} +3 -310
- package/dist/chunk-Z4CZRMNF.js.map +1 -0
- package/dist/db/index.cjs +29 -0
- package/dist/db/index.cjs.map +1 -1
- package/dist/db/index.d.cts +1 -1
- package/dist/db/index.d.ts +1 -1
- package/dist/db/index.js +12 -13
- package/dist/engine/index.cjs +136 -3
- package/dist/engine/index.cjs.map +1 -1
- package/dist/engine/index.d.cts +3 -3
- package/dist/engine/index.d.ts +3 -3
- package/dist/engine/index.js +7 -7
- package/dist/{index-b-Q3l7W5.d.ts → index-BILC9WwS.d.ts} +9 -2
- package/dist/{index-8qy3kIuA.d.ts → index-BgWnP07a.d.ts} +119 -17
- package/dist/{index-Zi7MptvP.d.cts → index-CWGiJ2Up.d.cts} +9 -2
- package/dist/{index-DtCgaZAg.d.cts → index-DgYkdNT9.d.cts} +119 -17
- package/dist/index.cjs +87 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -23
- package/dist/index.d.ts +6 -23
- package/dist/index.js +48 -48
- package/dist/index.js.map +1 -1
- package/dist/openapi/index.d.cts +2 -2
- package/dist/openapi/index.d.ts +2 -2
- package/dist/openapi/index.js +3 -4
- package/dist/openapi/index.js.map +1 -1
- package/dist/{registry-CEYLH-Iz.d.cts → registry-BcRYIQ-R.d.cts} +1 -1
- package/dist/{registry-BGJ-Al6F.d.ts → registry-ClzjxIWy.d.ts} +1 -1
- package/dist/test/index.cjs +703 -14
- package/dist/test/index.cjs.map +1 -1
- package/dist/test/index.d.cts +59 -4
- package/dist/test/index.d.ts +59 -4
- package/dist/test/index.js +51 -13
- package/dist/test/index.js.map +1 -1
- package/docs/README.md +1 -1
- package/docs/database.md +54 -0
- package/docs/llms-full.txt +87 -1
- package/docs/schema.md +32 -0
- package/package.json +1 -1
- package/template/package.json +1 -1
- package/dist/chunk-3TUJWHC2.js.map +0 -1
- package/dist/chunk-5J5W75A6.js.map +0 -1
- package/dist/chunk-ENZ2RFFJ.js.map +0 -1
- package/dist/chunk-SG4UTNOP.js +0 -374
- package/dist/chunk-SG4UTNOP.js.map +0 -1
- package/dist/chunk-VN7NMDUH.js.map +0 -1
- package/dist/chunk-VXPNPVAG.js +0 -40
- package/dist/chunk-VXPNPVAG.js.map +0 -1
- /package/dist/{chunk-VVMJEVQP.js.map → chunk-BRLJOXWS.js.map} +0 -0
package/dist/test/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { T as Token } from '../module-Dl1KFVtc.cjs';
|
|
2
|
-
import { D as DBClient } from '../index-
|
|
2
|
+
import { E as EnvServiceDatabase, D as DBClient, a as RuntimeServices } from '../index-DgYkdNT9.cjs';
|
|
3
3
|
import '../db/env.cjs';
|
|
4
4
|
import '../stack.cjs';
|
|
5
5
|
import 'zod';
|
|
@@ -163,8 +163,26 @@ interface RecordedQuery {
|
|
|
163
163
|
}
|
|
164
164
|
/** What a service-layer test is handed. */
|
|
165
165
|
interface FakeDatabase {
|
|
166
|
-
/** Pass this where the service expects `Database`.
|
|
167
|
-
|
|
166
|
+
/** Pass this where the service expects `Database`.
|
|
167
|
+
*
|
|
168
|
+
* Built with the SAME constructor the production `Database` uses
|
|
169
|
+
* (`makeTypedSurface`), so the fake's surface cannot drift from the real one
|
|
170
|
+
* — including the `$`-prefixed raw ops and the typed `public` schema surface. */
|
|
171
|
+
db: EnvServiceDatabase;
|
|
172
|
+
/**
|
|
173
|
+
* The RAW `DBClient` behind {@link FakeDatabase.db} (FR-028).
|
|
174
|
+
*
|
|
175
|
+
* `RuntimeServices.Database` is the raw client — the ambient `Database`
|
|
176
|
+
* singleton is what WRAPS it with `makeTypedSurface`. So a test that installs
|
|
177
|
+
* the fake as the ambient runtime passes THIS:
|
|
178
|
+
*
|
|
179
|
+
* withServices({ Database: fake.raw }, () => …)
|
|
180
|
+
*
|
|
181
|
+
* Passing `db` there would wrap an already-wrapped surface and every `$op`
|
|
182
|
+
* would miss (measured). Two fields because there are two call sites: `db`
|
|
183
|
+
* goes straight to a service, `raw` goes into the runtime.
|
|
184
|
+
*/
|
|
185
|
+
raw: DBClient;
|
|
168
186
|
/** Every `query()` call, in order. */
|
|
169
187
|
queries: readonly RecordedQuery[];
|
|
170
188
|
/** Put rows in a table before the code under test runs. */
|
|
@@ -178,4 +196,41 @@ interface FakeDatabase {
|
|
|
178
196
|
}
|
|
179
197
|
declare function fakeDatabase(): FakeDatabase;
|
|
180
198
|
|
|
181
|
-
|
|
199
|
+
/**
|
|
200
|
+
* `withServices()` — run code with only the platform services a test supplies.
|
|
201
|
+
*
|
|
202
|
+
* WHY IT IS PUBLIC. `isolated()` substitutes CONSTRUCTOR dependencies, and its
|
|
203
|
+
* own documentation says why it cannot help here: "platform services are
|
|
204
|
+
* ambient rather than injected". So the repository layer — the one place that
|
|
205
|
+
* really does `import { Database } from "@palbase/backend"` — had no supported
|
|
206
|
+
* way to be unit-tested, while `__runWithRuntime` demands EVERY service. A
|
|
207
|
+
* measured consumer project wrote this helper by hand, exploding proxies
|
|
208
|
+
* included, and 30.0.0 then added a tenth required service (`Auth`) which broke
|
|
209
|
+
* that hand-written copy. Shipping it here is what stops that from recurring.
|
|
210
|
+
*
|
|
211
|
+
* WHAT IS ABSENT IS LOUD. An unsupplied service is neither `undefined` nor a
|
|
212
|
+
* silent no-op: touching it throws and NAMES itself, so a test that quietly
|
|
213
|
+
* grew a dependency on `Cache` fails saying "Cache", not "cannot read
|
|
214
|
+
* properties of undefined".
|
|
215
|
+
*
|
|
216
|
+
* SCOPE IS THE REQUEST ALS, never the process-global slot. Two tests in one
|
|
217
|
+
* file must not be able to see each other's services, and a helper that wrote
|
|
218
|
+
* the global slot would leak the first test's fake into the second.
|
|
219
|
+
*
|
|
220
|
+
* EKSİKSİZLİK DERLEYİCİYE SORULUR, BİR LİSTEYE DEĞİL. İlk yazımı servis
|
|
221
|
+
* adlarını bir diziye koyup `satisfies readonly (keyof RuntimeServices)[]` ile
|
|
222
|
+
* pinliyordu — ama `satisfies` yalnız "her ELEMAN bir anahtar mı" diye bakar,
|
|
223
|
+
* "her ANAHTAR listede mi" diye BAKMAZ. Ölçüldü: `RuntimeServices`'a on birinci
|
|
224
|
+
* bir servis eklenip liste dokunulmadan bırakıldığında `tsc --strict` TEMİZ
|
|
225
|
+
* derliyor, ve eksik servise erişen tüketici `TypeError: Reflect.get called on
|
|
226
|
+
* non-object` alıyor — ne servisin adı, ne çaresi. Yani bu dosyanın var olma
|
|
227
|
+
* sebebi olan kusurun ta kendisi, bu dosya tarafından üretiliyordu.
|
|
228
|
+
*
|
|
229
|
+
* Şimdi `filled` düz bir `RuntimeServices` nesne literali: bir alan eksik
|
|
230
|
+
* kalırsa TypeScript `TS2741: Property '<ad>' is missing` diyor ve derleme
|
|
231
|
+
* durur. `as unknown as` yok.
|
|
232
|
+
*/
|
|
233
|
+
|
|
234
|
+
declare function withServices<T>(services: Partial<RuntimeServices>, fn: () => T): T;
|
|
235
|
+
|
|
236
|
+
export { type CallOptions, type ErrorEnvelope, type FakeDatabase, type IsolatedContainer, type RecordedQuery, type RecordedRequest, type TestApi, type TestApiConfig, TestApiError, type TestIdentity, api, createTestApi, fakeDatabase, isolated, withServices };
|
package/dist/test/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { T as Token } from '../module-Dl1KFVtc.js';
|
|
2
|
-
import { D as DBClient } from '../index-
|
|
2
|
+
import { E as EnvServiceDatabase, D as DBClient, a as RuntimeServices } from '../index-BgWnP07a.js';
|
|
3
3
|
import '../db/env.js';
|
|
4
4
|
import '../stack.js';
|
|
5
5
|
import 'zod';
|
|
@@ -163,8 +163,26 @@ interface RecordedQuery {
|
|
|
163
163
|
}
|
|
164
164
|
/** What a service-layer test is handed. */
|
|
165
165
|
interface FakeDatabase {
|
|
166
|
-
/** Pass this where the service expects `Database`.
|
|
167
|
-
|
|
166
|
+
/** Pass this where the service expects `Database`.
|
|
167
|
+
*
|
|
168
|
+
* Built with the SAME constructor the production `Database` uses
|
|
169
|
+
* (`makeTypedSurface`), so the fake's surface cannot drift from the real one
|
|
170
|
+
* — including the `$`-prefixed raw ops and the typed `public` schema surface. */
|
|
171
|
+
db: EnvServiceDatabase;
|
|
172
|
+
/**
|
|
173
|
+
* The RAW `DBClient` behind {@link FakeDatabase.db} (FR-028).
|
|
174
|
+
*
|
|
175
|
+
* `RuntimeServices.Database` is the raw client — the ambient `Database`
|
|
176
|
+
* singleton is what WRAPS it with `makeTypedSurface`. So a test that installs
|
|
177
|
+
* the fake as the ambient runtime passes THIS:
|
|
178
|
+
*
|
|
179
|
+
* withServices({ Database: fake.raw }, () => …)
|
|
180
|
+
*
|
|
181
|
+
* Passing `db` there would wrap an already-wrapped surface and every `$op`
|
|
182
|
+
* would miss (measured). Two fields because there are two call sites: `db`
|
|
183
|
+
* goes straight to a service, `raw` goes into the runtime.
|
|
184
|
+
*/
|
|
185
|
+
raw: DBClient;
|
|
168
186
|
/** Every `query()` call, in order. */
|
|
169
187
|
queries: readonly RecordedQuery[];
|
|
170
188
|
/** Put rows in a table before the code under test runs. */
|
|
@@ -178,4 +196,41 @@ interface FakeDatabase {
|
|
|
178
196
|
}
|
|
179
197
|
declare function fakeDatabase(): FakeDatabase;
|
|
180
198
|
|
|
181
|
-
|
|
199
|
+
/**
|
|
200
|
+
* `withServices()` — run code with only the platform services a test supplies.
|
|
201
|
+
*
|
|
202
|
+
* WHY IT IS PUBLIC. `isolated()` substitutes CONSTRUCTOR dependencies, and its
|
|
203
|
+
* own documentation says why it cannot help here: "platform services are
|
|
204
|
+
* ambient rather than injected". So the repository layer — the one place that
|
|
205
|
+
* really does `import { Database } from "@palbase/backend"` — had no supported
|
|
206
|
+
* way to be unit-tested, while `__runWithRuntime` demands EVERY service. A
|
|
207
|
+
* measured consumer project wrote this helper by hand, exploding proxies
|
|
208
|
+
* included, and 30.0.0 then added a tenth required service (`Auth`) which broke
|
|
209
|
+
* that hand-written copy. Shipping it here is what stops that from recurring.
|
|
210
|
+
*
|
|
211
|
+
* WHAT IS ABSENT IS LOUD. An unsupplied service is neither `undefined` nor a
|
|
212
|
+
* silent no-op: touching it throws and NAMES itself, so a test that quietly
|
|
213
|
+
* grew a dependency on `Cache` fails saying "Cache", not "cannot read
|
|
214
|
+
* properties of undefined".
|
|
215
|
+
*
|
|
216
|
+
* SCOPE IS THE REQUEST ALS, never the process-global slot. Two tests in one
|
|
217
|
+
* file must not be able to see each other's services, and a helper that wrote
|
|
218
|
+
* the global slot would leak the first test's fake into the second.
|
|
219
|
+
*
|
|
220
|
+
* EKSİKSİZLİK DERLEYİCİYE SORULUR, BİR LİSTEYE DEĞİL. İlk yazımı servis
|
|
221
|
+
* adlarını bir diziye koyup `satisfies readonly (keyof RuntimeServices)[]` ile
|
|
222
|
+
* pinliyordu — ama `satisfies` yalnız "her ELEMAN bir anahtar mı" diye bakar,
|
|
223
|
+
* "her ANAHTAR listede mi" diye BAKMAZ. Ölçüldü: `RuntimeServices`'a on birinci
|
|
224
|
+
* bir servis eklenip liste dokunulmadan bırakıldığında `tsc --strict` TEMİZ
|
|
225
|
+
* derliyor, ve eksik servise erişen tüketici `TypeError: Reflect.get called on
|
|
226
|
+
* non-object` alıyor — ne servisin adı, ne çaresi. Yani bu dosyanın var olma
|
|
227
|
+
* sebebi olan kusurun ta kendisi, bu dosya tarafından üretiliyordu.
|
|
228
|
+
*
|
|
229
|
+
* Şimdi `filled` düz bir `RuntimeServices` nesne literali: bir alan eksik
|
|
230
|
+
* kalırsa TypeScript `TS2741: Property '<ad>' is missing` diyor ve derleme
|
|
231
|
+
* durur. `as unknown as` yok.
|
|
232
|
+
*/
|
|
233
|
+
|
|
234
|
+
declare function withServices<T>(services: Partial<RuntimeServices>, fn: () => T): T;
|
|
235
|
+
|
|
236
|
+
export { type CallOptions, type ErrorEnvelope, type FakeDatabase, type IsolatedContainer, type RecordedQuery, type RecordedRequest, type TestApi, type TestApiConfig, TestApiError, type TestIdentity, api, createTestApi, fakeDatabase, isolated, withServices };
|
package/dist/test/index.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__requestALS,
|
|
3
|
+
makeTypedSurface
|
|
4
|
+
} from "../chunk-XEGZ3S2Q.js";
|
|
1
5
|
import {
|
|
2
6
|
assertNoExpressionHandles,
|
|
3
7
|
assertUsableFilter,
|
|
@@ -7,10 +11,10 @@ import {
|
|
|
7
11
|
isColumnExpr,
|
|
8
12
|
isNowExpr,
|
|
9
13
|
isSqlFragment
|
|
10
|
-
} from "../chunk-
|
|
14
|
+
} from "../chunk-IXAX5CON.js";
|
|
11
15
|
import {
|
|
12
16
|
__name
|
|
13
|
-
} from "../chunk-
|
|
17
|
+
} from "../chunk-KATPXCJ5.js";
|
|
14
18
|
|
|
15
19
|
// ../core/dist/index.js
|
|
16
20
|
var CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
@@ -624,7 +628,7 @@ function createMockDB() {
|
|
|
624
628
|
const vals = bucket.map((r) => r[c]).filter((v) => v !== null && v !== void 0);
|
|
625
629
|
(out["avg"] ??= {})[c] = vals.length === 0 ? null : String(Number(vals.reduce((a, v) => addDecimal(a, v, 1), "0")) / vals.length);
|
|
626
630
|
}
|
|
627
|
-
for (const [fn,
|
|
631
|
+
for (const [fn, pick2] of [
|
|
628
632
|
[
|
|
629
633
|
"min",
|
|
630
634
|
-1
|
|
@@ -636,7 +640,7 @@ function createMockDB() {
|
|
|
636
640
|
]) {
|
|
637
641
|
for (const c of q[fn] ?? []) {
|
|
638
642
|
const vals = bucket.map((r) => r[c]).filter((v) => v !== null && v !== void 0);
|
|
639
|
-
(out[fn] ??= {})[c] = vals.length === 0 ? null : vals.reduce((a, v) => cmp(v, a,
|
|
643
|
+
(out[fn] ??= {})[c] = vals.length === 0 ? null : vals.reduce((a, v) => cmp(v, a, pick2 === 1 ? "gt" : "lt") ? v : a);
|
|
640
644
|
}
|
|
641
645
|
}
|
|
642
646
|
if (q.count === true) out["count"] = bucket.length;
|
|
@@ -785,16 +789,12 @@ function createMockDB() {
|
|
|
785
789
|
applied[k] = v;
|
|
786
790
|
}
|
|
787
791
|
assertNoExpressionHandles("update", table, Object.keys(applied), applied);
|
|
788
|
-
|
|
792
|
+
if (idx < 0) return null;
|
|
793
|
+
const updated = {
|
|
789
794
|
...rows[idx],
|
|
790
795
|
...applied
|
|
791
|
-
} : {
|
|
792
|
-
id,
|
|
793
|
-
...applied
|
|
794
796
|
};
|
|
795
|
-
|
|
796
|
-
rows[idx] = updated;
|
|
797
|
-
}
|
|
797
|
+
rows[idx] = updated;
|
|
798
798
|
track(tracked.updated, table, updated);
|
|
799
799
|
return updated;
|
|
800
800
|
},
|
|
@@ -819,6 +819,9 @@ function createMockDB() {
|
|
|
819
819
|
async findMany(table, query, opts) {
|
|
820
820
|
assertUsableFilter("findMany", table, query);
|
|
821
821
|
refuseFragment("findMany", table, query);
|
|
822
|
+
if (opts?.with !== void 0 && Object.keys(opts.with).length > 0) {
|
|
823
|
+
throw new Error(`findMany(${table}): fakeDatabase \`with\` desteklemiyor \u2014 ili\u015Fki grafi\u011Fi yabanc\u0131 anahtarlardan T\xDCRET\u0130L\u0130YOR ve fake \u015Femay\u0131 okumuyor. \u0130li\u015Fkili sat\u0131rlar\u0131 \xF6l\xE7en bir test ger\xE7ek motoru kullanmal\u0131; fake ile \xF6l\xE7mek istiyorsan\u0131z ilgili sat\u0131rlar\u0131 \`seed\` ile ayr\u0131 koyup ayr\u0131 sorgulay\u0131n.`);
|
|
824
|
+
}
|
|
822
825
|
const rows = store.get(table) ?? [];
|
|
823
826
|
let out = query ? rows.filter((row) => rowMatchesFilter("findMany", table, row, query)) : [
|
|
824
827
|
...rows
|
|
@@ -1114,7 +1117,8 @@ function fakeDatabase() {
|
|
|
1114
1117
|
}, "query")
|
|
1115
1118
|
});
|
|
1116
1119
|
return {
|
|
1117
|
-
db,
|
|
1120
|
+
db: makeTypedSurface(db),
|
|
1121
|
+
raw: db,
|
|
1118
1122
|
queries,
|
|
1119
1123
|
seed: /* @__PURE__ */ __name((table, rows) => mock.seed(table, rows), "seed"),
|
|
1120
1124
|
inserted: /* @__PURE__ */ __name((table) => mock.inserted(table), "inserted"),
|
|
@@ -1123,11 +1127,45 @@ function fakeDatabase() {
|
|
|
1123
1127
|
};
|
|
1124
1128
|
}
|
|
1125
1129
|
__name(fakeDatabase, "fakeDatabase");
|
|
1130
|
+
|
|
1131
|
+
// src/test/with-services.ts
|
|
1132
|
+
function absent(name) {
|
|
1133
|
+
return new Proxy({}, {
|
|
1134
|
+
get(_target, prop) {
|
|
1135
|
+
throw new Error(`${String(name)}.${String(prop)} was read, but this test did not provide ${String(name)}. Pass it: withServices({ ${String(name)}: \u2026 }, () => \u2026)`);
|
|
1136
|
+
}
|
|
1137
|
+
});
|
|
1138
|
+
}
|
|
1139
|
+
__name(absent, "absent");
|
|
1140
|
+
function pick(services, key) {
|
|
1141
|
+
return services[key] ?? absent(key);
|
|
1142
|
+
}
|
|
1143
|
+
__name(pick, "pick");
|
|
1144
|
+
function withServices(services, fn) {
|
|
1145
|
+
const filled = {
|
|
1146
|
+
Database: pick(services, "Database"),
|
|
1147
|
+
Auth: pick(services, "Auth"),
|
|
1148
|
+
Secrets: pick(services, "Secrets"),
|
|
1149
|
+
Documents: pick(services, "Documents"),
|
|
1150
|
+
Storage: pick(services, "Storage"),
|
|
1151
|
+
Cache: pick(services, "Cache"),
|
|
1152
|
+
Log: pick(services, "Log"),
|
|
1153
|
+
Notifications: pick(services, "Notifications"),
|
|
1154
|
+
Flags: pick(services, "Flags"),
|
|
1155
|
+
Realtime: pick(services, "Realtime")
|
|
1156
|
+
};
|
|
1157
|
+
return __requestALS.run({
|
|
1158
|
+
runtime: filled,
|
|
1159
|
+
userId: null
|
|
1160
|
+
}, fn);
|
|
1161
|
+
}
|
|
1162
|
+
__name(withServices, "withServices");
|
|
1126
1163
|
export {
|
|
1127
1164
|
TestApiError,
|
|
1128
1165
|
api,
|
|
1129
1166
|
createTestApi,
|
|
1130
1167
|
fakeDatabase,
|
|
1131
|
-
isolated
|
|
1168
|
+
isolated,
|
|
1169
|
+
withServices
|
|
1132
1170
|
};
|
|
1133
1171
|
//# sourceMappingURL=index.js.map
|