@jami-studio/core 0.92.27 → 0.92.28
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/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +17 -0
- package/corpus/core/package.json +2 -1
- package/corpus/core/src/deploy/build.ts +56 -2
- package/corpus/core/src/event-bus/bus.ts +138 -140
- package/corpus/core/src/event-bus/registry.ts +81 -79
- package/corpus/core/src/file-upload/registry.ts +135 -125
- package/corpus/core/src/notifications/registry.ts +218 -216
- package/corpus/core/src/private-blob/registry.ts +246 -242
- package/corpus/core/src/secrets/register.ts +132 -129
- package/corpus/core/src/shared/global-scope.ts +75 -0
- package/corpus/core/src/sharing/registry.ts +193 -194
- package/corpus/core/src/tracking/providers.ts +425 -422
- package/corpus/core/src/tracking/registry.ts +102 -102
- package/dist/collab/routes.d.ts +1 -1
- package/dist/deploy/build.d.ts +23 -0
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +36 -2
- package/dist/deploy/build.js.map +1 -1
- package/dist/event-bus/bus.d.ts.map +1 -1
- package/dist/event-bus/bus.js +8 -6
- package/dist/event-bus/bus.js.map +1 -1
- package/dist/event-bus/registry.d.ts.map +1 -1
- package/dist/event-bus/registry.js +10 -6
- package/dist/event-bus/registry.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/file-upload/registry.d.ts.map +1 -1
- package/dist/file-upload/registry.js +28 -8
- package/dist/file-upload/registry.js.map +1 -1
- package/dist/notifications/registry.d.ts.map +1 -1
- package/dist/notifications/registry.js +6 -5
- package/dist/notifications/registry.js.map +1 -1
- package/dist/observability/routes.d.ts +5 -5
- package/dist/private-blob/registry.d.ts.map +1 -1
- package/dist/private-blob/registry.js +18 -13
- package/dist/private-blob/registry.js.map +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +2 -2
- package/dist/secrets/register.d.ts.map +1 -1
- package/dist/secrets/register.js +11 -7
- package/dist/secrets/register.js.map +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/shared/global-scope.d.ts +55 -0
- package/dist/shared/global-scope.d.ts.map +1 -0
- package/dist/shared/global-scope.js +70 -0
- package/dist/shared/global-scope.js.map +1 -0
- package/dist/sharing/registry.d.ts.map +1 -1
- package/dist/sharing/registry.js +2 -16
- package/dist/sharing/registry.js.map +1 -1
- package/dist/tracking/providers.d.ts.map +1 -1
- package/dist/tracking/providers.js +11 -9
- package/dist/tracking/providers.js.map +1 -1
- package/dist/tracking/registry.d.ts.map +1 -1
- package/dist/tracking/registry.js +5 -5
- package/dist/tracking/registry.js.map +1 -1
- package/package.json +2 -1
|
@@ -1,194 +1,193 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Registry of shareable resources.
|
|
3
|
-
*
|
|
4
|
-
* Each template registers its ownable resource(s) once on module load so the
|
|
5
|
-
* framework-level share actions (`share-resource`, `list-resource-shares`,
|
|
6
|
-
* etc.) can dispatch to the correct tables.
|
|
7
|
-
*
|
|
8
|
-
* import { registerShareableResource } from "@agent-native/core/sharing";
|
|
9
|
-
* import * as schema from "./schema.js";
|
|
10
|
-
*
|
|
11
|
-
* registerShareableResource({
|
|
12
|
-
* type: "document",
|
|
13
|
-
* resourceTable: schema.documents,
|
|
14
|
-
* sharesTable: schema.documentShares,
|
|
15
|
-
* displayName: "Document",
|
|
16
|
-
* titleColumn: "title",
|
|
17
|
-
* });
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
|
|
25
|
-
/** Drizzle table
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
*
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
| "
|
|
69
|
-
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
| "
|
|
76
|
-
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
|
|
124
|
-
/** Optional override for the
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
//
|
|
132
|
-
//
|
|
133
|
-
// bundle
|
|
134
|
-
//
|
|
135
|
-
//
|
|
136
|
-
//
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
process.env.
|
|
146
|
-
process.env.VITEST === "
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
)
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
)
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Registry of shareable resources.
|
|
3
|
+
*
|
|
4
|
+
* Each template registers its ownable resource(s) once on module load so the
|
|
5
|
+
* framework-level share actions (`share-resource`, `list-resource-shares`,
|
|
6
|
+
* etc.) can dispatch to the correct tables.
|
|
7
|
+
*
|
|
8
|
+
* import { registerShareableResource } from "@agent-native/core/sharing";
|
|
9
|
+
* import * as schema from "./schema.js";
|
|
10
|
+
*
|
|
11
|
+
* registerShareableResource({
|
|
12
|
+
* type: "document",
|
|
13
|
+
* resourceTable: schema.documents,
|
|
14
|
+
* sharesTable: schema.documentShares,
|
|
15
|
+
* displayName: "Document",
|
|
16
|
+
* titleColumn: "title",
|
|
17
|
+
* });
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { getScopedGlobal } from "../shared/global-scope.js";
|
|
21
|
+
|
|
22
|
+
export interface ShareableResourceRegistration {
|
|
23
|
+
/** Stable identifier used across actions, UI, and analytics. e.g. "document". */
|
|
24
|
+
type: string;
|
|
25
|
+
/** Drizzle table for the parent resource (must have ownableColumns()). */
|
|
26
|
+
resourceTable: any;
|
|
27
|
+
/** Drizzle table produced by createSharesTable(). */
|
|
28
|
+
sharesTable: any;
|
|
29
|
+
/** Human-readable singular label shown in the share dialog. */
|
|
30
|
+
displayName: string;
|
|
31
|
+
/**
|
|
32
|
+
* Column on the resource table that holds a human-readable title for
|
|
33
|
+
* display in the share UI. Default: "title".
|
|
34
|
+
*/
|
|
35
|
+
titleColumn?: string;
|
|
36
|
+
/**
|
|
37
|
+
* Optional app-relative path to this resource. Used by share notifications
|
|
38
|
+
* when the caller does not pass a more specific resourceUrl.
|
|
39
|
+
*/
|
|
40
|
+
getResourcePath?: (resource: any) => string | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* Drizzle DB accessor from the template's server/db/index.ts. Required —
|
|
43
|
+
* the framework-level share actions and access helpers call this to reach
|
|
44
|
+
* the right DB instance (schema is template-specific).
|
|
45
|
+
*/
|
|
46
|
+
getDb: () => any;
|
|
47
|
+
/**
|
|
48
|
+
* When `false`, `visibility: "public"` is rejected by `set-resource-visibility`,
|
|
49
|
+
* and `accessFilter` / `resolveAccess` treat any stored public row as private
|
|
50
|
+
* (defense in depth — only owner + explicit shares grant access).
|
|
51
|
+
*
|
|
52
|
+
* Use this for resources that execute code or expose privileged data and must
|
|
53
|
+
* never be reachable by a random authenticated user. Extensions set this:
|
|
54
|
+
* extension HTML runs inside an iframe that calls actions / DB / proxied APIs
|
|
55
|
+
* as the *viewer*, so a public extension would be arbitrary code with the
|
|
56
|
+
* viewer's credentials.
|
|
57
|
+
*
|
|
58
|
+
* Default: `true` (matches the historical behavior — most resources can be public).
|
|
59
|
+
*/
|
|
60
|
+
allowPublic?: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Optional role granted by a public-by-link read. Most resources should omit
|
|
63
|
+
* this so public visibility remains viewer-only. Use narrowly for local or
|
|
64
|
+
* otherwise constrained resources where the resource owner intentionally wants
|
|
65
|
+
* unauthenticated link holders to do more than view.
|
|
66
|
+
*/
|
|
67
|
+
publicAccessRole?:
|
|
68
|
+
| "viewer"
|
|
69
|
+
| "editor"
|
|
70
|
+
| "admin"
|
|
71
|
+
| ((
|
|
72
|
+
resource: any,
|
|
73
|
+
ctx: { userEmail?: string; orgId?: string },
|
|
74
|
+
) =>
|
|
75
|
+
| "viewer"
|
|
76
|
+
| "editor"
|
|
77
|
+
| "admin"
|
|
78
|
+
| Promise<"viewer" | "editor" | "admin">);
|
|
79
|
+
/**
|
|
80
|
+
* When `true`, individual user shares (`principalType: "user"`) must target
|
|
81
|
+
* an email that is already a member of the same org as the resource, OR has
|
|
82
|
+
* a pending invitation to that org. Cross-org user shares are rejected.
|
|
83
|
+
*
|
|
84
|
+
* Pair with `allowPublic: false` for resources that need a hard "this org
|
|
85
|
+
* only" trust boundary. Extensions set this so a malicious caller can't
|
|
86
|
+
* widen reach by sharing a code-executing extension to an outsider email.
|
|
87
|
+
*
|
|
88
|
+
* Default: `false` (matches the historical behavior — any email can be granted).
|
|
89
|
+
*/
|
|
90
|
+
requireOrgMemberForUserShares?: boolean;
|
|
91
|
+
/**
|
|
92
|
+
* Optional per-resource access-context adapter. Most resources should use the
|
|
93
|
+
* request user/org unchanged. Templates with an intentional alternate local
|
|
94
|
+
* identity can normalize here so the generic framework sharing actions and
|
|
95
|
+
* access helpers stay in sync with template-owned actions.
|
|
96
|
+
*/
|
|
97
|
+
resolveAccessContext?: (ctx: { userEmail?: string; orgId?: string }) => {
|
|
98
|
+
userEmail?: string;
|
|
99
|
+
orgId?: string;
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* When true, direct ownership is recognized by owner_email regardless of the
|
|
103
|
+
* caller's active org. Use this only for resource types where the template's
|
|
104
|
+
* own actions already treat owner_email as the cross-org authority and list
|
|
105
|
+
* views add their own org filters.
|
|
106
|
+
*
|
|
107
|
+
* Default: `false`.
|
|
108
|
+
*/
|
|
109
|
+
ownerAccessIgnoresOrg?: boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Optional external-agent read handoff. When set, the framework-level
|
|
112
|
+
* `create-agent-resource-link` action can mint a short-lived, read-only
|
|
113
|
+
* `agent_access` URL for this resource. The context endpoint is owned by the
|
|
114
|
+
* template so it can expose the same intentionally shareable shape as the
|
|
115
|
+
* public page, not a generic raw database row.
|
|
116
|
+
*/
|
|
117
|
+
agentReadable?:
|
|
118
|
+
| false
|
|
119
|
+
| {
|
|
120
|
+
/** Token scope. Include the app name to avoid cross-app collisions. */
|
|
121
|
+
resourceKind: string;
|
|
122
|
+
/** App-relative JSON endpoint that accepts `id` + `agent_access`. */
|
|
123
|
+
getContextPath: (resource: any) => string | undefined;
|
|
124
|
+
/** Optional override for the page URL. Defaults to getResourcePath. */
|
|
125
|
+
getPagePath?: (resource: any) => string | undefined;
|
|
126
|
+
/** Optional override for the default two-hour token lifetime. */
|
|
127
|
+
ttlSeconds?: number;
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Stash the registry on globalThis so it survives SSR bundle duplication.
|
|
132
|
+
// Vite SSR's `noExternal: /^(?!node:)/` policy means @agent-native/core gets
|
|
133
|
+
// inlined into every server bundle that imports it — and each bundle gets its
|
|
134
|
+
// own module-level state. A plain `new Map()` here would create one Map per
|
|
135
|
+
// bundle, so the template's `registerShareableResource()` (called from the
|
|
136
|
+
// Nitro plugin graph) wouldn't be visible to the framework's auto-mounted
|
|
137
|
+
// share-resource action (loaded via `import("../sharing/actions/...js")` in a
|
|
138
|
+
// different module instance). Using globalThis collapses them back to one Map.
|
|
139
|
+
// Scope-aware + lazily resolved so unified workspace deployments (all apps in
|
|
140
|
+
// one isolate) keep per-app registrations. See shared/global-scope.
|
|
141
|
+
type RegistryStore = Map<string, ShareableResourceRegistration>;
|
|
142
|
+
|
|
143
|
+
function isTestRuntime(): boolean {
|
|
144
|
+
return (
|
|
145
|
+
process.env.NODE_ENV === "test" ||
|
|
146
|
+
process.env.VITEST === "true" ||
|
|
147
|
+
process.env.VITEST === "1"
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function registrationCameFromTestFile(): boolean {
|
|
152
|
+
const stack = new Error().stack ?? "";
|
|
153
|
+
return /[./\\](?:[^/\\]+[.-])(?:test|spec)\.[cm]?[jt]sx?(?::\d+)?(?::\d+)?/.test(
|
|
154
|
+
stack,
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function getRegistry(): RegistryStore {
|
|
159
|
+
return getScopedGlobal(
|
|
160
|
+
"agent-native.sharing.shareable-resources",
|
|
161
|
+
() => new Map<string, ShareableResourceRegistration>(),
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export function registerShareableResource(
|
|
166
|
+
entry: ShareableResourceRegistration,
|
|
167
|
+
): void {
|
|
168
|
+
if (!isTestRuntime() && registrationCameFromTestFile()) return;
|
|
169
|
+
getRegistry().set(entry.type, entry);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export function getShareableResource(
|
|
173
|
+
type: string,
|
|
174
|
+
): ShareableResourceRegistration | undefined {
|
|
175
|
+
return getRegistry().get(type);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export function requireShareableResource(
|
|
179
|
+
type: string,
|
|
180
|
+
): ShareableResourceRegistration {
|
|
181
|
+
const reg = getRegistry();
|
|
182
|
+
const entry = reg.get(type);
|
|
183
|
+
if (!entry) {
|
|
184
|
+
throw new Error(
|
|
185
|
+
`Unknown shareable resource type: "${type}". Did you forget registerShareableResource()?`,
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
return entry;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export function listShareableResources(): ShareableResourceRegistration[] {
|
|
192
|
+
return Array.from(getRegistry().values());
|
|
193
|
+
}
|