@gemmein/sdk 0.2.0 → 0.2.1
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/REFERENCE.md +10 -1
- package/dist/index.cjs +16 -5
- package/dist/index.d.cts +16 -3
- package/dist/index.d.ts +16 -3
- package/dist/index.js +16 -5
- package/llms.txt +25 -13
- package/package.json +1 -1
package/REFERENCE.md
CHANGED
|
@@ -72,12 +72,18 @@ deleted, subscription row removed. Irreversible: put a real confirm in front.
|
|
|
72
72
|
|
|
73
73
|
---
|
|
74
74
|
|
|
75
|
-
## Data — `g.collection<T>(name)`
|
|
75
|
+
## Data — `g.collection<T>(name, options?)`
|
|
76
76
|
|
|
77
77
|
`name` must be **lowercase letters, numbers, and underscores** (`saved_games`,
|
|
78
78
|
never `savedGames` — a bad name throws synchronously). Collections are created
|
|
79
79
|
by the app owner in the dashboard, never by the SDK.
|
|
80
80
|
|
|
81
|
+
`options.intent` — one sentence: what the collection is for and who should
|
|
82
|
+
access it. It rides every call as a hint; against a **local `gemmein dev`
|
|
83
|
+
runtime** an undeclared collection then reaches the human with your
|
|
84
|
+
suggestion attached. The cloud ignores it. Pass it whenever you aren't
|
|
85
|
+
certain the collection exists yet.
|
|
86
|
+
|
|
81
87
|
| Method | Signature | Returns |
|
|
82
88
|
|--------|-----------|---------|
|
|
83
89
|
| `create` | `(data: T, options?: { key?: string; for?: string; published?: boolean })` | `Promise<GemmeinRecord<T>>` |
|
|
@@ -260,5 +266,8 @@ Branch on `err.code`. The stable codes:
|
|
|
260
266
|
| `unsupported_file_type` (415) | upload isn't one of the allowed image types | send JPEG/PNG/WebP/GIF/HEIC |
|
|
261
267
|
| `invalid_key` | a keyed create's `key` breaks the charset/length law | 1-120 chars of letters, numbers, `: _ . @ / -` |
|
|
262
268
|
| `invalid_secret_key` (client-side) | `gemmeinServer()` got a missing/`pk_` key | pass the `sk_` key from a server env var |
|
|
269
|
+
| `authentication_required` (401) | checkout/subscription/pay without a signed-in user | sign the user in first |
|
|
270
|
+
| `plan_has_no_link` (409) | the paid plan has no Payment Link pasted yet | ask the owner to paste it in their dashboard |
|
|
271
|
+
| `account_suspended` (403) | the app owner's account is suspended (billing) | the owner fixes payment at app.gemmein.com |
|
|
263
272
|
|
|
264
273
|
Keys: `pk_` (public, domain-locked, browser-safe) vs `sk_` (secret, server only).
|
package/dist/index.cjs
CHANGED
|
@@ -112,9 +112,15 @@ class Gemmein {
|
|
|
112
112
|
/**
|
|
113
113
|
* Your app's data — `g.collection<{ title: string }>("notes")`. The
|
|
114
114
|
* canonical spelling; `g.storage.collection(name)` is the same client.
|
|
115
|
+
*
|
|
116
|
+
* `intent` (one sentence: what this collection is for and who should
|
|
117
|
+
* access it) travels with every call. Against a LOCAL gemmein dev
|
|
118
|
+
* runtime, an undeclared collection then reaches the human with your
|
|
119
|
+
* suggestion attached — always pass it when you aren't certain the
|
|
120
|
+
* collection exists yet. The cloud ignores it.
|
|
115
121
|
*/
|
|
116
|
-
collection(name) {
|
|
117
|
-
return this.storage.collection(name);
|
|
122
|
+
collection(name, options = {}) {
|
|
123
|
+
return this.storage.collection(name, options);
|
|
118
124
|
}
|
|
119
125
|
}
|
|
120
126
|
exports.Gemmein = Gemmein;
|
|
@@ -286,9 +292,9 @@ class StorageClient {
|
|
|
286
292
|
this.config = config;
|
|
287
293
|
}
|
|
288
294
|
/** Optionally type your fields: `g.storage.collection<{ title: string }>("notes")`. */
|
|
289
|
-
collection(name) {
|
|
295
|
+
collection(name, options = {}) {
|
|
290
296
|
assertCollectionName(name);
|
|
291
|
-
return new CollectionClient(this.config, name);
|
|
297
|
+
return new CollectionClient(this.config, name, options);
|
|
292
298
|
}
|
|
293
299
|
}
|
|
294
300
|
exports.StorageClient = StorageClient;
|
|
@@ -299,9 +305,10 @@ exports.StorageClient = StorageClient;
|
|
|
299
305
|
* it there, don't retry.
|
|
300
306
|
*/
|
|
301
307
|
class CollectionClient {
|
|
302
|
-
constructor(config, name) {
|
|
308
|
+
constructor(config, name, options = {}) {
|
|
303
309
|
this.config = config;
|
|
304
310
|
this.name = name;
|
|
311
|
+
this.intent = options.intent;
|
|
305
312
|
}
|
|
306
313
|
/**
|
|
307
314
|
* Create a record from your fields. The signed-in user becomes its owner.
|
|
@@ -433,6 +440,10 @@ class CollectionClient {
|
|
|
433
440
|
...init,
|
|
434
441
|
headers: await runtimeHeaders(this.config, {
|
|
435
442
|
"content-type": "application/json",
|
|
443
|
+
// The intent rides every call so an undeclared collection reaches
|
|
444
|
+
// the human WITH the AI's suggestion attached (local runtime only;
|
|
445
|
+
// the cloud ignores it).
|
|
446
|
+
...(this.intent ? { "x-collection-intent": this.intent.slice(0, 200) } : {}),
|
|
436
447
|
...init.headers
|
|
437
448
|
})
|
|
438
449
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -148,8 +148,16 @@ export declare class Gemmein {
|
|
|
148
148
|
/**
|
|
149
149
|
* Your app's data — `g.collection<{ title: string }>("notes")`. The
|
|
150
150
|
* canonical spelling; `g.storage.collection(name)` is the same client.
|
|
151
|
+
*
|
|
152
|
+
* `intent` (one sentence: what this collection is for and who should
|
|
153
|
+
* access it) travels with every call. Against a LOCAL gemmein dev
|
|
154
|
+
* runtime, an undeclared collection then reaches the human with your
|
|
155
|
+
* suggestion attached — always pass it when you aren't certain the
|
|
156
|
+
* collection exists yet. The cloud ignores it.
|
|
151
157
|
*/
|
|
152
|
-
collection<T extends Record<string, unknown> = Record<string, unknown>>(name: string
|
|
158
|
+
collection<T extends Record<string, unknown> = Record<string, unknown>>(name: string, options?: {
|
|
159
|
+
intent?: string;
|
|
160
|
+
}): CollectionClient<T>;
|
|
153
161
|
}
|
|
154
162
|
export declare function gemmein(appKeyOrOptions: string | GemmeinOptions, options?: Omit<GemmeinOptions, "appKey">): Gemmein;
|
|
155
163
|
export declare function gemmeinServer(secretKeyOrOptions: string | GemmeinServerOptions, options?: Omit<GemmeinServerOptions, "secretKey">): GemmeinServer;
|
|
@@ -245,7 +253,9 @@ export declare class StorageClient {
|
|
|
245
253
|
private readonly config;
|
|
246
254
|
constructor(config: ClientConfig);
|
|
247
255
|
/** Optionally type your fields: `g.storage.collection<{ title: string }>("notes")`. */
|
|
248
|
-
collection<T extends Record<string, unknown> = Record<string, unknown>>(name: string
|
|
256
|
+
collection<T extends Record<string, unknown> = Record<string, unknown>>(name: string, options?: {
|
|
257
|
+
intent?: string;
|
|
258
|
+
}): CollectionClient<T>;
|
|
249
259
|
}
|
|
250
260
|
/**
|
|
251
261
|
* Talks to one collection. Collections themselves are created by the app
|
|
@@ -256,7 +266,10 @@ export declare class StorageClient {
|
|
|
256
266
|
export declare class CollectionClient<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
257
267
|
private readonly config;
|
|
258
268
|
private readonly name;
|
|
259
|
-
|
|
269
|
+
private readonly intent?;
|
|
270
|
+
constructor(config: ClientConfig, name: string, options?: {
|
|
271
|
+
intent?: string;
|
|
272
|
+
});
|
|
260
273
|
/**
|
|
261
274
|
* Create a record from your fields. The signed-in user becomes its owner.
|
|
262
275
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -148,8 +148,16 @@ export declare class Gemmein {
|
|
|
148
148
|
/**
|
|
149
149
|
* Your app's data — `g.collection<{ title: string }>("notes")`. The
|
|
150
150
|
* canonical spelling; `g.storage.collection(name)` is the same client.
|
|
151
|
+
*
|
|
152
|
+
* `intent` (one sentence: what this collection is for and who should
|
|
153
|
+
* access it) travels with every call. Against a LOCAL gemmein dev
|
|
154
|
+
* runtime, an undeclared collection then reaches the human with your
|
|
155
|
+
* suggestion attached — always pass it when you aren't certain the
|
|
156
|
+
* collection exists yet. The cloud ignores it.
|
|
151
157
|
*/
|
|
152
|
-
collection<T extends Record<string, unknown> = Record<string, unknown>>(name: string
|
|
158
|
+
collection<T extends Record<string, unknown> = Record<string, unknown>>(name: string, options?: {
|
|
159
|
+
intent?: string;
|
|
160
|
+
}): CollectionClient<T>;
|
|
153
161
|
}
|
|
154
162
|
export declare function gemmein(appKeyOrOptions: string | GemmeinOptions, options?: Omit<GemmeinOptions, "appKey">): Gemmein;
|
|
155
163
|
export declare function gemmeinServer(secretKeyOrOptions: string | GemmeinServerOptions, options?: Omit<GemmeinServerOptions, "secretKey">): GemmeinServer;
|
|
@@ -245,7 +253,9 @@ export declare class StorageClient {
|
|
|
245
253
|
private readonly config;
|
|
246
254
|
constructor(config: ClientConfig);
|
|
247
255
|
/** Optionally type your fields: `g.storage.collection<{ title: string }>("notes")`. */
|
|
248
|
-
collection<T extends Record<string, unknown> = Record<string, unknown>>(name: string
|
|
256
|
+
collection<T extends Record<string, unknown> = Record<string, unknown>>(name: string, options?: {
|
|
257
|
+
intent?: string;
|
|
258
|
+
}): CollectionClient<T>;
|
|
249
259
|
}
|
|
250
260
|
/**
|
|
251
261
|
* Talks to one collection. Collections themselves are created by the app
|
|
@@ -256,7 +266,10 @@ export declare class StorageClient {
|
|
|
256
266
|
export declare class CollectionClient<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
257
267
|
private readonly config;
|
|
258
268
|
private readonly name;
|
|
259
|
-
|
|
269
|
+
private readonly intent?;
|
|
270
|
+
constructor(config: ClientConfig, name: string, options?: {
|
|
271
|
+
intent?: string;
|
|
272
|
+
});
|
|
260
273
|
/**
|
|
261
274
|
* Create a record from your fields. The signed-in user becomes its owner.
|
|
262
275
|
*
|
package/dist/index.js
CHANGED
|
@@ -104,9 +104,15 @@ export class Gemmein {
|
|
|
104
104
|
/**
|
|
105
105
|
* Your app's data — `g.collection<{ title: string }>("notes")`. The
|
|
106
106
|
* canonical spelling; `g.storage.collection(name)` is the same client.
|
|
107
|
+
*
|
|
108
|
+
* `intent` (one sentence: what this collection is for and who should
|
|
109
|
+
* access it) travels with every call. Against a LOCAL gemmein dev
|
|
110
|
+
* runtime, an undeclared collection then reaches the human with your
|
|
111
|
+
* suggestion attached — always pass it when you aren't certain the
|
|
112
|
+
* collection exists yet. The cloud ignores it.
|
|
107
113
|
*/
|
|
108
|
-
collection(name) {
|
|
109
|
-
return this.storage.collection(name);
|
|
114
|
+
collection(name, options = {}) {
|
|
115
|
+
return this.storage.collection(name, options);
|
|
110
116
|
}
|
|
111
117
|
}
|
|
112
118
|
// Factory forms — what the copied prompts teach. `gemmein("pk_...")` reads
|
|
@@ -273,9 +279,9 @@ export class StorageClient {
|
|
|
273
279
|
this.config = config;
|
|
274
280
|
}
|
|
275
281
|
/** Optionally type your fields: `g.storage.collection<{ title: string }>("notes")`. */
|
|
276
|
-
collection(name) {
|
|
282
|
+
collection(name, options = {}) {
|
|
277
283
|
assertCollectionName(name);
|
|
278
|
-
return new CollectionClient(this.config, name);
|
|
284
|
+
return new CollectionClient(this.config, name, options);
|
|
279
285
|
}
|
|
280
286
|
}
|
|
281
287
|
/**
|
|
@@ -285,9 +291,10 @@ export class StorageClient {
|
|
|
285
291
|
* it there, don't retry.
|
|
286
292
|
*/
|
|
287
293
|
export class CollectionClient {
|
|
288
|
-
constructor(config, name) {
|
|
294
|
+
constructor(config, name, options = {}) {
|
|
289
295
|
this.config = config;
|
|
290
296
|
this.name = name;
|
|
297
|
+
this.intent = options.intent;
|
|
291
298
|
}
|
|
292
299
|
/**
|
|
293
300
|
* Create a record from your fields. The signed-in user becomes its owner.
|
|
@@ -419,6 +426,10 @@ export class CollectionClient {
|
|
|
419
426
|
...init,
|
|
420
427
|
headers: await runtimeHeaders(this.config, {
|
|
421
428
|
"content-type": "application/json",
|
|
429
|
+
// The intent rides every call so an undeclared collection reaches
|
|
430
|
+
// the human WITH the AI's suggestion attached (local runtime only;
|
|
431
|
+
// the cloud ignores it).
|
|
432
|
+
...(this.intent ? { "x-collection-intent": this.intent.slice(0, 200) } : {}),
|
|
422
433
|
...init.headers
|
|
423
434
|
})
|
|
424
435
|
});
|
package/llms.txt
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
> structured data storage with plain-English safety rules, and built-in Stripe
|
|
5
5
|
> subscription handling. Security is on by default for every app — tenant
|
|
6
6
|
> isolation, rate limiting, audit logs, domain-locked keys — with nothing to
|
|
7
|
-
> configure. Free while building;
|
|
8
|
-
> 1,000
|
|
7
|
+
> configure. Free while building; going live starts the Live state at
|
|
8
|
+
> $50/mo (up to 1,000 people); Growing unlocks 10,000 at $150/mo.
|
|
9
9
|
|
|
10
10
|
## What it is
|
|
11
11
|
|
|
@@ -30,9 +30,13 @@
|
|
|
30
30
|
- Data: records live in collections. Collections are created by YOUR HUMAN in
|
|
31
31
|
their dashboard (app.gemmein.com → data → "+ New collection"), never by you
|
|
32
32
|
or the SDK. Best practice: at planning time, list the collections your app
|
|
33
|
-
will need and ask your human up front
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
will need and ask your human up front, and pass your intent whenever a
|
|
34
|
+
collection might not exist yet —
|
|
35
|
+
`g.collection("bookings", { intent: "students reserve slots; each sees only their own" })`
|
|
36
|
+
— so the missing-collection conversation reaches your human with your
|
|
37
|
+
suggestion attached (local dev runtimes show it; the cloud ignores it).
|
|
38
|
+
If one is missing at runtime (404 `unknown_collection`), stop and ask
|
|
39
|
+
them to create it, telling them the name and which safety rule to pick. Each collection has exactly one
|
|
36
40
|
safety rule:
|
|
37
41
|
- `private` — each signed-in user sees and edits only their own records
|
|
38
42
|
(right for notes, tasks, anything personal).
|
|
@@ -184,7 +188,7 @@
|
|
|
184
188
|
back — redirects can be faked, receipts come from Stripe's signed
|
|
185
189
|
webhook. Receipts carry
|
|
186
190
|
{ product, item?, status: "paid"|"refunded", amountTotal (minor units,
|
|
187
|
-
as Stripe said), currency, paidAt, deliveryUrl
|
|
191
|
+
as Stripe said), currency, paidAt, deliveryUrl?, paymentRef } — deliveryUrl appears
|
|
188
192
|
when the builder attached a delivery link to the product (that's how
|
|
189
193
|
digital goods deliver themselves; never put a secret download URL in a
|
|
190
194
|
public collection). Fulfilment status changes ("shipped") are the owner
|
|
@@ -287,14 +291,22 @@ enforces — never because these checks are the enforcement. A ready-to-edit
|
|
|
287
291
|
`reaffirm.mjs` ships inside this npm package (next to this file and
|
|
288
292
|
REFERENCE.md) — copy it out, name your collections, run it in CI.
|
|
289
293
|
|
|
290
|
-
## Pricing (current,
|
|
294
|
+
## Pricing (current, Pricing Model v1 — states, not plans)
|
|
291
295
|
|
|
292
|
-
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
296
|
+
- Development is free indefinitely — no card at signup, unlimited
|
|
297
|
+
collections, the full security model included.
|
|
298
|
+
- Going live starts the Live state: $50/mo, up to 1,000 people and 10 GB
|
|
299
|
+
of file storage (a person = a unique enabled end-user identity on the
|
|
300
|
+
live app).
|
|
301
|
+
- Growing: $150/mo, up to 10,000 people and 50 GB — unlocked from the
|
|
302
|
+
dashboard when the product outgrows Live; down as easily as up.
|
|
303
|
+
- Beyond 10,000 people: talk to Gemmein (hello@gemmein.com) — scale is
|
|
304
|
+
priced as a relationship, not a checkout.
|
|
305
|
+
- Pricing reflects responsibility, not complexity: almost nothing is
|
|
306
|
+
metered. Safe limits exist purely as safety rails against runaway
|
|
307
|
+
scripts, are never billed, and real users never notice them. Hitting a
|
|
308
|
+
limit never breaks the app outright — there is grace, and the owner is
|
|
309
|
+
told.
|
|
298
310
|
|
|
299
311
|
## Facts for citation
|
|
300
312
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gemmein/sdk",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Gemmein SDK \u2014 passwordless auth, safe storage, and Stripe-driven record flips for AI-built apps. Small enough that one prompt teaches the whole API.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|