@agent-native/core 0.7.2 → 0.7.6
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 +6 -5
- package/dist/agent/engine/anthropic-engine.d.ts.map +1 -1
- package/dist/agent/engine/anthropic-engine.js +8 -4
- package/dist/agent/engine/anthropic-engine.js.map +1 -1
- package/dist/agent/engine/types.d.ts +1 -1
- package/dist/agent/engine/types.d.ts.map +1 -1
- package/dist/agent/production-agent.d.ts +7 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +153 -118
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +8 -1
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/index.js +8 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/info.d.ts +2 -0
- package/dist/cli/info.d.ts.map +1 -0
- package/dist/cli/info.js +103 -0
- package/dist/cli/info.js.map +1 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +171 -68
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/FeedbackButton.d.ts +3 -1
- package/dist/client/FeedbackButton.d.ts.map +1 -1
- package/dist/client/FeedbackButton.js +115 -40
- package/dist/client/FeedbackButton.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +12 -1
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts +3 -1
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +46 -2
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/composer/VoiceButton.d.ts +21 -0
- package/dist/client/composer/VoiceButton.d.ts.map +1 -0
- package/dist/client/composer/VoiceButton.js +51 -0
- package/dist/client/composer/VoiceButton.js.map +1 -0
- package/dist/client/composer/useVoiceDictation.d.ts +38 -0
- package/dist/client/composer/useVoiceDictation.d.ts.map +1 -0
- package/dist/client/composer/useVoiceDictation.js +398 -0
- package/dist/client/composer/useVoiceDictation.js.map +1 -0
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -0
- package/dist/client/index.js.map +1 -1
- package/dist/client/onboarding/OnboardingPanel.js +2 -2
- package/dist/client/onboarding/OnboardingPanel.js.map +1 -1
- package/dist/client/org/OrgSwitcher.d.ts +5 -4
- package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
- package/dist/client/org/OrgSwitcher.js +90 -24
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/resources/McpServerDetail.d.ts +15 -0
- package/dist/client/resources/McpServerDetail.d.ts.map +1 -0
- package/dist/client/resources/McpServerDetail.js +65 -0
- package/dist/client/resources/McpServerDetail.js.map +1 -0
- package/dist/client/resources/ResourceEditor.js +1 -1
- package/dist/client/resources/ResourceEditor.js.map +1 -1
- package/dist/client/resources/ResourceTree.d.ts +6 -1
- package/dist/client/resources/ResourceTree.d.ts.map +1 -1
- package/dist/client/resources/ResourceTree.js +18 -7
- package/dist/client/resources/ResourceTree.js.map +1 -1
- package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
- package/dist/client/resources/ResourcesPanel.js +191 -20
- package/dist/client/resources/ResourcesPanel.js.map +1 -1
- package/dist/client/resources/use-mcp-servers.d.ts +68 -0
- package/dist/client/resources/use-mcp-servers.d.ts.map +1 -0
- package/dist/client/resources/use-mcp-servers.js +83 -0
- package/dist/client/resources/use-mcp-servers.js.map +1 -0
- package/dist/client/resources/use-resources.d.ts +27 -1
- package/dist/client/resources/use-resources.d.ts.map +1 -1
- package/dist/client/resources/use-resources.js +63 -0
- package/dist/client/resources/use-resources.js.map +1 -1
- package/dist/client/settings/SecretsSection.d.ts +12 -0
- package/dist/client/settings/SecretsSection.d.ts.map +1 -0
- package/dist/client/settings/SecretsSection.js +148 -0
- package/dist/client/settings/SecretsSection.js.map +1 -0
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +101 -2
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/settings/VoiceTranscriptionSection.d.ts +14 -0
- package/dist/client/settings/VoiceTranscriptionSection.d.ts.map +1 -0
- package/dist/client/settings/VoiceTranscriptionSection.js +111 -0
- package/dist/client/settings/VoiceTranscriptionSection.js.map +1 -0
- package/dist/client/settings/index.d.ts +1 -0
- package/dist/client/settings/index.d.ts.map +1 -1
- package/dist/client/settings/index.js +1 -0
- package/dist/client/settings/index.js.map +1 -1
- package/dist/client/sharing/ShareButton.d.ts +16 -0
- package/dist/client/sharing/ShareButton.d.ts.map +1 -0
- package/dist/client/sharing/ShareButton.js +308 -0
- package/dist/client/sharing/ShareButton.js.map +1 -0
- package/dist/client/sharing/ShareDialog.d.ts +33 -0
- package/dist/client/sharing/ShareDialog.d.ts.map +1 -0
- package/dist/client/sharing/ShareDialog.js +231 -0
- package/dist/client/sharing/ShareDialog.js.map +1 -0
- package/dist/client/sharing/VisibilityBadge.d.ts +11 -0
- package/dist/client/sharing/VisibilityBadge.d.ts.map +1 -0
- package/dist/client/sharing/VisibilityBadge.js +19 -0
- package/dist/client/sharing/VisibilityBadge.js.map +1 -0
- package/dist/client/sharing/index.d.ts +4 -0
- package/dist/client/sharing/index.d.ts.map +1 -0
- package/dist/client/sharing/index.js +4 -0
- package/dist/client/sharing/index.js.map +1 -0
- package/dist/client/use-action.d.ts.map +1 -1
- package/dist/client/use-action.js +27 -3
- package/dist/client/use-action.js.map +1 -1
- package/dist/db/migrations.d.ts +18 -3
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +25 -3
- package/dist/db/migrations.js.map +1 -1
- package/dist/db/schema.d.ts +1 -0
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +4 -0
- package/dist/db/schema.js.map +1 -1
- package/dist/deploy/build.js +22 -3
- package/dist/deploy/build.js.map +1 -1
- package/dist/deploy/workspace-core.js +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp-client/config.d.ts +20 -1
- package/dist/mcp-client/config.d.ts.map +1 -1
- package/dist/mcp-client/config.js +28 -11
- package/dist/mcp-client/config.js.map +1 -1
- package/dist/mcp-client/hub-client.d.ts +38 -0
- package/dist/mcp-client/hub-client.d.ts.map +1 -0
- package/dist/mcp-client/hub-client.js +147 -0
- package/dist/mcp-client/hub-client.js.map +1 -0
- package/dist/mcp-client/hub-routes.d.ts +42 -0
- package/dist/mcp-client/hub-routes.d.ts.map +1 -0
- package/dist/mcp-client/hub-routes.js +114 -0
- package/dist/mcp-client/hub-routes.js.map +1 -0
- package/dist/mcp-client/index.d.ts +15 -0
- package/dist/mcp-client/index.d.ts.map +1 -1
- package/dist/mcp-client/index.js +35 -0
- package/dist/mcp-client/index.js.map +1 -1
- package/dist/mcp-client/manager.d.ts +54 -8
- package/dist/mcp-client/manager.d.ts.map +1 -1
- package/dist/mcp-client/manager.js +276 -59
- package/dist/mcp-client/manager.js.map +1 -1
- package/dist/mcp-client/remote-store.d.ts +102 -0
- package/dist/mcp-client/remote-store.d.ts.map +1 -0
- package/dist/mcp-client/remote-store.js +200 -0
- package/dist/mcp-client/remote-store.js.map +1 -0
- package/dist/mcp-client/routes.d.ts +55 -0
- package/dist/mcp-client/routes.d.ts.map +1 -0
- package/dist/mcp-client/routes.js +384 -0
- package/dist/mcp-client/routes.js.map +1 -0
- package/dist/mcp-client/visibility.d.ts +16 -0
- package/dist/mcp-client/visibility.d.ts.map +1 -0
- package/dist/mcp-client/visibility.js +45 -0
- package/dist/mcp-client/visibility.js.map +1 -0
- package/dist/onboarding/default-steps.d.ts.map +1 -1
- package/dist/onboarding/default-steps.js +5 -0
- package/dist/onboarding/default-steps.js.map +1 -1
- package/dist/org/accept-pending.d.ts +22 -0
- package/dist/org/accept-pending.d.ts.map +1 -0
- package/dist/org/accept-pending.js +75 -0
- package/dist/org/accept-pending.js.map +1 -0
- package/dist/org/context.js +2 -2
- package/dist/org/context.js.map +1 -1
- package/dist/org/handlers.d.ts +2 -0
- package/dist/org/handlers.d.ts.map +1 -1
- package/dist/org/handlers.js +54 -3
- package/dist/org/handlers.js.map +1 -1
- package/dist/org/index.d.ts +2 -0
- package/dist/org/index.d.ts.map +1 -1
- package/dist/org/index.js +1 -0
- package/dist/org/index.js.map +1 -1
- package/dist/resources/handlers.d.ts.map +1 -1
- package/dist/resources/handlers.js +30 -0
- package/dist/resources/handlers.js.map +1 -1
- package/dist/secrets/index.d.ts +15 -0
- package/dist/secrets/index.d.ts.map +1 -0
- package/dist/secrets/index.js +15 -0
- package/dist/secrets/index.js.map +1 -0
- package/dist/secrets/onboarding.d.ts +18 -0
- package/dist/secrets/onboarding.d.ts.map +1 -0
- package/dist/secrets/onboarding.js +87 -0
- package/dist/secrets/onboarding.js.map +1 -0
- package/dist/secrets/register-framework-secrets.d.ts +13 -0
- package/dist/secrets/register-framework-secrets.d.ts.map +1 -0
- package/dist/secrets/register-framework-secrets.js +59 -0
- package/dist/secrets/register-framework-secrets.js.map +1 -0
- package/dist/secrets/register.d.ts +63 -0
- package/dist/secrets/register.d.ts.map +1 -0
- package/dist/secrets/register.js +62 -0
- package/dist/secrets/register.js.map +1 -0
- package/dist/secrets/routes.d.ts +67 -0
- package/dist/secrets/routes.d.ts.map +1 -0
- package/dist/secrets/routes.js +275 -0
- package/dist/secrets/routes.js.map +1 -0
- package/dist/secrets/schema.d.ts +154 -0
- package/dist/secrets/schema.d.ts.map +1 -0
- package/dist/secrets/schema.js +41 -0
- package/dist/secrets/schema.js.map +1 -0
- package/dist/secrets/storage.d.ts +54 -0
- package/dist/secrets/storage.d.ts.map +1 -0
- package/dist/secrets/storage.js +181 -0
- package/dist/secrets/storage.js.map +1 -0
- package/dist/server/action-discovery.d.ts +18 -0
- package/dist/server/action-discovery.d.ts.map +1 -1
- package/dist/server/action-discovery.js +95 -0
- package/dist/server/action-discovery.js.map +1 -1
- package/dist/server/action-routes.d.ts.map +1 -1
- package/dist/server/action-routes.js +22 -2
- package/dist/server/action-routes.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts +16 -0
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +120 -25
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/app-name.d.ts +13 -0
- package/dist/server/app-name.d.ts.map +1 -0
- package/dist/server/app-name.js +41 -0
- package/dist/server/app-name.js.map +1 -0
- package/dist/server/app-url.d.ts +24 -0
- package/dist/server/app-url.d.ts.map +1 -0
- package/dist/server/app-url.js +76 -0
- package/dist/server/app-url.js.map +1 -0
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +50 -0
- package/dist/server/auth.js.map +1 -1
- package/dist/server/better-auth-instance.d.ts.map +1 -1
- package/dist/server/better-auth-instance.js +137 -13
- package/dist/server/better-auth-instance.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +73 -0
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/create-server.d.ts.map +1 -1
- package/dist/server/create-server.js +6 -0
- package/dist/server/create-server.js.map +1 -1
- package/dist/server/date-utils.d.ts +15 -0
- package/dist/server/date-utils.d.ts.map +1 -0
- package/dist/server/date-utils.js +41 -0
- package/dist/server/date-utils.js.map +1 -0
- package/dist/server/email-template.d.ts +51 -0
- package/dist/server/email-template.d.ts.map +1 -0
- package/dist/server/email-template.js +146 -0
- package/dist/server/email-template.js.map +1 -0
- package/dist/server/index.d.ts +6 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +6 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/onboarding-html.d.ts +3 -0
- package/dist/server/onboarding-html.d.ts.map +1 -1
- package/dist/server/onboarding-html.js +13 -3
- package/dist/server/onboarding-html.js.map +1 -1
- package/dist/server/request-context.d.ts +9 -0
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/request-context.js +10 -0
- package/dist/server/request-context.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +26 -0
- package/dist/server/transcribe-voice.d.ts.map +1 -0
- package/dist/server/transcribe-voice.js +143 -0
- package/dist/server/transcribe-voice.js.map +1 -0
- package/dist/sharing/access.d.ts +56 -0
- package/dist/sharing/access.d.ts.map +1 -0
- package/dist/sharing/access.js +149 -0
- package/dist/sharing/access.js.map +1 -0
- package/dist/sharing/actions/list-resource-shares.d.ts +3 -0
- package/dist/sharing/actions/list-resource-shares.d.ts.map +1 -0
- package/dist/sharing/actions/list-resource-shares.js +38 -0
- package/dist/sharing/actions/list-resource-shares.js.map +1 -0
- package/dist/sharing/actions/set-resource-visibility.d.ts +3 -0
- package/dist/sharing/actions/set-resource-visibility.d.ts.map +1 -0
- package/dist/sharing/actions/set-resource-visibility.js +24 -0
- package/dist/sharing/actions/set-resource-visibility.js.map +1 -0
- package/dist/sharing/actions/share-resource.d.ts +3 -0
- package/dist/sharing/actions/share-resource.d.ts.map +1 -0
- package/dist/sharing/actions/share-resource.js +64 -0
- package/dist/sharing/actions/share-resource.js.map +1 -0
- package/dist/sharing/actions/unshare-resource.d.ts +3 -0
- package/dist/sharing/actions/unshare-resource.d.ts.map +1 -0
- package/dist/sharing/actions/unshare-resource.js +24 -0
- package/dist/sharing/actions/unshare-resource.js.map +1 -0
- package/dist/sharing/index.d.ts +11 -0
- package/dist/sharing/index.d.ts.map +1 -0
- package/dist/sharing/index.js +11 -0
- package/dist/sharing/index.js.map +1 -0
- package/dist/sharing/registry.d.ts +44 -0
- package/dist/sharing/registry.d.ts.map +1 -0
- package/dist/sharing/registry.js +54 -0
- package/dist/sharing/registry.js.map +1 -0
- package/dist/sharing/schema.d.ts +202 -0
- package/dist/sharing/schema.d.ts.map +1 -0
- package/dist/sharing/schema.js +88 -0
- package/dist/sharing/schema.js.map +1 -0
- package/dist/styles/agent-native.css +111 -0
- package/dist/tailwind.preset.d.ts +2 -2
- package/dist/tailwind.preset.d.ts.map +1 -1
- package/dist/tailwind.preset.js +27 -7
- package/dist/tailwind.preset.js.map +1 -1
- package/dist/templates/default/app/global.css +65 -68
- package/dist/templates/default/components.json +1 -1
- package/dist/templates/default/package.json +2 -4
- package/dist/templates/default/vite.config.ts +3 -0
- package/dist/templates/workspace-core/package.json +1 -4
- package/dist/templates/workspace-core/src/index.ts +1 -1
- package/dist/templates/workspace-core/styles/tokens.css +22 -0
- package/dist/templates/workspace-core/tsconfig.json +1 -1
- package/dist/vite/action-types-plugin.d.ts +5 -0
- package/dist/vite/action-types-plugin.d.ts.map +1 -1
- package/dist/vite/action-types-plugin.js +129 -28
- package/dist/vite/action-types-plugin.js.map +1 -1
- package/dist/vite/client.d.ts +6 -0
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +18 -1
- package/dist/vite/client.js.map +1 -1
- package/docs/content/actions.md +169 -74
- package/docs/content/agent-teams.md +139 -0
- package/docs/content/cloneable-saas.md +98 -0
- package/docs/content/creating-templates.md +9 -11
- package/docs/content/deployment.md +2 -9
- package/docs/content/drop-in-agent.md +200 -0
- package/docs/content/enterprise-workspace.md +22 -10
- package/docs/content/getting-started.md +34 -19
- package/docs/content/integrations.md +3 -3
- package/docs/content/key-concepts.md +50 -23
- package/docs/content/mcp-clients.md +71 -0
- package/docs/content/pure-agent-apps.md +69 -0
- package/docs/content/recurring-jobs.md +123 -0
- package/docs/content/skills-guide.md +8 -0
- package/docs/content/template-analytics.md +190 -0
- package/docs/content/template-calendar.md +151 -0
- package/docs/content/template-clips.md +55 -0
- package/docs/content/template-content.md +141 -0
- package/docs/content/template-dispatch.md +58 -0
- package/docs/content/template-forms.md +51 -0
- package/docs/content/template-mail.md +169 -0
- package/docs/content/template-slides.md +218 -0
- package/docs/content/template-starter.md +68 -0
- package/docs/content/template-video.md +162 -0
- package/docs/content/voice-input.md +59 -0
- package/docs/content/what-is-agent-native.md +142 -45
- package/docs/content/workspace-management.md +1 -0
- package/docs/content/{resources.md → workspace.md} +94 -42
- package/package.json +20 -19
- package/src/templates/default/app/global.css +65 -68
- package/src/templates/default/components.json +1 -1
- package/src/templates/default/package.json +2 -4
- package/src/templates/default/vite.config.ts +3 -0
- package/src/templates/workspace-core/package.json +1 -4
- package/src/templates/workspace-core/src/index.ts +1 -1
- package/src/templates/workspace-core/styles/tokens.css +22 -0
- package/src/templates/workspace-core/tsconfig.json +1 -1
- package/dist/templates/default/postcss.config.js +0 -6
- package/dist/templates/default/tailwind.config.ts +0 -7
- package/dist/templates/workspace-core/tailwind.preset.ts +0 -34
- package/src/templates/default/postcss.config.js +0 -6
- package/src/templates/default/tailwind.config.ts +0 -7
- package/src/templates/workspace-core/tailwind.preset.ts +0 -34
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"set-resource-visibility.d.ts","sourceRoot":"","sources":["../../../src/sharing/actions/set-resource-visibility.ts"],"names":[],"mappings":";AAMA,wBAkBG"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { eq } from "drizzle-orm";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { defineAction } from "../../action.js";
|
|
4
|
+
import { assertAccess } from "../access.js";
|
|
5
|
+
import { requireShareableResource } from "../registry.js";
|
|
6
|
+
export default defineAction({
|
|
7
|
+
description: "Change the coarse visibility of a shareable resource: 'private' | 'org' | 'public'. Owner or admin role required.",
|
|
8
|
+
schema: z.object({
|
|
9
|
+
resourceType: z.string(),
|
|
10
|
+
resourceId: z.string(),
|
|
11
|
+
visibility: z.enum(["private", "org", "public"]),
|
|
12
|
+
}),
|
|
13
|
+
run: async (args) => {
|
|
14
|
+
const reg = requireShareableResource(args.resourceType);
|
|
15
|
+
await assertAccess(args.resourceType, args.resourceId, "admin");
|
|
16
|
+
const db = reg.getDb();
|
|
17
|
+
await db
|
|
18
|
+
.update(reg.resourceTable)
|
|
19
|
+
.set({ visibility: args.visibility })
|
|
20
|
+
.where(eq(reg.resourceTable.id, args.resourceId));
|
|
21
|
+
return { ok: true, visibility: args.visibility };
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
//# sourceMappingURL=set-resource-visibility.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"set-resource-visibility.js","sourceRoot":"","sources":["../../../src/sharing/actions/set-resource-visibility.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAE1D,eAAe,YAAY,CAAC;IAC1B,WAAW,EACT,mHAAmH;IACrH,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;QACxB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;QACtB,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;KACjD,CAAC;IACF,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QAClB,MAAM,GAAG,GAAG,wBAAwB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACxD,MAAM,YAAY,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAChE,MAAM,EAAE,GAAG,GAAG,CAAC,KAAK,EAAS,CAAC;QAC9B,MAAM,EAAE;aACL,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC;aACzB,GAAG,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC;aACpC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QACpD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC;IACnD,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"share-resource.d.ts","sourceRoot":"","sources":["../../../src/sharing/actions/share-resource.ts"],"names":[],"mappings":";AAgBA,wBAyDG"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { and, eq } from "drizzle-orm";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { defineAction } from "../../action.js";
|
|
4
|
+
import { getRequestUserEmail } from "../../server/request-context.js";
|
|
5
|
+
import { assertAccess, ForbiddenError } from "../access.js";
|
|
6
|
+
import { requireShareableResource } from "../registry.js";
|
|
7
|
+
function nanoid(size = 12) {
|
|
8
|
+
const chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
9
|
+
let id = "";
|
|
10
|
+
const bytes = crypto.getRandomValues(new Uint8Array(size));
|
|
11
|
+
for (const byte of bytes)
|
|
12
|
+
id += chars[byte % chars.length];
|
|
13
|
+
return id;
|
|
14
|
+
}
|
|
15
|
+
export default defineAction({
|
|
16
|
+
description: "Grant a user or org access to a shareable resource. Owner or admin role required.",
|
|
17
|
+
schema: z.object({
|
|
18
|
+
resourceType: z
|
|
19
|
+
.string()
|
|
20
|
+
.describe("Registered resource type, e.g. 'document', 'form'."),
|
|
21
|
+
resourceId: z.string().describe("Id of the resource to share."),
|
|
22
|
+
principalType: z
|
|
23
|
+
.enum(["user", "org"])
|
|
24
|
+
.describe("'user' for an individual, 'org' for a whole organization."),
|
|
25
|
+
principalId: z
|
|
26
|
+
.string()
|
|
27
|
+
.describe("Email (user) or org id (org) of the principal."),
|
|
28
|
+
role: z
|
|
29
|
+
.enum(["viewer", "editor", "admin"])
|
|
30
|
+
.default("viewer")
|
|
31
|
+
.describe("Role to grant."),
|
|
32
|
+
}),
|
|
33
|
+
run: async (args) => {
|
|
34
|
+
const reg = requireShareableResource(args.resourceType);
|
|
35
|
+
await assertAccess(args.resourceType, args.resourceId, "admin");
|
|
36
|
+
const actor = getRequestUserEmail();
|
|
37
|
+
if (!actor)
|
|
38
|
+
throw new ForbiddenError("Not signed in");
|
|
39
|
+
const db = reg.getDb();
|
|
40
|
+
const [existing] = await db
|
|
41
|
+
.select()
|
|
42
|
+
.from(reg.sharesTable)
|
|
43
|
+
.where(and(eq(reg.sharesTable.resourceId, args.resourceId), eq(reg.sharesTable.principalType, args.principalType), eq(reg.sharesTable.principalId, args.principalId)));
|
|
44
|
+
if (existing) {
|
|
45
|
+
await db
|
|
46
|
+
.update(reg.sharesTable)
|
|
47
|
+
.set({ role: args.role })
|
|
48
|
+
.where(eq(reg.sharesTable.id, existing.id));
|
|
49
|
+
return { id: existing.id, updated: true };
|
|
50
|
+
}
|
|
51
|
+
const id = nanoid();
|
|
52
|
+
await db.insert(reg.sharesTable).values({
|
|
53
|
+
id,
|
|
54
|
+
resourceId: args.resourceId,
|
|
55
|
+
principalType: args.principalType,
|
|
56
|
+
principalId: args.principalId,
|
|
57
|
+
role: args.role,
|
|
58
|
+
createdBy: actor,
|
|
59
|
+
createdAt: new Date().toISOString(),
|
|
60
|
+
});
|
|
61
|
+
return { id, updated: false };
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
//# sourceMappingURL=share-resource.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"share-resource.js","sourceRoot":"","sources":["../../../src/sharing/actions/share-resource.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unshare-resource.d.ts","sourceRoot":"","sources":["../../../src/sharing/actions/unshare-resource.ts"],"names":[],"mappings":";AAMA,wBAwBG"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { and, eq } from "drizzle-orm";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { defineAction } from "../../action.js";
|
|
4
|
+
import { assertAccess } from "../access.js";
|
|
5
|
+
import { requireShareableResource } from "../registry.js";
|
|
6
|
+
export default defineAction({
|
|
7
|
+
description: "Revoke a previously granted share. Owner or admin role required.",
|
|
8
|
+
schema: z.object({
|
|
9
|
+
resourceType: z.string(),
|
|
10
|
+
resourceId: z.string(),
|
|
11
|
+
principalType: z.enum(["user", "org"]),
|
|
12
|
+
principalId: z.string(),
|
|
13
|
+
}),
|
|
14
|
+
run: async (args) => {
|
|
15
|
+
const reg = requireShareableResource(args.resourceType);
|
|
16
|
+
await assertAccess(args.resourceType, args.resourceId, "admin");
|
|
17
|
+
const db = reg.getDb();
|
|
18
|
+
await db
|
|
19
|
+
.delete(reg.sharesTable)
|
|
20
|
+
.where(and(eq(reg.sharesTable.resourceId, args.resourceId), eq(reg.sharesTable.principalType, args.principalType), eq(reg.sharesTable.principalId, args.principalId)));
|
|
21
|
+
return { ok: true };
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
//# sourceMappingURL=unshare-resource.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unshare-resource.js","sourceRoot":"","sources":["../../../src/sharing/actions/unshare-resource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAE1D,eAAe,YAAY,CAAC;IAC1B,WAAW,EACT,kEAAkE;IACpE,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;QACxB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;QACtB,aAAa,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACtC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;KACxB,CAAC;IACF,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QAClB,MAAM,GAAG,GAAG,wBAAwB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACxD,MAAM,YAAY,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAChE,MAAM,EAAE,GAAG,GAAG,CAAC,KAAK,EAAS,CAAC;QAC9B,MAAM,EAAE;aACL,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC;aACvB,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,EAC/C,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,aAAa,EAAE,IAAI,CAAC,aAAa,CAAC,EACrD,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,WAAW,EAAE,IAAI,CAAC,WAAW,CAAC,CAClD,CACF,CAAC;QACJ,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework-level sharing / privacy primitive.
|
|
3
|
+
*
|
|
4
|
+
* Templates make their resource tables ownable and register them here so the
|
|
5
|
+
* shared share actions and UI work end-to-end. See
|
|
6
|
+
* `.agents/skills/sharing/SKILL.md` for the full pattern.
|
|
7
|
+
*/
|
|
8
|
+
export { ownableColumns, createSharesTable, roleSatisfies, ROLE_RANK, type Visibility, type ShareRole, type PrincipalType, } from "./schema.js";
|
|
9
|
+
export { registerShareableResource, getShareableResource, requireShareableResource, listShareableResources, type ShareableResourceRegistration, } from "./registry.js";
|
|
10
|
+
export { accessFilter, resolveAccess, assertAccess, currentAccess, ForbiddenError, type AccessContext, type ResolvedAccess, } from "./access.js";
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sharing/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,SAAS,EACT,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,aAAa,GACnB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,yBAAyB,EACzB,oBAAoB,EACpB,wBAAwB,EACxB,sBAAsB,EACtB,KAAK,6BAA6B,GACnC,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,aAAa,EACb,cAAc,EACd,KAAK,aAAa,EAClB,KAAK,cAAc,GACpB,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework-level sharing / privacy primitive.
|
|
3
|
+
*
|
|
4
|
+
* Templates make their resource tables ownable and register them here so the
|
|
5
|
+
* shared share actions and UI work end-to-end. See
|
|
6
|
+
* `.agents/skills/sharing/SKILL.md` for the full pattern.
|
|
7
|
+
*/
|
|
8
|
+
export { ownableColumns, createSharesTable, roleSatisfies, ROLE_RANK, } from "./schema.js";
|
|
9
|
+
export { registerShareableResource, getShareableResource, requireShareableResource, listShareableResources, } from "./registry.js";
|
|
10
|
+
export { accessFilter, resolveAccess, assertAccess, currentAccess, ForbiddenError, } from "./access.js";
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sharing/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,SAAS,GAIV,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,yBAAyB,EACzB,oBAAoB,EACpB,wBAAwB,EACxB,sBAAsB,GAEvB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,aAAa,EACb,cAAc,GAGf,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
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
|
+
export interface ShareableResourceRegistration {
|
|
20
|
+
/** Stable identifier used across actions, UI, and analytics. e.g. "document". */
|
|
21
|
+
type: string;
|
|
22
|
+
/** Drizzle table for the parent resource (must have ownableColumns()). */
|
|
23
|
+
resourceTable: any;
|
|
24
|
+
/** Drizzle table produced by createSharesTable(). */
|
|
25
|
+
sharesTable: any;
|
|
26
|
+
/** Human-readable singular label shown in the share dialog. */
|
|
27
|
+
displayName: string;
|
|
28
|
+
/**
|
|
29
|
+
* Column on the resource table that holds a human-readable title for
|
|
30
|
+
* display in the share UI. Default: "title".
|
|
31
|
+
*/
|
|
32
|
+
titleColumn?: string;
|
|
33
|
+
/**
|
|
34
|
+
* Drizzle DB accessor from the template's server/db/index.ts. Required —
|
|
35
|
+
* the framework-level share actions and access helpers call this to reach
|
|
36
|
+
* the right DB instance (schema is template-specific).
|
|
37
|
+
*/
|
|
38
|
+
getDb: () => any;
|
|
39
|
+
}
|
|
40
|
+
export declare function registerShareableResource(entry: ShareableResourceRegistration): void;
|
|
41
|
+
export declare function getShareableResource(type: string): ShareableResourceRegistration | undefined;
|
|
42
|
+
export declare function requireShareableResource(type: string): ShareableResourceRegistration;
|
|
43
|
+
export declare function listShareableResources(): ShareableResourceRegistration[];
|
|
44
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/sharing/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,WAAW,6BAA6B;IAC5C,iFAAiF;IACjF,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,aAAa,EAAE,GAAG,CAAC;IACnB,qDAAqD;IACrD,WAAW,EAAE,GAAG,CAAC;IACjB,+DAA+D;IAC/D,WAAW,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,KAAK,EAAE,MAAM,GAAG,CAAC;CAClB;AAuBD,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,6BAA6B,GACnC,IAAI,CAEN;AAED,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,GACX,6BAA6B,GAAG,SAAS,CAE3C;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,GACX,6BAA6B,CAS/B;AAED,wBAAgB,sBAAsB,IAAI,6BAA6B,EAAE,CAExE"}
|
|
@@ -0,0 +1,54 @@
|
|
|
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
|
+
// Stash the registry on globalThis so it survives SSR bundle duplication.
|
|
20
|
+
// Vite SSR's `noExternal: /^(?!node:)/` policy means @agent-native/core gets
|
|
21
|
+
// inlined into every server bundle that imports it — and each bundle gets its
|
|
22
|
+
// own module-level state. A plain `new Map()` here would create one Map per
|
|
23
|
+
// bundle, so the template's `registerShareableResource()` (called from the
|
|
24
|
+
// Nitro plugin graph) wouldn't be visible to the framework's auto-mounted
|
|
25
|
+
// share-resource action (loaded via `import("../sharing/actions/...js")` in a
|
|
26
|
+
// different module instance). Using globalThis collapses them back to one Map.
|
|
27
|
+
const REGISTRY_KEY = "__agentNativeShareableResources__";
|
|
28
|
+
const globalRegistry = globalThis;
|
|
29
|
+
function getRegistry() {
|
|
30
|
+
let r = globalRegistry[REGISTRY_KEY];
|
|
31
|
+
if (!r) {
|
|
32
|
+
r = new Map();
|
|
33
|
+
globalRegistry[REGISTRY_KEY] = r;
|
|
34
|
+
}
|
|
35
|
+
return r;
|
|
36
|
+
}
|
|
37
|
+
export function registerShareableResource(entry) {
|
|
38
|
+
getRegistry().set(entry.type, entry);
|
|
39
|
+
}
|
|
40
|
+
export function getShareableResource(type) {
|
|
41
|
+
return getRegistry().get(type);
|
|
42
|
+
}
|
|
43
|
+
export function requireShareableResource(type) {
|
|
44
|
+
const reg = getRegistry();
|
|
45
|
+
const entry = reg.get(type);
|
|
46
|
+
if (!entry) {
|
|
47
|
+
throw new Error(`Unknown shareable resource type: "${type}". Did you forget registerShareableResource()?`);
|
|
48
|
+
}
|
|
49
|
+
return entry;
|
|
50
|
+
}
|
|
51
|
+
export function listShareableResources() {
|
|
52
|
+
return Array.from(getRegistry().values());
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/sharing/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAwBH,0EAA0E;AAC1E,6EAA6E;AAC7E,8EAA8E;AAC9E,4EAA4E;AAC5E,2EAA2E;AAC3E,0EAA0E;AAC1E,8EAA8E;AAC9E,+EAA+E;AAC/E,MAAM,YAAY,GAAG,mCAAmC,CAAC;AAEzD,MAAM,cAAc,GAClB,UAAiB,CAAC;AACpB,SAAS,WAAW;IAClB,IAAI,CAAC,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;IACrC,IAAI,CAAC,CAAC,EAAE,CAAC;QACP,CAAC,GAAG,IAAI,GAAG,EAAyC,CAAC;QACrD,cAAc,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,KAAoC;IAEpC,WAAW,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,IAAY;IAEZ,OAAO,WAAW,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,wBAAwB,CACtC,IAAY;IAEZ,MAAM,GAAG,GAAG,WAAW,EAAE,CAAC;IAC1B,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACb,qCAAqC,IAAI,gDAAgD,CAC1F,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema factories for sharing/ownership.
|
|
3
|
+
*
|
|
4
|
+
* Templates make a resource table "ownable" by spreading `ownableColumns()` into
|
|
5
|
+
* the table definition and declaring a companion shares table via
|
|
6
|
+
* `createSharesTable()`. The shares table carries per-principal grants; the
|
|
7
|
+
* parent table's `visibility` column is the coarse default (private / org /
|
|
8
|
+
* public).
|
|
9
|
+
*
|
|
10
|
+
* import { table, text, ownableColumns, createSharesTable } from
|
|
11
|
+
* "@agent-native/core/db/schema";
|
|
12
|
+
*
|
|
13
|
+
* export const decks = table("decks", {
|
|
14
|
+
* id: text("id").primaryKey(),
|
|
15
|
+
* title: text("title").notNull(),
|
|
16
|
+
* data: text("data").notNull(),
|
|
17
|
+
* ...ownableColumns(),
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* export const deckShares = createSharesTable("deck_shares");
|
|
21
|
+
*
|
|
22
|
+
* The share row `role` supports `viewer | editor | admin`. `admin` is a
|
|
23
|
+
* share-level capability — it lets non-owners manage shares. The single
|
|
24
|
+
* `owner_email` column on the resource remains the ground truth for ownership.
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Columns any ownable resource should include. Spread into the table definition.
|
|
28
|
+
*
|
|
29
|
+
* - `ownerEmail` — the creator. Auto-filled by write actions from the request context.
|
|
30
|
+
* - `orgId` — owner's active org at creation time. Used for `visibility = 'org'` checks.
|
|
31
|
+
* - `visibility`— coarse default: `'private' | 'org' | 'public'`. Default `'private'`.
|
|
32
|
+
*/
|
|
33
|
+
export declare function ownableColumns(): {
|
|
34
|
+
ownerEmail: import("drizzle-orm").HasDefault<import("drizzle-orm").NotNull<import("drizzle-orm/sqlite-core").SQLiteTextBuilderInitial<"owner_email", [string, ...string[]], number>>>;
|
|
35
|
+
orgId: import("drizzle-orm/sqlite-core").SQLiteTextBuilderInitial<"org_id", [string, ...string[]], number>;
|
|
36
|
+
visibility: import("drizzle-orm").HasDefault<import("drizzle-orm").NotNull<import("drizzle-orm/sqlite-core").SQLiteTextBuilderInitial<"visibility", ["private", "org", "public"], number>>>;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Create a companion shares table for an ownable resource. Call this right
|
|
40
|
+
* after defining the parent table.
|
|
41
|
+
*
|
|
42
|
+
* Columns:
|
|
43
|
+
* - `id` — share row id (generated by the share action)
|
|
44
|
+
* - `resourceId` — id of the parent resource
|
|
45
|
+
* - `principalType` — `'user' | 'org'`
|
|
46
|
+
* - `principalId` — email (for user) or org id (for org)
|
|
47
|
+
* - `role` — `'viewer' | 'editor' | 'admin'`
|
|
48
|
+
* - `createdBy` — email of the user who created the share
|
|
49
|
+
* - `createdAt` — ISO timestamp
|
|
50
|
+
*
|
|
51
|
+
* Uniqueness across `(resource_id, principal_type, principal_id)` is enforced
|
|
52
|
+
* at the action layer via upsert-style logic. A composite DB-level unique
|
|
53
|
+
* index can be added per template if desired — omitted here to keep the
|
|
54
|
+
* factory dialect-agnostic.
|
|
55
|
+
*/
|
|
56
|
+
export declare function createSharesTable(tableName: string): import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
|
|
57
|
+
name: string;
|
|
58
|
+
schema: undefined;
|
|
59
|
+
columns: {
|
|
60
|
+
id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
61
|
+
name: "id";
|
|
62
|
+
tableName: string;
|
|
63
|
+
dataType: "string";
|
|
64
|
+
columnType: "SQLiteText";
|
|
65
|
+
data: string;
|
|
66
|
+
driverParam: string;
|
|
67
|
+
notNull: true;
|
|
68
|
+
hasDefault: false;
|
|
69
|
+
isPrimaryKey: true;
|
|
70
|
+
isAutoincrement: false;
|
|
71
|
+
hasRuntimeDefault: false;
|
|
72
|
+
enumValues: [string, ...string[]];
|
|
73
|
+
baseColumn: never;
|
|
74
|
+
identity: undefined;
|
|
75
|
+
generated: undefined;
|
|
76
|
+
}, {}, {
|
|
77
|
+
length: number;
|
|
78
|
+
}>;
|
|
79
|
+
resourceId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
80
|
+
name: "resource_id";
|
|
81
|
+
tableName: string;
|
|
82
|
+
dataType: "string";
|
|
83
|
+
columnType: "SQLiteText";
|
|
84
|
+
data: string;
|
|
85
|
+
driverParam: string;
|
|
86
|
+
notNull: true;
|
|
87
|
+
hasDefault: false;
|
|
88
|
+
isPrimaryKey: false;
|
|
89
|
+
isAutoincrement: false;
|
|
90
|
+
hasRuntimeDefault: false;
|
|
91
|
+
enumValues: [string, ...string[]];
|
|
92
|
+
baseColumn: never;
|
|
93
|
+
identity: undefined;
|
|
94
|
+
generated: undefined;
|
|
95
|
+
}, {}, {
|
|
96
|
+
length: number;
|
|
97
|
+
}>;
|
|
98
|
+
principalType: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
99
|
+
name: "principal_type";
|
|
100
|
+
tableName: string;
|
|
101
|
+
dataType: "string";
|
|
102
|
+
columnType: "SQLiteText";
|
|
103
|
+
data: "user" | "org";
|
|
104
|
+
driverParam: string;
|
|
105
|
+
notNull: true;
|
|
106
|
+
hasDefault: false;
|
|
107
|
+
isPrimaryKey: false;
|
|
108
|
+
isAutoincrement: false;
|
|
109
|
+
hasRuntimeDefault: false;
|
|
110
|
+
enumValues: ["user", "org"];
|
|
111
|
+
baseColumn: never;
|
|
112
|
+
identity: undefined;
|
|
113
|
+
generated: undefined;
|
|
114
|
+
}, {}, {
|
|
115
|
+
length: number;
|
|
116
|
+
}>;
|
|
117
|
+
principalId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
118
|
+
name: "principal_id";
|
|
119
|
+
tableName: string;
|
|
120
|
+
dataType: "string";
|
|
121
|
+
columnType: "SQLiteText";
|
|
122
|
+
data: string;
|
|
123
|
+
driverParam: string;
|
|
124
|
+
notNull: true;
|
|
125
|
+
hasDefault: false;
|
|
126
|
+
isPrimaryKey: false;
|
|
127
|
+
isAutoincrement: false;
|
|
128
|
+
hasRuntimeDefault: false;
|
|
129
|
+
enumValues: [string, ...string[]];
|
|
130
|
+
baseColumn: never;
|
|
131
|
+
identity: undefined;
|
|
132
|
+
generated: undefined;
|
|
133
|
+
}, {}, {
|
|
134
|
+
length: number;
|
|
135
|
+
}>;
|
|
136
|
+
role: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
137
|
+
name: "role";
|
|
138
|
+
tableName: string;
|
|
139
|
+
dataType: "string";
|
|
140
|
+
columnType: "SQLiteText";
|
|
141
|
+
data: "admin" | "viewer" | "editor";
|
|
142
|
+
driverParam: string;
|
|
143
|
+
notNull: true;
|
|
144
|
+
hasDefault: true;
|
|
145
|
+
isPrimaryKey: false;
|
|
146
|
+
isAutoincrement: false;
|
|
147
|
+
hasRuntimeDefault: false;
|
|
148
|
+
enumValues: ["viewer", "editor", "admin"];
|
|
149
|
+
baseColumn: never;
|
|
150
|
+
identity: undefined;
|
|
151
|
+
generated: undefined;
|
|
152
|
+
}, {}, {
|
|
153
|
+
length: number;
|
|
154
|
+
}>;
|
|
155
|
+
createdBy: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
156
|
+
name: "created_by";
|
|
157
|
+
tableName: string;
|
|
158
|
+
dataType: "string";
|
|
159
|
+
columnType: "SQLiteText";
|
|
160
|
+
data: string;
|
|
161
|
+
driverParam: string;
|
|
162
|
+
notNull: true;
|
|
163
|
+
hasDefault: false;
|
|
164
|
+
isPrimaryKey: false;
|
|
165
|
+
isAutoincrement: false;
|
|
166
|
+
hasRuntimeDefault: false;
|
|
167
|
+
enumValues: [string, ...string[]];
|
|
168
|
+
baseColumn: never;
|
|
169
|
+
identity: undefined;
|
|
170
|
+
generated: undefined;
|
|
171
|
+
}, {}, {
|
|
172
|
+
length: number;
|
|
173
|
+
}>;
|
|
174
|
+
createdAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
|
|
175
|
+
name: "created_at";
|
|
176
|
+
tableName: string;
|
|
177
|
+
dataType: "string";
|
|
178
|
+
columnType: "SQLiteText";
|
|
179
|
+
data: string;
|
|
180
|
+
driverParam: string;
|
|
181
|
+
notNull: true;
|
|
182
|
+
hasDefault: true;
|
|
183
|
+
isPrimaryKey: false;
|
|
184
|
+
isAutoincrement: false;
|
|
185
|
+
hasRuntimeDefault: false;
|
|
186
|
+
enumValues: [string, ...string[]];
|
|
187
|
+
baseColumn: never;
|
|
188
|
+
identity: undefined;
|
|
189
|
+
generated: undefined;
|
|
190
|
+
}, {}, {
|
|
191
|
+
length: number;
|
|
192
|
+
}>;
|
|
193
|
+
};
|
|
194
|
+
dialect: "sqlite";
|
|
195
|
+
}>;
|
|
196
|
+
export type Visibility = "private" | "org" | "public";
|
|
197
|
+
export type ShareRole = "viewer" | "editor" | "admin";
|
|
198
|
+
export type PrincipalType = "user" | "org";
|
|
199
|
+
/** Role precedence — higher number = stronger capability. */
|
|
200
|
+
export declare const ROLE_RANK: Record<ShareRole | "owner", number>;
|
|
201
|
+
export declare function roleSatisfies(actual: ShareRole | "owner", minimum: ShareRole | "owner"): boolean;
|
|
202
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/sharing/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH;;;;;;GAMG;AACH,wBAAgB,cAAc;;;;EAU7B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAclD;AAED,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,KAAK,GAAG,QAAQ,CAAC;AACtD,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AACtD,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,KAAK,CAAC;AAE3C,6DAA6D;AAC7D,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,SAAS,GAAG,OAAO,EAAE,MAAM,CAKzD,CAAC;AAEF,wBAAgB,aAAa,CAC3B,MAAM,EAAE,SAAS,GAAG,OAAO,EAC3B,OAAO,EAAE,SAAS,GAAG,OAAO,GAC3B,OAAO,CAET"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema factories for sharing/ownership.
|
|
3
|
+
*
|
|
4
|
+
* Templates make a resource table "ownable" by spreading `ownableColumns()` into
|
|
5
|
+
* the table definition and declaring a companion shares table via
|
|
6
|
+
* `createSharesTable()`. The shares table carries per-principal grants; the
|
|
7
|
+
* parent table's `visibility` column is the coarse default (private / org /
|
|
8
|
+
* public).
|
|
9
|
+
*
|
|
10
|
+
* import { table, text, ownableColumns, createSharesTable } from
|
|
11
|
+
* "@agent-native/core/db/schema";
|
|
12
|
+
*
|
|
13
|
+
* export const decks = table("decks", {
|
|
14
|
+
* id: text("id").primaryKey(),
|
|
15
|
+
* title: text("title").notNull(),
|
|
16
|
+
* data: text("data").notNull(),
|
|
17
|
+
* ...ownableColumns(),
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* export const deckShares = createSharesTable("deck_shares");
|
|
21
|
+
*
|
|
22
|
+
* The share row `role` supports `viewer | editor | admin`. `admin` is a
|
|
23
|
+
* share-level capability — it lets non-owners manage shares. The single
|
|
24
|
+
* `owner_email` column on the resource remains the ground truth for ownership.
|
|
25
|
+
*/
|
|
26
|
+
import { table, text, now } from "../db/schema.js";
|
|
27
|
+
/**
|
|
28
|
+
* Columns any ownable resource should include. Spread into the table definition.
|
|
29
|
+
*
|
|
30
|
+
* - `ownerEmail` — the creator. Auto-filled by write actions from the request context.
|
|
31
|
+
* - `orgId` — owner's active org at creation time. Used for `visibility = 'org'` checks.
|
|
32
|
+
* - `visibility`— coarse default: `'private' | 'org' | 'public'`. Default `'private'`.
|
|
33
|
+
*/
|
|
34
|
+
export function ownableColumns() {
|
|
35
|
+
return {
|
|
36
|
+
ownerEmail: text("owner_email").notNull().default("local@localhost"),
|
|
37
|
+
orgId: text("org_id"),
|
|
38
|
+
visibility: text("visibility", {
|
|
39
|
+
enum: ["private", "org", "public"],
|
|
40
|
+
})
|
|
41
|
+
.notNull()
|
|
42
|
+
.default("private"),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Create a companion shares table for an ownable resource. Call this right
|
|
47
|
+
* after defining the parent table.
|
|
48
|
+
*
|
|
49
|
+
* Columns:
|
|
50
|
+
* - `id` — share row id (generated by the share action)
|
|
51
|
+
* - `resourceId` — id of the parent resource
|
|
52
|
+
* - `principalType` — `'user' | 'org'`
|
|
53
|
+
* - `principalId` — email (for user) or org id (for org)
|
|
54
|
+
* - `role` — `'viewer' | 'editor' | 'admin'`
|
|
55
|
+
* - `createdBy` — email of the user who created the share
|
|
56
|
+
* - `createdAt` — ISO timestamp
|
|
57
|
+
*
|
|
58
|
+
* Uniqueness across `(resource_id, principal_type, principal_id)` is enforced
|
|
59
|
+
* at the action layer via upsert-style logic. A composite DB-level unique
|
|
60
|
+
* index can be added per template if desired — omitted here to keep the
|
|
61
|
+
* factory dialect-agnostic.
|
|
62
|
+
*/
|
|
63
|
+
export function createSharesTable(tableName) {
|
|
64
|
+
return table(tableName, {
|
|
65
|
+
id: text("id").primaryKey(),
|
|
66
|
+
resourceId: text("resource_id").notNull(),
|
|
67
|
+
principalType: text("principal_type", {
|
|
68
|
+
enum: ["user", "org"],
|
|
69
|
+
}).notNull(),
|
|
70
|
+
principalId: text("principal_id").notNull(),
|
|
71
|
+
role: text("role", { enum: ["viewer", "editor", "admin"] })
|
|
72
|
+
.notNull()
|
|
73
|
+
.default("viewer"),
|
|
74
|
+
createdBy: text("created_by").notNull(),
|
|
75
|
+
createdAt: text("created_at").notNull().default(now()),
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
/** Role precedence — higher number = stronger capability. */
|
|
79
|
+
export const ROLE_RANK = {
|
|
80
|
+
viewer: 1,
|
|
81
|
+
editor: 2,
|
|
82
|
+
admin: 3,
|
|
83
|
+
owner: 4,
|
|
84
|
+
};
|
|
85
|
+
export function roleSatisfies(actual, minimum) {
|
|
86
|
+
return ROLE_RANK[actual] >= ROLE_RANK[minimum];
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/sharing/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAEnD;;;;;;GAMG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO;QACL,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,iBAAiB,CAAC;QACpE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC;QACrB,UAAU,EAAE,IAAI,CAAC,YAAY,EAAE;YAC7B,IAAI,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,CAAC;SACnC,CAAC;aACC,OAAO,EAAE;aACT,OAAO,CAAC,SAAS,CAAC;KACtB,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAAiB;IACjD,OAAO,KAAK,CAAC,SAAS,EAAE;QACtB,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE;QAC3B,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,OAAO,EAAE;QACzC,aAAa,EAAE,IAAI,CAAC,gBAAgB,EAAE;YACpC,IAAI,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC;SACtB,CAAC,CAAC,OAAO,EAAE;QACZ,WAAW,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE;QAC3C,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,CAAC;aACxD,OAAO,EAAE;aACT,OAAO,CAAC,QAAQ,CAAC;QACpB,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE;QACvC,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;KACvD,CAAC,CAAC;AACL,CAAC;AAMD,6DAA6D;AAC7D,MAAM,CAAC,MAAM,SAAS,GAAwC;IAC5D,MAAM,EAAE,CAAC;IACT,MAAM,EAAE,CAAC;IACT,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;CACT,CAAC;AAEF,MAAM,UAAU,aAAa,CAC3B,MAA2B,EAC3B,OAA4B;IAE5B,OAAO,SAAS,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC,OAAO,CAAC,CAAC;AACjD,CAAC"}
|