@fias/arche-sdk 2.11.0 → 2.12.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.
@@ -179,7 +179,9 @@ import { useFiasDataStore } from '@fias/arche-sdk';
179
179
  function MyComponent() {
180
180
  const dataStore = useFiasDataStore();
181
181
 
182
- // Collection management
182
+ // Collection management. PREFER declaring collections in fias-plugin.json
183
+ // (see "Declaring your collections" below) — createCollection is capped at
184
+ // 10/minute, so scaffolding several at startup can silently lose the tail.
183
185
  await dataStore.createCollection('scores', { userScope: 'user' }); // or 'shared'
184
186
  const collections = await dataStore.listCollections();
185
187
  await dataStore.deleteCollection('scores');
@@ -236,6 +238,24 @@ await dataStore.batch([
236
238
  ]);
237
239
  ```
238
240
 
241
+ ### Declaring your collections (preferred)
242
+
243
+ List the collections your plugin needs in `fias-plugin.json` and the platform creates them once at publish, before your plugin ever runs:
244
+
245
+ ```jsonc
246
+ "collections": [
247
+ { "name": "scores", "scope": "user" },
248
+ { "name": "ledger", "scope": "workspace", "readMinRole": "member" },
249
+ { "name": "recipes", "scope": "shared", "writePolicy": "author", "searchable": { "field": "text" } }
250
+ ]
251
+ ```
252
+
253
+ `scope` is `user` | `shared` | `workspace`. `readMinRole` / `writeMinRole` are workspace-only; `writePolicy` is shared-only; `searchable` names the text field to embed. Same options as `createCollection`, checked by `fias-dev validate` before you publish.
254
+
255
+ Why this and not `createCollection` at startup: the runtime op is capped at **10 per minute** while an arche may hold **50** collections, so a plugin creating several on mount can exceed the cap and lose the rest **with no error** — surfacing later as `COLLECTION_NOT_FOUND` on an unrelated call. Declaring has no such window, and a mistake fails your publish instead of a user's session.
256
+
257
+ Re-publishing is safe: existing collections are left alone, a stricter role floor is applied, a looser one is refused, and a collection you stop declaring is kept (never deleted — it may hold user data). Keep using `createCollection` for collections whose names you only know at runtime.
258
+
239
259
  **Rate limits (per minute):** `put` 120, `get` 300, `query` 60, `delete` 60, `batch` 30, `createCollection` 10
240
260
 
241
261
  **Error handling:** Data store calls can reject on infrastructure errors or limit violations. Always use `try/catch`. Common error codes: `COLLECTION_NOT_FOUND`, `DOCUMENT_TOO_LARGE`, `STORAGE_LIMIT_REACHED`, `RATE_LIMIT`.
@@ -756,6 +776,40 @@ const fresh = await getUrl(assetId);
756
776
 
757
777
  Cache the `assetId`; refresh `signedUrl` via `getUrl()` rather than persisting URLs across sessions.
758
778
 
779
+ ### `useCommunityAssets()` — User-published images, visible to this arche's users
780
+
781
+ **Permissions:** `assets:community:read` (browse/view) · `assets:community:publish` (publish/unpublish/listMine)
782
+ **Returns:** `CommunityAssetsApi`
783
+
784
+ The only way one user's content reaches another user. A user publishes an image **they created here**, and after moderation every authenticated user of **this arche** (and no other) can see it. Free to publish.
785
+
786
+ ```tsx
787
+ import { useCommunityAssets, useImageGeneration } from '@fias/arche-sdk';
788
+
789
+ const { publish, publishMany, listCommunity, listMine, getUrls, unpublish } = useCommunityAssets();
790
+ const { generate } = useImageGeneration();
791
+
792
+ // 1. The user makes something, then shares it
793
+ const image = await generate({ prompt: 'a sleepy blue whale' });
794
+ const asset = await publish({ fileId: image.fileId, title: 'Sleepy whale', tags: ['page-art'] });
795
+ // asset.status === 'pending_moderation' ← NOT visible to others yet
796
+
797
+ // 2. Browse what the community published
798
+ const { assets, nextCursor } = await listCommunity({ limit: 30, tag: 'page-art' });
799
+
800
+ // 3. Sign a whole gallery in ONE call (URLs last ~5 min; the hook refreshes them)
801
+ const urls = await getUrls(assets.map((a) => a.assetId));
802
+ // urls[i]: { assetId, url, expiresAt } → drop straight into <img src={url} />
803
+ ```
804
+
805
+ Three things to design around:
806
+
807
+ 1. **Publishing is not instant.** `publish()` returns `status: 'pending_moderation'`. It shows up in `listCommunity()` only once approved — so show the author their own pending item via `listMine()` instead of optimistically adding it to the community feed.
808
+ 2. **Batch your URLs.** Use `getUrls()` for a gallery or a multi-page book. Thirteen separate `getUrl()` calls against a ~5-minute TTL is the shape this exists to avoid. Ids that were taken down or aren't published yet are simply omitted — render around the gap.
809
+ 3. **Structure goes in the Data Store.** Which asset belongs on which page/level lives in a `shared`-scope Data Store collection holding `assetId`s. Community Assets stores the bytes and nothing queryable — `tags` plus cursor paging is the whole query surface, deliberately.
810
+
811
+ Only images the user made or uploaded in **their own** Fias files can be published (pass the `fileId` from a `useImageGeneration()` result). PNG/JPEG/WebP only; every image is re-encoded to a canonical PNG with metadata stripped. Publishers can `unpublish()` their own assets, and any user can `report()` one for review.
812
+
759
813
  ### `useFiasStore()` — In-app purchases (IAP)
760
814
 
761
815
  **Permission:** `store:purchase`