@rimori/client 2.5.36 → 2.5.37-next.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/dist/cli/types/DatabaseTypes.d.ts +12 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/plugin/RimoriClient.d.ts +3 -0
- package/dist/plugin/RimoriClient.js +4 -0
- package/dist/plugin/module/AssetsModule.d.ts +41 -0
- package/dist/plugin/module/AssetsModule.js +34 -0
- package/package.json +1 -1
|
@@ -16,7 +16,18 @@
|
|
|
16
16
|
* 3. The column MUST be named 'embedding' and only one per table is allowed.
|
|
17
17
|
* 4. Requires `source_column` — the column whose content is embedded async on insert.
|
|
18
18
|
*/
|
|
19
|
-
|
|
19
|
+
/**
|
|
20
|
+
* 'image', 'audio', 'video' and 'file' are stored as `text` (URL) in the database.
|
|
21
|
+
* Marking a column with one of these types causes the migration system to:
|
|
22
|
+
* 1. Add an `updated_at` timestamp + trigger to the table.
|
|
23
|
+
* 2. Register the column for the asset-refs cron, which links rows to bucket
|
|
24
|
+
* files (in the `plugin-assets` Supabase bucket) and deletes orphans when
|
|
25
|
+
* the row is deleted, the column is replaced, or the value is cleared.
|
|
26
|
+
*
|
|
27
|
+
* Use these types instead of `text` for any column whose value is a URL into the
|
|
28
|
+
* `plugin-assets` bucket — that way the file is automatically cleaned up.
|
|
29
|
+
*/
|
|
30
|
+
type DbColumnType = 'decimal' | 'integer' | 'text' | 'boolean' | 'json' | 'timestamp' | 'uuid' | 'markdown' | 'vector' | 'image' | 'audio' | 'video' | 'file';
|
|
20
31
|
/**
|
|
21
32
|
* Foreign key relationship configuration with cascade delete support.
|
|
22
33
|
* Defines a relationship where the source record is deleted when the destination record is deleted.
|
package/dist/index.d.ts
CHANGED
|
@@ -21,4 +21,5 @@ export { TIER_ORDER, ROLE_ORDER } from './plugin/module/PluginModule';
|
|
|
21
21
|
export type { SharedContent, BasicSharedContent, ContentStatus } from './plugin/module/SharedContentController';
|
|
22
22
|
export type { MacroAccomplishmentPayload, MicroAccomplishmentPayload } from './controller/AccomplishmentController';
|
|
23
23
|
export { StorageModule } from './plugin/module/StorageModule';
|
|
24
|
+
export { AssetsModule, type AssetKind } from './plugin/module/AssetsModule';
|
|
24
25
|
export type { PublicityLevel } from './plugin/module/DbModule';
|
package/dist/index.js
CHANGED
|
@@ -13,3 +13,4 @@ export { AudioController } from './controller/AudioController';
|
|
|
13
13
|
export { Translator } from './controller/TranslationController';
|
|
14
14
|
export { TIER_ORDER, ROLE_ORDER } from './plugin/module/PluginModule';
|
|
15
15
|
export { StorageModule } from './plugin/module/StorageModule';
|
|
16
|
+
export { AssetsModule } from './plugin/module/AssetsModule';
|
|
@@ -6,6 +6,7 @@ import { EventModule } from './module/EventModule';
|
|
|
6
6
|
import { AIModule } from './module/AIModule';
|
|
7
7
|
import { ExerciseModule } from './module/ExerciseModule';
|
|
8
8
|
import { StorageModule } from './module/StorageModule';
|
|
9
|
+
import { AssetsModule } from './module/AssetsModule';
|
|
9
10
|
import { EventBusHandler } from '../fromRimori/EventBus';
|
|
10
11
|
export declare class RimoriClient {
|
|
11
12
|
private static instance;
|
|
@@ -18,6 +19,8 @@ export declare class RimoriClient {
|
|
|
18
19
|
exercise: ExerciseModule;
|
|
19
20
|
/** Upload and manage images stored in Supabase via the backend. */
|
|
20
21
|
storage: StorageModule;
|
|
22
|
+
/** Upload assets (image/audio/video/file) backing asset-typed db.config columns. */
|
|
23
|
+
assets: AssetsModule;
|
|
21
24
|
/** The EventBus instance used by this client. In federation mode this is a per-plugin instance. */
|
|
22
25
|
eventBus: EventBusHandler;
|
|
23
26
|
private constructor();
|
|
@@ -7,6 +7,7 @@ import { EventModule } from './module/EventModule';
|
|
|
7
7
|
import { AIModule } from './module/AIModule';
|
|
8
8
|
import { ExerciseModule } from './module/ExerciseModule';
|
|
9
9
|
import { StorageModule } from './module/StorageModule';
|
|
10
|
+
import { AssetsModule } from './module/AssetsModule';
|
|
10
11
|
import { PostgrestClient } from '@supabase/postgrest-js';
|
|
11
12
|
import { EventBus, EventBusHandler } from '../fromRimori/EventBus';
|
|
12
13
|
export class RimoriClient {
|
|
@@ -20,6 +21,8 @@ export class RimoriClient {
|
|
|
20
21
|
exercise;
|
|
21
22
|
/** Upload and manage images stored in Supabase via the backend. */
|
|
22
23
|
storage;
|
|
24
|
+
/** Upload assets (image/audio/video/file) backing asset-typed db.config columns. */
|
|
25
|
+
assets;
|
|
23
26
|
/** The EventBus instance used by this client. In federation mode this is a per-plugin instance. */
|
|
24
27
|
eventBus;
|
|
25
28
|
constructor(controller, supabase, info, eventBus) {
|
|
@@ -35,6 +38,7 @@ export class RimoriClient {
|
|
|
35
38
|
this.plugin = new PluginModule(supabase, controller, info, this.ai);
|
|
36
39
|
this.exercise = new ExerciseModule(supabase, controller, info, this.event);
|
|
37
40
|
this.storage = new StorageModule(controller);
|
|
41
|
+
this.assets = new AssetsModule(controller);
|
|
38
42
|
//only init logger in workers and on main plugin pages
|
|
39
43
|
if (this.plugin.applicationMode !== 'sidebar') {
|
|
40
44
|
Logger.getInstance(this);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Assets module for the `plugin-assets` Supabase bucket.
|
|
3
|
+
*
|
|
4
|
+
* Use this to upload files (image|audio|video|file) whose URL is stored in a
|
|
5
|
+
* matching `type: 'image' | 'audio' | 'video' | 'file'` column in db.config.ts.
|
|
6
|
+
*
|
|
7
|
+
* Lifecycle is automatic: the backend asset-refs cron links the upload to the
|
|
8
|
+
* row whose column value matches the returned URL (within ~30 minutes), and
|
|
9
|
+
* deletes the file when the row is removed or the column is replaced/cleared.
|
|
10
|
+
* No plugin-side confirm or delete call is needed.
|
|
11
|
+
*
|
|
12
|
+
* For markdown editor images (embedded as `` in markdown text), use
|
|
13
|
+
* `plugin.storage.uploadImage` instead — that has a different lifecycle (regex
|
|
14
|
+
* scan over markdown bodies) and lives in the separate `plugin-images` bucket.
|
|
15
|
+
*/
|
|
16
|
+
import { RimoriCommunicationHandler } from '../CommunicationHandler';
|
|
17
|
+
export type AssetKind = 'image' | 'audio' | 'video' | 'file';
|
|
18
|
+
export declare class AssetsModule {
|
|
19
|
+
private readonly controller;
|
|
20
|
+
constructor(controller: RimoriCommunicationHandler);
|
|
21
|
+
/**
|
|
22
|
+
* Upload a blob as an asset of the given kind.
|
|
23
|
+
*
|
|
24
|
+
* @returns `{ data: { url, path } }` on success, `{ error }` on failure.
|
|
25
|
+
* Store `url` in the matching asset-typed column on your row. The cron
|
|
26
|
+
* will pick it up on the next tick and confirm the ref.
|
|
27
|
+
*/
|
|
28
|
+
upload(blob: Blob, options: {
|
|
29
|
+
kind: AssetKind;
|
|
30
|
+
filename?: string;
|
|
31
|
+
}): Promise<{
|
|
32
|
+
data: {
|
|
33
|
+
url: string;
|
|
34
|
+
path: string;
|
|
35
|
+
};
|
|
36
|
+
error?: undefined;
|
|
37
|
+
} | {
|
|
38
|
+
data?: undefined;
|
|
39
|
+
error: Error;
|
|
40
|
+
}>;
|
|
41
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export class AssetsModule {
|
|
2
|
+
controller;
|
|
3
|
+
constructor(controller) {
|
|
4
|
+
this.controller = controller;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Upload a blob as an asset of the given kind.
|
|
8
|
+
*
|
|
9
|
+
* @returns `{ data: { url, path } }` on success, `{ error }` on failure.
|
|
10
|
+
* Store `url` in the matching asset-typed column on your row. The cron
|
|
11
|
+
* will pick it up on the next tick and confirm the ref.
|
|
12
|
+
*/
|
|
13
|
+
async upload(blob, options) {
|
|
14
|
+
const formData = new FormData();
|
|
15
|
+
const filename = options.filename ?? `asset.${options.kind}`;
|
|
16
|
+
formData.append('file', blob, filename);
|
|
17
|
+
formData.append('kind', options.kind);
|
|
18
|
+
try {
|
|
19
|
+
const response = await this.controller.fetchBackend('/plugin-assets/upload', {
|
|
20
|
+
method: 'POST',
|
|
21
|
+
body: formData,
|
|
22
|
+
});
|
|
23
|
+
if (!response.ok) {
|
|
24
|
+
const body = (await response.json().catch(() => ({})));
|
|
25
|
+
return { error: new Error(body.message ?? `Upload failed (${response.status})`) };
|
|
26
|
+
}
|
|
27
|
+
const result = (await response.json());
|
|
28
|
+
return { data: result };
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
return { error: err instanceof Error ? err : new Error(String(err)) };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|