@gettersethya/mira-collection 0.1.0-alpha.2 → 0.1.0-alpha.21
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/README.md +173 -0
- package/dist/src/collection/auth.d.ts +4 -34
- package/dist/src/collection/auth.d.ts.map +1 -1
- package/dist/src/collection/auth.js +19 -22
- package/dist/src/collection/auth.js.map +1 -1
- package/dist/src/collection/base.d.ts +7 -31
- package/dist/src/collection/base.d.ts.map +1 -1
- package/dist/src/collection/base.js +12 -15
- package/dist/src/collection/base.js.map +1 -1
- package/dist/src/collection/field.d.ts +35 -1
- package/dist/src/collection/field.d.ts.map +1 -1
- package/dist/src/collection/field.js +26 -1
- package/dist/src/collection/field.js.map +1 -1
- package/dist/src/collection/index.d.ts +5 -1
- package/dist/src/collection/index.d.ts.map +1 -1
- package/dist/src/collection/index.js.map +1 -1
- package/dist/src/collection/infer.d.ts +183 -0
- package/dist/src/collection/infer.d.ts.map +1 -0
- package/dist/src/collection/infer.js +2 -0
- package/dist/src/collection/infer.js.map +1 -0
- package/dist/src/collection/serialize.d.ts +0 -2
- package/dist/src/collection/serialize.d.ts.map +1 -1
- package/dist/src/collection/serialize.js +14 -5
- package/dist/src/collection/serialize.js.map +1 -1
- package/dist/src/collection/types.d.ts +13 -4
- package/dist/src/collection/types.d.ts.map +1 -1
- package/dist/src/collection/view.d.ts +4 -11
- package/dist/src/collection/view.d.ts.map +1 -1
- package/dist/src/collection/view.js +10 -10
- package/dist/src/collection/view.js.map +1 -1
- package/dist/src/filter/builder.d.ts.map +1 -1
- package/dist/src/filter/builder.js.map +1 -1
- package/dist/src/filter/compiler.d.ts +1 -1
- package/dist/src/filter/compiler.d.ts.map +1 -1
- package/dist/src/filter/compiler.js.map +1 -1
- package/dist/src/filter/index.d.ts +2 -2
- package/dist/src/filter/index.d.ts.map +1 -1
- package/dist/src/filter/index.js.map +1 -1
- package/dist/src/filter/types.d.ts +3 -3
- package/dist/src/filter/types.d.ts.map +1 -1
- package/dist/src/filter/types.js +32 -26
- package/dist/src/filter/types.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/rule/builder.d.ts +32 -36
- package/dist/src/rule/builder.d.ts.map +1 -1
- package/dist/src/rule/builder.js +21 -8
- package/dist/src/rule/builder.js.map +1 -1
- package/dist/src/rule/index.d.ts +1 -1
- package/dist/src/rule/index.d.ts.map +1 -1
- package/dist/src/rule/index.js +1 -1
- package/dist/src/rule/index.js.map +1 -1
- package/dist/src/rule/types.d.ts +11 -0
- package/dist/src/rule/types.d.ts.map +1 -1
- package/dist/tests/collection/auth.test.js +5 -5
- package/dist/tests/collection/auth.test.js.map +1 -1
- package/dist/tests/collection/base.test.js +4 -21
- package/dist/tests/collection/base.test.js.map +1 -1
- package/dist/tests/collection/field.test.js +25 -0
- package/dist/tests/collection/field.test.js.map +1 -1
- package/dist/tests/collection/index-type.test.js +1 -1
- package/dist/tests/collection/index-type.test.js.map +1 -1
- package/dist/tests/collection/serialize.test.js +30 -19
- package/dist/tests/collection/serialize.test.js.map +1 -1
- package/dist/tests/collection/view.test.js +1 -1
- package/dist/tests/collection/view.test.js.map +1 -1
- package/dist/tests/filter/compiler.test.js +10 -11
- package/dist/tests/filter/compiler.test.js.map +1 -1
- package/dist/tests/rule/builder.test.js +52 -0
- package/dist/tests/rule/builder.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -4
package/README.md
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# @gettersethya/mira-collection
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@gettersethya/mira-collection)
|
|
4
|
+
|
|
5
|
+
> **Early pre-alpha.** Breaking changes may occur without notice.
|
|
6
|
+
|
|
7
|
+
Collection definitions, filter DSL, and access rule builder for [Mira](https://github.com/gettersethya/mira). Shared between server and client — isomorphic, no runtime dependencies beyond `effect`.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @gettersethya/mira-collection effect
|
|
13
|
+
# or
|
|
14
|
+
pnpm add @gettersethya/mira-collection effect
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Collection types
|
|
18
|
+
|
|
19
|
+
### Base collection
|
|
20
|
+
|
|
21
|
+
Standard CRUD collection. System fields `id`, `seqId`, `created`, and `updated` are added automatically.
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { BaseCollection, Bytes, Field } from "@gettersethya/mira-collection"
|
|
25
|
+
|
|
26
|
+
export const Posts = BaseCollection.define("posts", {
|
|
27
|
+
title: Field.text({ maxLength: 200 }),
|
|
28
|
+
slug: Field.text({ unique: true }),
|
|
29
|
+
content: Field.text(),
|
|
30
|
+
published: Field.boolean({ default: false }),
|
|
31
|
+
authorId: Field.relation(Users),
|
|
32
|
+
thumbnail: Field.file({ maxSize: Bytes.fromMB(5), mimeTypes: ["image/*"] }),
|
|
33
|
+
})
|
|
34
|
+
.indexes((I) => [
|
|
35
|
+
I.on("authorId"),
|
|
36
|
+
I.unique("slug"),
|
|
37
|
+
])
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Auth collection
|
|
41
|
+
|
|
42
|
+
Adds `email`, `password` (hashed with scrypt on create/update), and `emailVerified` system fields. Exposes an `authWithPassword` endpoint.
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import { AuthCollection, Field } from "@gettersethya/mira-collection"
|
|
46
|
+
|
|
47
|
+
export const Users = AuthCollection.define("users", {
|
|
48
|
+
displayName: Field.text(),
|
|
49
|
+
username: Field.text({ unique: true }),
|
|
50
|
+
role: Field.text({ default: "user" }),
|
|
51
|
+
})
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### View collection
|
|
55
|
+
|
|
56
|
+
Read-only, backed by a SQL `VIEW`. Supports `list` and `view` access rules. Every field must be marked `.view()`.
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
import { Field, ViewCollection } from "@gettersethya/mira-collection"
|
|
60
|
+
|
|
61
|
+
export const PostsWithAuthors = ViewCollection.define(
|
|
62
|
+
"posts_with_authors",
|
|
63
|
+
`SELECT p.id, p.seqId, p.title, u.displayName AS authorName
|
|
64
|
+
FROM posts p LEFT JOIN users u ON p.authorId = u.id`,
|
|
65
|
+
{
|
|
66
|
+
id: Field.text().view(),
|
|
67
|
+
seqId: Field.integer().view(),
|
|
68
|
+
title: Field.text().view(),
|
|
69
|
+
authorName: Field.text().view(),
|
|
70
|
+
}
|
|
71
|
+
)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Rules for collections are defined server-side using `defineRule()` from `@gettersethya/mira`.
|
|
75
|
+
|
|
76
|
+
## Type inference
|
|
77
|
+
|
|
78
|
+
The record and input inference types are exported from `@gettersethya/mira-collection`, so no
|
|
79
|
+
server or client package is required to derive TypeScript types from a collection definition.
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
import type { InferRecord, InferCreateInput, InferMutationInput } from "@gettersethya/mira-collection"
|
|
83
|
+
import { Posts } from "./collections.js"
|
|
84
|
+
|
|
85
|
+
type Post = InferRecord<typeof Posts> // full record incl. system fields
|
|
86
|
+
type NewPost = InferCreateInput<typeof Posts> // create input, no system fields
|
|
87
|
+
type Edit = InferMutationInput<typeof Posts> // mutation input; file fields are File | Blob
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Also exported: `RelationKeys`, `FileKeys`, `WithExpand`, `CollectionKind`, `CreateInput`,
|
|
91
|
+
`UpdateInput`, `AuthCreateInput`, `AuthUpdateInput`, `RegisterInput`, and `AnyAuthCollectionDef`.
|
|
92
|
+
|
|
93
|
+
## Field types
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
Field.text({ minLength?, maxLength?, unique?, indexed?, required?, default? })
|
|
97
|
+
Field.literalText({ literal: ["a", "b"], default? })
|
|
98
|
+
Field.email()
|
|
99
|
+
Field.integer({ min?, max?, unique?, indexed?, default? })
|
|
100
|
+
Field.number({ min?, max? })
|
|
101
|
+
Field.boolean({ default? })
|
|
102
|
+
Field.date()
|
|
103
|
+
Field.json()
|
|
104
|
+
Field.file({ maxSize?, mimeTypes?, protected? })
|
|
105
|
+
Field.relation(Collection)
|
|
106
|
+
|
|
107
|
+
// File size helpers
|
|
108
|
+
Bytes.fromKB(n)
|
|
109
|
+
Bytes.fromMB(n)
|
|
110
|
+
Bytes.fromGB(n)
|
|
111
|
+
Bytes.fromTB(n)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Indexes
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
// Field-level (single column)
|
|
118
|
+
Field.text({ unique: true }) // unique index
|
|
119
|
+
Field.text({ indexed: true }) // non-unique index
|
|
120
|
+
|
|
121
|
+
// Callback (composite or explicit)
|
|
122
|
+
.indexes((I) => [
|
|
123
|
+
I.on("authorId"), // non-unique
|
|
124
|
+
I.on("authorId", "published"), // composite
|
|
125
|
+
I.unique("slug"), // unique constraint
|
|
126
|
+
I.unique("teamId", "userId"), // composite unique
|
|
127
|
+
])
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Rules
|
|
131
|
+
|
|
132
|
+
Rules are evaluated server-side on every request. A missing key means **deny all** for that action.
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
Rule.public() // allow all
|
|
136
|
+
R.authId(Users).neq(R.literal("")) // logged-in users only
|
|
137
|
+
R.field("ownerId").eq(R.authId(Users)) // owner-only
|
|
138
|
+
R.field("role").in(R.literal(["admin", "mod"])) // role check
|
|
139
|
+
R.auth(Users, "role").eq(R.literal("admin")) // check a field on the auth record
|
|
140
|
+
Rule.not(R.field("archived").eq(R.literal(true))) // negation
|
|
141
|
+
Rule.or(R.field("isPublic").eq(R.literal(true)), R.field("ownerId").eq(R.authId(Users)))
|
|
142
|
+
Rule.and(R.field("published").eq(R.literal(true)), R.field("ownerId").eq(R.authId(Users)))
|
|
143
|
+
|
|
144
|
+
// Date arithmetic
|
|
145
|
+
R.field("created").gte(Rule.dateAdd(Rule.now(), -30, "day"))
|
|
146
|
+
|
|
147
|
+
// Request values (header, query param, or body field)
|
|
148
|
+
Rule.request("header", "x-api-key").eq(R.literal("secret"))
|
|
149
|
+
|
|
150
|
+
// Subquery membership check
|
|
151
|
+
Rule.subquery(Members, "teamId").where(R.field("userId").eq(R.authId(Users)))
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Filters
|
|
155
|
+
|
|
156
|
+
Used in client queries. Type-checked against the collection's field types.
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
f.field("published").eq(true)
|
|
160
|
+
f.field("viewCount").gte(100)
|
|
161
|
+
f.field("status").in(["draft", "published"])
|
|
162
|
+
f.field("title").like("%effect%")
|
|
163
|
+
f.field("deletedAt").null()
|
|
164
|
+
f.field("price").between(10, 100)
|
|
165
|
+
|
|
166
|
+
f.and(f.field("published").eq(true), f.field("viewCount").gte(100))
|
|
167
|
+
f.or(f.field("category").eq("tech"), f.field("category").eq("science"))
|
|
168
|
+
f.not(f.field("archived").eq(true))
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## More
|
|
172
|
+
|
|
173
|
+
See the [Mira root README](https://github.com/gettersethya/mira) for full documentation.
|
|
@@ -1,46 +1,26 @@
|
|
|
1
|
-
import type { RuleBuilder } from "../rule/builder.js";
|
|
2
|
-
import type { RuleMap } from "../rule/types.js";
|
|
3
|
-
import type { OperandNode } from "../rule/types.js";
|
|
4
1
|
import type { IndexBuilder, IndexEntry } from "./index-builder.js";
|
|
5
2
|
import type { CollectionSchema, FieldDef, FieldsMap } from "./types.js";
|
|
6
3
|
type AuthSystemField = "id" | "email" | "password" | "emailVerified" | "created" | "updated" | "seqId";
|
|
7
4
|
type AuthRuleField = "id" | "email" | "emailVerified" | "created" | "updated" | "seqId";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
kind: "text";
|
|
11
|
-
};
|
|
5
|
+
/** Only the auth-specific fields not already provided by InferRecord's base type. */
|
|
6
|
+
type AuthPublicFieldDefs = {
|
|
12
7
|
email: FieldDef & {
|
|
13
8
|
kind: "email";
|
|
14
9
|
};
|
|
15
10
|
emailVerified: FieldDef & {
|
|
16
11
|
kind: "boolean";
|
|
17
12
|
};
|
|
18
|
-
created: FieldDef & {
|
|
19
|
-
kind: "date";
|
|
20
|
-
};
|
|
21
|
-
updated: FieldDef & {
|
|
22
|
-
kind: "date";
|
|
23
|
-
};
|
|
24
|
-
seqId: FieldDef & {
|
|
25
|
-
kind: "seqId";
|
|
26
|
-
};
|
|
27
|
-
};
|
|
28
|
-
/** Rule builder for auth collections — extends RuleBuilder with `selfId()`. */
|
|
29
|
-
type AuthRuleBuilder<F extends FieldsMap> = RuleBuilder<F> & {
|
|
30
|
-
/** authId operand for this collection. Use instead of `Rule.authId(ThisCollection)` to avoid circular references. */
|
|
31
|
-
selfId(): OperandNode<any, string>;
|
|
32
13
|
};
|
|
33
14
|
type IndexCb<F extends FieldsMap> = (I: IndexBuilder<(keyof F & string) | AuthRuleField>) => Array<IndexEntry<(keyof F & string) | AuthRuleField>>;
|
|
34
|
-
type RuleCb<F extends FieldsMap> = (R: AuthRuleBuilder<F & AuthSystemFieldDefs>) => RuleMap;
|
|
35
15
|
/**
|
|
36
16
|
* Builder returned by `AuthCollection.define()`.
|
|
37
17
|
* Immediately satisfies `AnyCollectionDef` — no terminal `.build()` needed.
|
|
38
|
-
* Chain `.indexes()`
|
|
18
|
+
* Chain `.indexes()` to add optional indexes.
|
|
39
19
|
* Each chained method returns a new builder; the original is unchanged.
|
|
40
20
|
*/
|
|
41
21
|
export type AuthCollectionBuilder<F extends FieldsMap> = {
|
|
42
22
|
name: string;
|
|
43
|
-
fields: F;
|
|
23
|
+
fields: F & AuthPublicFieldDefs;
|
|
44
24
|
schema: CollectionSchema & {
|
|
45
25
|
"x-collection-kind": "auth";
|
|
46
26
|
};
|
|
@@ -50,12 +30,6 @@ export type AuthCollectionBuilder<F extends FieldsMap> = {
|
|
|
50
30
|
* Pass a callback to get a typed index builder with auto-completion over field names.
|
|
51
31
|
*/
|
|
52
32
|
indexes(cb: IndexCb<F>): AuthCollectionBuilder<F>;
|
|
53
|
-
/**
|
|
54
|
-
* Add per-action access rules. No rule means deny all.
|
|
55
|
-
* The rule builder includes `.selfId()` as a shorthand for the authenticated user's id
|
|
56
|
-
* on this collection — use it instead of `Rule.authId(ThisCollection)` to avoid circular references.
|
|
57
|
-
*/
|
|
58
|
-
rules(cb: RuleCb<F>): AuthCollectionBuilder<F>;
|
|
59
33
|
};
|
|
60
34
|
/**
|
|
61
35
|
* Defines an auth collection for user authentication.
|
|
@@ -67,10 +41,6 @@ export type AuthCollectionBuilder<F extends FieldsMap> = {
|
|
|
67
41
|
* name: Field.text(),
|
|
68
42
|
* avatar: Field.file({ maxSize: Bytes.fromMB(2) })
|
|
69
43
|
* })
|
|
70
|
-
* .rules((R) => ({
|
|
71
|
-
* list: R.field("id").eq(R.selfId()),
|
|
72
|
-
* create: R.public()
|
|
73
|
-
* }))
|
|
74
44
|
*/
|
|
75
45
|
export declare const AuthCollection: {
|
|
76
46
|
define<F extends FieldsMap & { [K in keyof F & AuthSystemField]?: never; }>(name: string, extraFields: F): AuthCollectionBuilder<F>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/collection/auth.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/collection/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAGlE,OAAO,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,SAAS,EAAgC,MAAM,YAAY,CAAA;AAErG,KAAK,eAAe,GAAG,IAAI,GAAG,OAAO,GAAG,UAAU,GAAG,eAAe,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAA;AACtG,KAAK,aAAa,GAAG,IAAI,GAAG,OAAO,GAAG,eAAe,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAA;AAEvF,qFAAqF;AACrF,KAAK,mBAAmB,GAAG;IACzB,KAAK,EAAU,QAAQ,GAAG;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,CAAA;IAC3C,aAAa,EAAE,QAAQ,GAAG;QAAE,IAAI,EAAE,SAAS,CAAA;KAAE,CAAA;CAC9C,CAAA;AAED,KAAK,OAAO,CAAC,CAAC,SAAS,SAAS,IAAI,CAClC,CAAC,EAAE,YAAY,CAAC,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,aAAa,CAAC,KAChD,KAAK,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,aAAa,CAAC,CAAC,CAAA;AAE1D;;;;;GAKG;AACH,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,SAAS,IAAI;IACvD,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,CAAC,GAAG,mBAAmB,CAAA;IAC/B,MAAM,EAAE,gBAAgB,GAAG;QAAE,mBAAmB,EAAE,MAAM,CAAA;KAAE,CAAA;IAC1D;;;;OAIG;IACH,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAA;CAClD,CAAA;AAuCD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc;WAClB,CAAC,SAAS,SAAS,GAAG,GAAG,CAAC,IAAI,MAAM,CAAC,GAAG,eAAe,CAAC,CAAC,EAAE,KAAK,GAAE,QACjE,MAAM,eACC,CAAC,GACb,qBAAqB,CAAC,CAAC,CAAC;CAG5B,CAAA"}
|
|
@@ -1,30 +1,31 @@
|
|
|
1
|
-
import { makeRuleBuilder } from "../rule/builder.js";
|
|
2
1
|
import { Index } from "./index-builder.js";
|
|
3
2
|
import { toJSONSchema } from "./serialize.js";
|
|
4
3
|
const AUTH_SYSTEM_PROPERTIES = {
|
|
5
4
|
email: { type: "string", format: "email", "x-system": true },
|
|
6
|
-
password: { type: "string", "x-system": true, "x-hidden": true },
|
|
5
|
+
password: { type: "string", "x-system": true, "x-hidden": true, "x-kind": "password" },
|
|
7
6
|
emailVerified: { type: "boolean", "x-system": true, default: false }
|
|
8
7
|
};
|
|
8
|
+
const AUTH_SYSTEM_FIELD_DEFS = {
|
|
9
|
+
email: { _tag: "FieldDef", kind: "email" },
|
|
10
|
+
emailVerified: { _tag: "FieldDef", kind: "boolean" },
|
|
11
|
+
};
|
|
9
12
|
const AUTH_SYSTEM_INDEXES = [{ fields: ["email"], unique: true }];
|
|
10
|
-
function makeAuthBuilder(name, extraFields, indexesCb
|
|
11
|
-
|
|
12
|
-
const authRuleBuilder = {
|
|
13
|
-
...makeRuleBuilder(),
|
|
14
|
-
selfId() { return { kind: "authId", collection: name }; }
|
|
15
|
-
};
|
|
16
|
-
const rules = rulesCb?.(authRuleBuilder);
|
|
17
|
-
const schema = toJSONSchema("auth", name, extraFields, {
|
|
18
|
-
indexes: [...AUTH_SYSTEM_INDEXES, ...(indexes ?? [])],
|
|
19
|
-
systemFields: AUTH_SYSTEM_PROPERTIES,
|
|
20
|
-
...(rules !== undefined ? { rules } : {})
|
|
21
|
-
});
|
|
13
|
+
function makeAuthBuilder(name, extraFields, indexesCb) {
|
|
14
|
+
let _schema;
|
|
22
15
|
return {
|
|
23
16
|
name,
|
|
24
|
-
fields: extraFields,
|
|
25
|
-
schema
|
|
26
|
-
|
|
27
|
-
|
|
17
|
+
fields: Object.assign({}, AUTH_SYSTEM_FIELD_DEFS, extraFields),
|
|
18
|
+
get schema() {
|
|
19
|
+
if (_schema === undefined) {
|
|
20
|
+
const indexes = indexesCb?.(Index);
|
|
21
|
+
_schema = toJSONSchema("auth", name, extraFields, {
|
|
22
|
+
indexes: [...AUTH_SYSTEM_INDEXES, ...(indexes ?? [])],
|
|
23
|
+
systemFields: AUTH_SYSTEM_PROPERTIES,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
return _schema;
|
|
27
|
+
},
|
|
28
|
+
indexes: (cb) => makeAuthBuilder(name, extraFields, cb)
|
|
28
29
|
};
|
|
29
30
|
}
|
|
30
31
|
/**
|
|
@@ -37,10 +38,6 @@ function makeAuthBuilder(name, extraFields, indexesCb, rulesCb) {
|
|
|
37
38
|
* name: Field.text(),
|
|
38
39
|
* avatar: Field.file({ maxSize: Bytes.fromMB(2) })
|
|
39
40
|
* })
|
|
40
|
-
* .rules((R) => ({
|
|
41
|
-
* list: R.field("id").eq(R.selfId()),
|
|
42
|
-
* create: R.public()
|
|
43
|
-
* }))
|
|
44
41
|
*/
|
|
45
42
|
export const AuthCollection = {
|
|
46
43
|
define(name, extraFields) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/collection/auth.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/collection/auth.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAkC7C,MAAM,sBAAsB,GAAuC;IACjE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE;IAC5D,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE;IACtF,aAAa,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE;CACrE,CAAA;AAED,MAAM,sBAAsB,GAAwB;IAClD,KAAK,EAAU,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE;IAClD,aAAa,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE;CACrD,CAAA;AAED,MAAM,mBAAmB,GAAoB,CAAC,EAAE,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAA;AAElF,SAAS,eAAe,CACtB,IAAY,EACZ,WAAc,EACd,SAAsB;IAGtB,IAAI,OAAyE,CAAA;IAC7E,OAAO;QACL,IAAI;QACJ,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,sBAAsB,EAAE,WAAW,CAAC;QAC9D,IAAI,MAAM;YACR,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC1B,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC,KAAyB,CAAC,CAAA;gBACtD,OAAO,GAAG,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE;oBAChD,OAAO,EAAE,CAAC,GAAG,mBAAmB,EAAE,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;oBACrD,YAAY,EAAE,sBAAsB;iBACrC,CAAuD,CAAA;YAC1D,CAAC;YACD,OAAO,OAAQ,CAAA;QACjB,CAAC;QACD,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,CAAC;KACxD,CAAA;AACH,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,MAAM,CACJ,IAAY,EACZ,WAAc;QAEd,OAAO,eAAe,CAAC,IAAI,EAAE,WAAW,CAAC,CAAA;IAC3C,CAAC;CACF,CAAA"}
|
|
@@ -1,45 +1,25 @@
|
|
|
1
|
-
import type { RuleBuilder } from "../rule/builder.js";
|
|
2
|
-
import type { RuleMap } from "../rule/types.js";
|
|
3
1
|
import type { IndexBuilder, IndexEntry } from "./index-builder.js";
|
|
4
|
-
import type { CollectionSchema,
|
|
2
|
+
import type { CollectionSchema, FieldsMap } from "./types.js";
|
|
5
3
|
type BaseForbiddenField = "id" | "seqId";
|
|
6
4
|
type BaseSystemField = "id" | "seqId" | "created" | "updated";
|
|
7
|
-
type BaseSystemFieldDefs = {
|
|
8
|
-
id: FieldDef & {
|
|
9
|
-
kind: "text";
|
|
10
|
-
};
|
|
11
|
-
created: FieldDef & {
|
|
12
|
-
kind: "date";
|
|
13
|
-
};
|
|
14
|
-
updated: FieldDef & {
|
|
15
|
-
kind: "date";
|
|
16
|
-
};
|
|
17
|
-
seqId: FieldDef & {
|
|
18
|
-
kind: "seqId";
|
|
19
|
-
};
|
|
20
|
-
};
|
|
21
5
|
type IndexCb<F extends FieldsMap> = (I: IndexBuilder<(keyof F & string) | BaseSystemField>) => Array<IndexEntry<(keyof F & string) | BaseSystemField>>;
|
|
22
|
-
type RuleCb<F extends FieldsMap> = (R: RuleBuilder<F & BaseSystemFieldDefs>) => RuleMap;
|
|
23
6
|
/**
|
|
24
7
|
* Builder returned by `BaseCollection.define()`.
|
|
25
8
|
* Immediately satisfies `AnyCollectionDef` — no terminal `.build()` needed.
|
|
26
|
-
* Chain `.indexes()`
|
|
9
|
+
* Chain `.indexes()` to add optional indexes.
|
|
27
10
|
* Each chained method returns a new builder; the original is unchanged.
|
|
28
11
|
*/
|
|
29
12
|
export type BaseCollectionBuilder<F extends FieldsMap> = {
|
|
30
|
-
name: string;
|
|
31
|
-
fields: F;
|
|
32
|
-
schema: CollectionSchema
|
|
13
|
+
readonly name: string;
|
|
14
|
+
readonly fields: F;
|
|
15
|
+
readonly schema: CollectionSchema & {
|
|
16
|
+
"x-collection-kind": "base";
|
|
17
|
+
};
|
|
33
18
|
/**
|
|
34
19
|
* Add collection-level indexes (in addition to field-level `unique`/`indexed` flags).
|
|
35
20
|
* Pass a callback to get a typed index builder with auto-completion over field names.
|
|
36
21
|
*/
|
|
37
22
|
indexes(cb: IndexCb<F>): BaseCollectionBuilder<F>;
|
|
38
|
-
/**
|
|
39
|
-
* Add per-action access rules. No rule means deny all.
|
|
40
|
-
* Pass a callback to get a typed rule builder with auto-completion over field names.
|
|
41
|
-
*/
|
|
42
|
-
rules(cb: RuleCb<F>): BaseCollectionBuilder<F>;
|
|
43
23
|
};
|
|
44
24
|
/**
|
|
45
25
|
* Defines a standard data collection.
|
|
@@ -52,10 +32,6 @@ export type BaseCollectionBuilder<F extends FieldsMap> = {
|
|
|
52
32
|
* ownerId: Field.text()
|
|
53
33
|
* })
|
|
54
34
|
* .indexes((I) => [I.on("ownerId")])
|
|
55
|
-
* .rules((R) => ({
|
|
56
|
-
* list: Rule.public(),
|
|
57
|
-
* view: R.field("ownerId").eq(R.authId(Users))
|
|
58
|
-
* }))
|
|
59
35
|
*/
|
|
60
36
|
export declare const BaseCollection: {
|
|
61
37
|
define<F extends FieldsMap & { [K in keyof F & BaseForbiddenField]?: never; }>(name: string, fields: F): BaseCollectionBuilder<F>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/collection/base.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/collection/base.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAGlE,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAE7D,KAAK,kBAAkB,GAAG,IAAI,GAAG,OAAO,CAAA;AACxC,KAAK,eAAe,GAAG,IAAI,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAA;AAE7D,KAAK,OAAO,CAAC,CAAC,SAAS,SAAS,IAAI,CAClC,CAAC,EAAE,YAAY,CAAC,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,eAAe,CAAC,KAClD,KAAK,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,eAAe,CAAC,CAAC,CAAA;AAE5D;;;;;GAKG;AACH,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,SAAS,IAAI;IACvD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;IAClB,QAAQ,CAAC,MAAM,EAAE,gBAAgB,GAAG;QAAE,mBAAmB,EAAE,MAAM,CAAA;KAAE,CAAA;IACnE;;;OAGG;IACH,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAA;CAClD,CAAA;AAyBD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc;WAClB,CAAC,SAAS,SAAS,GAAG,GAAG,CAAC,IAAI,MAAM,CAAC,GAAG,kBAAkB,CAAC,CAAC,EAAE,KAAK,GAAE,QACpE,MAAM,UACJ,CAAC,GACR,qBAAqB,CAAC,CAAC,CAAC;CAG5B,CAAA"}
|
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
import { makeRuleBuilder } from "../rule/builder.js";
|
|
2
1
|
import { Index } from "./index-builder.js";
|
|
3
2
|
import { toJSONSchema } from "./serialize.js";
|
|
4
|
-
function makeBaseBuilder(name, fields, indexesCb
|
|
5
|
-
|
|
6
|
-
const rules = rulesCb?.(makeRuleBuilder());
|
|
7
|
-
const schema = toJSONSchema("base", name, fields, {
|
|
8
|
-
...(indexes !== undefined ? { indexes } : {}),
|
|
9
|
-
...(rules !== undefined ? { rules } : {})
|
|
10
|
-
});
|
|
3
|
+
function makeBaseBuilder(name, fields, indexesCb) {
|
|
4
|
+
let _schema;
|
|
11
5
|
return {
|
|
12
6
|
name,
|
|
13
7
|
fields,
|
|
14
|
-
schema
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
get schema() {
|
|
9
|
+
if (_schema === undefined) {
|
|
10
|
+
const indexes = indexesCb?.(Index);
|
|
11
|
+
_schema = toJSONSchema("base", name, fields, {
|
|
12
|
+
...(indexes !== undefined ? { indexes } : {})
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
return _schema;
|
|
16
|
+
},
|
|
17
|
+
indexes: (cb) => makeBaseBuilder(name, fields, cb)
|
|
17
18
|
};
|
|
18
19
|
}
|
|
19
20
|
/**
|
|
@@ -27,10 +28,6 @@ function makeBaseBuilder(name, fields, indexesCb, rulesCb) {
|
|
|
27
28
|
* ownerId: Field.text()
|
|
28
29
|
* })
|
|
29
30
|
* .indexes((I) => [I.on("ownerId")])
|
|
30
|
-
* .rules((R) => ({
|
|
31
|
-
* list: Rule.public(),
|
|
32
|
-
* view: R.field("ownerId").eq(R.authId(Users))
|
|
33
|
-
* }))
|
|
34
31
|
*/
|
|
35
32
|
export const BaseCollection = {
|
|
36
33
|
define(name, fields) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/collection/base.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/collection/base.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AA2B7C,SAAS,eAAe,CACtB,IAAY,EACZ,MAAS,EACT,SAAsB;IAGtB,IAAI,OAAyE,CAAA;IAC7E,OAAO;QACL,IAAI;QACJ,MAAM;QACN,IAAI,MAAM;YACR,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC1B,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC,KAAyB,CAAC,CAAA;gBACtD,OAAO,GAAG,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE;oBAC3C,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBAC9C,CAAC,CAAA;YACJ,CAAC;YACD,OAAO,OAAQ,CAAA;QACjB,CAAC;QACD,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC;KACnD,CAAA;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,MAAM,CACJ,IAAY,EACZ,MAAS;QAET,OAAO,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IACtC,CAAC;CACF,CAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AnyCollectionDef, EmailConstraintKind, FieldDef, IntegerConstraintKind, NumberConstraintKind, SimpleConstraintKind, TextConstraintKind } from "./types.js";
|
|
1
|
+
import type { AnyCollectionDef, EmailConstraintKind, FieldDef, IntegerConstraintKind, LiteralTextConstraintKind, NumberConstraintKind, SimpleConstraintKind, TextConstraintKind } from "./types.js";
|
|
2
2
|
/** Common options shared by all field types. */
|
|
3
3
|
type BaseFieldOptions = {
|
|
4
4
|
/** Alternative field name in the database (defaults to the key in the fields map). */
|
|
@@ -61,6 +61,40 @@ export declare const Field: {
|
|
|
61
61
|
viewOnly: true;
|
|
62
62
|
};
|
|
63
63
|
};
|
|
64
|
+
/**
|
|
65
|
+
* A text field restricted to a fixed set of literal string values.
|
|
66
|
+
* Stored as `TEXT` in SQLite. The server rejects values not in the
|
|
67
|
+
* `literal` array on create and update operations.
|
|
68
|
+
*
|
|
69
|
+
* The TypeScript type narrows to the literal union for type-safe
|
|
70
|
+
* filter expressions and client SDK usage.
|
|
71
|
+
*
|
|
72
|
+
* @param opts.literal - Required: the allowed string values (automatically narrowed via `const` type parameter)
|
|
73
|
+
* @param opts.error - Callback for custom validation error messages
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* Field.literalText({ literal: ["admin", "agent", "readonly"] })
|
|
77
|
+
* Field.literalText({ literal: ["draft", "published"], default: "draft" })
|
|
78
|
+
*/
|
|
79
|
+
literalText: <const L extends ReadonlyArray<string>, O extends Omit<BaseFieldOptions, "default"> & {
|
|
80
|
+
default?: L[number];
|
|
81
|
+
}>(opts: {
|
|
82
|
+
literal: L;
|
|
83
|
+
} & O & {
|
|
84
|
+
error?: (kind: LiteralTextConstraintKind) => string | undefined;
|
|
85
|
+
}) => FieldDef & {
|
|
86
|
+
kind: "literalText";
|
|
87
|
+
literal: L;
|
|
88
|
+
_literal: L;
|
|
89
|
+
} & O & {
|
|
90
|
+
view(): FieldDef & {
|
|
91
|
+
kind: "literalText";
|
|
92
|
+
literal: L;
|
|
93
|
+
_literal: L;
|
|
94
|
+
} & O & {
|
|
95
|
+
viewOnly: true;
|
|
96
|
+
};
|
|
97
|
+
};
|
|
64
98
|
/**
|
|
65
99
|
* A floating-point number field with optional min/max constraints.
|
|
66
100
|
* Stored as `REAL` in SQLite.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field.d.ts","sourceRoot":"","sources":["../../../src/collection/field.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,mBAAmB,EACnB,QAAQ,EAER,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EACnB,MAAM,YAAY,CAAA;AAEnB,gDAAgD;AAChD,KAAK,gBAAgB,GAAG;IACtB,sFAAsF;IACtF,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,gDAAgD;IAChD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,0DAA0D;IAC1D,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAqBD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,KAAK;IAChB;;;;;;;;;;;;;;;;;OAiBG;WACI,CAAC,SAAS,gBAAgB,GAAG;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,SACrE,CAAC,GAAG;QAAE,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,MAAM,GAAG,SAAS,CAAA;KAAE;;;gBAAlD,CAAC,IAAI,EAAE,kBAAkB,KAAK,MAAM,GAAG,SAAS;;;;;oBAAhD,CAAC,IAAI,EAAE,kBAAkB,KAAK,MAAM,GAAG,SAAS;;sBArCU,IAAI;;;IAwCrF;;;;;;;;;;OAUG;aACM,CAAC,SAAS,gBAAgB,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,SAC3D,CAAC,GAAG;QAAE,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,MAAM,GAAG,SAAS,CAAA;KAAE;;;gBAApD,CAAC,IAAI,EAAE,oBAAoB,KAAK,MAAM,GAAG,SAAS;;;;;oBAAlD,CAAC,IAAI,EAAE,oBAAoB,KAAK,MAAM,GAAG,SAAS;;
|
|
1
|
+
{"version":3,"file":"field.d.ts","sourceRoot":"","sources":["../../../src/collection/field.ts"],"names":[],"mappings":"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"}
|
|
@@ -44,6 +44,32 @@ export const Field = {
|
|
|
44
44
|
* Field.text({ minLength: 3, maxLength: 100, default: "untitled" })
|
|
45
45
|
*/
|
|
46
46
|
text: (opts) => makeField("text", opts),
|
|
47
|
+
/**
|
|
48
|
+
* A text field restricted to a fixed set of literal string values.
|
|
49
|
+
* Stored as `TEXT` in SQLite. The server rejects values not in the
|
|
50
|
+
* `literal` array on create and update operations.
|
|
51
|
+
*
|
|
52
|
+
* The TypeScript type narrows to the literal union for type-safe
|
|
53
|
+
* filter expressions and client SDK usage.
|
|
54
|
+
*
|
|
55
|
+
* @param opts.literal - Required: the allowed string values (automatically narrowed via `const` type parameter)
|
|
56
|
+
* @param opts.error - Callback for custom validation error messages
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* Field.literalText({ literal: ["admin", "agent", "readonly"] })
|
|
60
|
+
* Field.literalText({ literal: ["draft", "published"], default: "draft" })
|
|
61
|
+
*/
|
|
62
|
+
literalText: (opts) => {
|
|
63
|
+
const { literal, ...rest } = opts;
|
|
64
|
+
const def = {
|
|
65
|
+
_tag: "FieldDef",
|
|
66
|
+
kind: "literalText",
|
|
67
|
+
literal,
|
|
68
|
+
_literal: literal,
|
|
69
|
+
...rest
|
|
70
|
+
};
|
|
71
|
+
return withView(def);
|
|
72
|
+
},
|
|
47
73
|
/**
|
|
48
74
|
* A floating-point number field with optional min/max constraints.
|
|
49
75
|
* Stored as `REAL` in SQLite.
|
|
@@ -166,7 +192,6 @@ export const Field = {
|
|
|
166
192
|
kind: "relation",
|
|
167
193
|
targetCollection: collection.name,
|
|
168
194
|
targetField,
|
|
169
|
-
_target: collection,
|
|
170
195
|
...fieldOpts
|
|
171
196
|
};
|
|
172
197
|
return withView(def);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field.js","sourceRoot":"","sources":["../../../src/collection/field.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"field.js","sourceRoot":"","sources":["../../../src/collection/field.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,12 +11,16 @@
|
|
|
11
11
|
* - `Index.*()` — index builders
|
|
12
12
|
* - `Bytes.*` — human-readable byte size constants
|
|
13
13
|
*/
|
|
14
|
+
export type { AuthCollectionBuilder } from "./auth.js";
|
|
14
15
|
export { AuthCollection } from "./auth.js";
|
|
16
|
+
export type { BaseCollectionBuilder } from "./base.js";
|
|
15
17
|
export { BaseCollection } from "./base.js";
|
|
16
18
|
export { Bytes } from "./bytes.js";
|
|
17
19
|
export { ValidationError } from "./errors.js";
|
|
18
20
|
export { Field } from "./field.js";
|
|
19
21
|
export { Index } from "./index-builder.js";
|
|
20
|
-
export type {
|
|
22
|
+
export type { AnyAuthCollectionDef, AuthCreateExtras, AuthCreateInput, AuthUpdateCreds, AuthUpdateInput, CollectionKind, CreateInput, FileKeys, InferCreateInput, InferMutationInput, InferRecord, RegisterInput, RelationKeys, UpdateInput, WithExpand } from "./infer.js";
|
|
23
|
+
export type { AnyCollectionDef, CollectionSchema, FieldDef, FieldsMap, LiteralTextConstraintKind } from "./types.js";
|
|
24
|
+
export type { ViewCollectionBuilder } from "./view.js";
|
|
21
25
|
export { ViewCollection } from "./view.js";
|
|
22
26
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/collection/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAC1C,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/collection/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,YAAY,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAA;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAC1C,YAAY,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAA;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAC1C,YAAY,EACV,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,eAAe,EACf,cAAc,EACd,WAAW,EACX,QAAQ,EACR,gBAAgB,EAChB,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,YAAY,EACZ,WAAW,EACX,UAAU,EACX,MAAM,YAAY,CAAA;AACnB,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,QAAQ,EAAE,SAAS,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAA;AACpH,YAAY,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAA;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/collection/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/collection/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAE1C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAoB1C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA"}
|