Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 27 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -515,11 +515,11 @@ may call — list, aliases / versions, a call by hand, a sample envelope for a
local run, and the last runs of a trigger or task. The five function hooks
need `@norbix.ai/ts` 4.19.0.

| Area | Hooks | Cache tag |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| Module switch | `useEnableCodeModuleMutation`, `useDisableCodeModuleMutation` | invalidates `Account`, `Projects`, `Code` |
| Area | Hooks | Cache tag |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| Module switch | `useEnableCodeModuleMutation`, `useDisableCodeModuleMutation` | invalidates `Account`, `Projects`, `Code` |
| Integrations | `useGetCodeIntegrationsQuery`, `useGetCodeIntegrationQuery`, `useSaveCodeIntegrationMutation`, `useDeleteCodeIntegrationMutation`, `useEnableCodeIntegrationMutation`, `useDisableCodeIntegrationMutation`, `useTestCodeIntegrationMutation` | provides / invalidates `CodeIntegrations/LIST` and `CodeIntegrations/<id>`; `test` touches nothing |
| Cloud functions | `useGetCodeFunctionsQuery`, `useGetCodeFunctionQualifiersQuery`, `useGetCodeFunctionEventSampleQuery`, `useGetCodeFunctionRunsQuery`, `useInvokeCodeFunctionMutation` | provides `CodeFunctions/LIST`, `CodeFunctions/SAMPLE`, `CodeFunctions/RUNS`; `invoke` touches nothing |
| Cloud functions | `useGetCodeFunctionsQuery`, `useGetCodeFunctionQualifiersQuery`, `useGetCodeFunctionEventSampleQuery`, `useGetCodeFunctionRunsQuery`, `useInvokeCodeFunctionMutation` | provides `CodeFunctions/LIST`, `CodeFunctions/SAMPLE`, `CodeFunctions/RUNS`; `invoke` touches nothing |

```tsx
const integrationId = 'int_6rBACnEaxQ0x1jTiHtAuWV';
Expand All @@ -544,6 +544,29 @@ The function side — parsing the envelope your function receives — is
`parseFunctionEvent` in the core SDK (`docs/code-functions.md`), not a hook.
Full method reference: the core SDK's `docs/hub/code.md`.

## Code — marketplace

The marketplace methods of `hub.code` have hooks too, 1:1 with
`norbix.hub.code` (gateway contract `Code.Marketplace.md` §14): the catalog of
listings, the installed connections (`int_…`) with their secrets, token
mappings and validation test, the vendor function catalog, and the functions
added on a connection (`func_…`). Every tag is of type `CodeMarketplace`.

| Area | Hooks | Cache tag (`CodeMarketplace/…`) |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------- |
| Catalog | `useGetMarketplaceListingsQuery`, `useGetMarketplaceListingQuery`, `useGetMarketplaceListingFunctionTokensQuery` | provides `LISTINGS` |
| Connections | `useGetMarketplaceIntegrationsQuery`, `useGetMarketplaceIntegrationQuery`, `useSaveMarketplaceIntegrationMutation`, `useDeleteMarketplaceIntegrationMutation`, `useEnableMarketplaceIntegrationMutation`, `useDisableMarketplaceIntegrationMutation`, `useReplaceMarketplaceIntegrationSecretsMutation`, `useRevealMarketplaceIntegrationSecretsMutation`, `useSetMarketplaceIntegrationTokenMappingsMutation`, `useTestMarketplaceIntegrationMutation`, `useGetMarketplaceFunctionCatalogQuery` | `INTEGRATIONS`, `<integrationViewId>`, `CATALOG:<integrationViewId>`; reveal touches nothing |
| Functions | `useGetMarketplaceFunctionsQuery`, `useGetMarketplaceFunctionQuery`, `useSaveMarketplaceFunctionMutation`, `useDeleteMarketplaceFunctionMutation`, `useEnableMarketplaceFunctionMutation`, `useDisableMarketplaceFunctionMutation`, `useGetMarketplaceFunctionTokensQuery`, `useInvokeMarketplaceFunctionMutation`, `useGetMarketplaceFunctionRunsQuery` | `FUNCTIONS:<integrationViewId>`, `<functionViewId>`, `RUNS`; invoke touches nothing |

Revealing secrets is a mutation on purpose: a query would keep the clear values
in the store's cache.

```tsx
const { data: listings } = useGetMarketplaceListingsQuery({ search: 'slack' });
const [invoke] = useInvokeMarketplaceFunctionMutation();
await invoke({ functionViewId: 'func_4hT2b9QkLm3XcT1yRfGh7a', payload: { text: 'Order shipped' } });
```

## Working with terms

A **taxonomy** is a named tree of **terms** (labels). A term can have one parent (a clean hierarchy) or several parents (the same item under many categories). There is one read hook per scenario — pick the one that matches what you want:
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
"@commitlint/cli": "^21.2.2",
"@commitlint/config-conventional": "^21.2.2",
"@eslint/js": "^10.0.1",
"@norbix.ai/ts": "^4.20.0",
"@norbix.ai/ts": "^4.21.0",
"@reduxjs/toolkit": "^2.12.0",
"@semantic-release/commit-analyzer": "^13.0.1",
"@semantic-release/github": "^12.0.9",
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/hub/code.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type { Arg, Result } from '../types.js';
* Azure Functions, Google Cloud Functions credentials) and the cloud functions
* they may call: list, aliases / versions, a call by hand, a sample envelope
* and the last runs of a trigger or task. The marketplace half of `hub.code`
* is not wrapped here.
* is in `./marketplace.ts`.
*
* Tag conventions:
* - `Code` — module state
Expand Down
183 changes: 183 additions & 0 deletions src/hooks/hub/marketplace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
import type { Norbix } from '@norbix.ai/ts';

import type { Builder } from '../index.js';
import type { Arg, Result } from '../types.js';

/**
* `hub.code` marketplace — the catalog of listings, the installed connections
* (`int_…`), their secrets, token mappings and validation test, the vendor
* function catalog, and the functions added on a connection (`func_…`).
* 1:1 with the marketplace methods of `norbix.hub.code` (gateway contract
* `Code.Marketplace.md` §14).
*
* Tag conventions (all type `CodeMarketplace`):
* - `LISTINGS` — the catalog, one listing, a listing's function tokens
* - `INTEGRATIONS` — the connection list
* - `<integrationViewId>` — one connection (secrets, token mappings and the
* last validation steps live on it)
* - `CATALOG:<integrationId>` — the vendor functions a connection offers
* - `FUNCTIONS:<integrationId>`— the functions added on a connection
* - `<functionViewId>` — one function and its tokens
* - `RUNS` — the last runs of a trigger or task (core SDK 4.21.0)
*
* Revealing secrets is a mutation on purpose: a query would keep the clear
* values in the store's cache.
*/
export const hubCodeMarketplace = (b: Builder) => {
type HC = Norbix['hub']['code'];
type Fn<K extends keyof HC> = HC[K] extends (...a: never[]) => unknown ? HC[K] : never;

type GetListings = Fn<'getMarketplaceListings'>;
type GetListing = Fn<'getMarketplaceListing'>;
type GetListingFunctionTokens = Fn<'getMarketplaceListingFunctionTokens'>;
type GetIntegrations = Fn<'getMarketplaceIntegrations'>;
type GetIntegration = Fn<'getMarketplaceIntegration'>;
type SaveIntegration = Fn<'saveMarketplaceIntegration'>;
type DeleteIntegration = Fn<'deleteMarketplaceIntegration'>;
type EnableIntegration = Fn<'enableMarketplaceIntegration'>;
type DisableIntegration = Fn<'disableMarketplaceIntegration'>;
type ReplaceSecrets = Fn<'replaceMarketplaceIntegrationSecrets'>;
type RevealSecrets = Fn<'revealMarketplaceIntegrationSecrets'>;
type SetTokenMappings = Fn<'setMarketplaceIntegrationTokenMappings'>;
type TestIntegration = Fn<'testMarketplaceIntegration'>;
type GetCatalog = Fn<'getMarketplaceFunctionCatalog'>;
type GetFunctions = Fn<'getMarketplaceFunctions'>;
type GetFunction = Fn<'getMarketplaceFunction'>;
type SaveFunction = Fn<'saveMarketplaceFunction'>;
type DeleteFunction = Fn<'deleteMarketplaceFunction'>;
type EnableFunction = Fn<'enableMarketplaceFunction'>;
type DisableFunction = Fn<'disableMarketplaceFunction'>;
type GetFunctionTokens = Fn<'getMarketplaceFunctionTokens'>;
type InvokeFunction = Fn<'invokeMarketplaceFunction'>;
type GetRuns = Fn<'getMarketplaceFunctionRuns'>;

const callHC = (norbix: Norbix) => norbix.hub.code as HC;

const T = 'CodeMarketplace' as const;
const integrationId = (arg: unknown) =>
(arg as { integrationViewId?: string })?.integrationViewId ??
(arg as { IntegrationViewId?: string })?.IntegrationViewId ??
'CURRENT';
const functionId = (arg: unknown) =>
(arg as { functionViewId?: string })?.functionViewId ??
(arg as { FunctionViewId?: string })?.FunctionViewId ??
'CURRENT';
const listings = [{ type: T, id: 'LISTINGS' }];
const integration = (arg: unknown) => [
{ type: T, id: 'INTEGRATIONS' },
{ type: T, id: integrationId(arg) },
];
const functions = (arg: unknown) => [
{ type: T, id: `FUNCTIONS:${integrationId(arg)}` },
{ type: T, id: functionId(arg) },
];

return {
// ---- Catalog ----
getMarketplaceListings: b.query<Result<GetListings>, Arg<GetListings>>({
query: (args) => (norbix) => callHC(norbix).getMarketplaceListings(args),
providesTags: listings,
}),
getMarketplaceListing: b.query<Result<GetListing>, Arg<GetListing>>({
query: (args) => (norbix) => callHC(norbix).getMarketplaceListing(args),
providesTags: listings,
}),
getMarketplaceListingFunctionTokens: b.query<
Result<GetListingFunctionTokens>,
Arg<GetListingFunctionTokens>
>({
query: (args) => (norbix) => callHC(norbix).getMarketplaceListingFunctionTokens(args),
providesTags: listings,
}),

// ---- Connections ----
getMarketplaceIntegrations: b.query<Result<GetIntegrations>, Arg<GetIntegrations>>({
query: (args) => (norbix) => callHC(norbix).getMarketplaceIntegrations(args),
providesTags: [{ type: T, id: 'INTEGRATIONS' }],
}),
getMarketplaceIntegration: b.query<Result<GetIntegration>, Arg<GetIntegration>>({
query: (args) => (norbix) => callHC(norbix).getMarketplaceIntegration(args),
providesTags: (_res, _err, arg) => [{ type: T, id: integrationId(arg) }],
}),
saveMarketplaceIntegration: b.mutation<Result<SaveIntegration>, Arg<SaveIntegration>>({
query: (args) => (norbix) => callHC(norbix).saveMarketplaceIntegration(args),
invalidatesTags: [{ type: T, id: 'INTEGRATIONS' }],
}),
deleteMarketplaceIntegration: b.mutation<Result<DeleteIntegration>, Arg<DeleteIntegration>>({
query: (args) => (norbix) => callHC(norbix).deleteMarketplaceIntegration(args),
invalidatesTags: (_res, _err, arg) => [
...integration(arg),
{ type: T, id: `FUNCTIONS:${integrationId(arg)}` },
],
}),
enableMarketplaceIntegration: b.mutation<Result<EnableIntegration>, Arg<EnableIntegration>>({
query: (args) => (norbix) => callHC(norbix).enableMarketplaceIntegration(args),
invalidatesTags: (_res, _err, arg) => integration(arg),
}),
disableMarketplaceIntegration: b.mutation<Result<DisableIntegration>, Arg<DisableIntegration>>({
query: (args) => (norbix) => callHC(norbix).disableMarketplaceIntegration(args),
invalidatesTags: (_res, _err, arg) => integration(arg),
}),
replaceMarketplaceIntegrationSecrets: b.mutation<Result<ReplaceSecrets>, Arg<ReplaceSecrets>>({
query: (args) => (norbix) => callHC(norbix).replaceMarketplaceIntegrationSecrets(args),
invalidatesTags: (_res, _err, arg) => [{ type: T, id: integrationId(arg) }],
}),
revealMarketplaceIntegrationSecrets: b.mutation<Result<RevealSecrets>, Arg<RevealSecrets>>({
query: (args) => (norbix) => callHC(norbix).revealMarketplaceIntegrationSecrets(args),
}),
setMarketplaceIntegrationTokenMappings: b.mutation<
Result<SetTokenMappings>,
Arg<SetTokenMappings>
>({
query: (args) => (norbix) => callHC(norbix).setMarketplaceIntegrationTokenMappings(args),
invalidatesTags: (_res, _err, arg) => [{ type: T, id: integrationId(arg) }],
}),
testMarketplaceIntegration: b.mutation<Result<TestIntegration>, Arg<TestIntegration>>({
query: (args) => (norbix) => callHC(norbix).testMarketplaceIntegration(args),
invalidatesTags: (_res, _err, arg) => [{ type: T, id: integrationId(arg) }],
}),
getMarketplaceFunctionCatalog: b.query<Result<GetCatalog>, Arg<GetCatalog>>({
query: (args) => (norbix) => callHC(norbix).getMarketplaceFunctionCatalog(args),
providesTags: (_res, _err, arg) => [{ type: T, id: `CATALOG:${integrationId(arg)}` }],
}),

// ---- Functions on a connection ----
getMarketplaceFunctions: b.query<Result<GetFunctions>, Arg<GetFunctions>>({
query: (args) => (norbix) => callHC(norbix).getMarketplaceFunctions(args),
providesTags: (_res, _err, arg) => [{ type: T, id: `FUNCTIONS:${integrationId(arg)}` }],
}),
getMarketplaceFunction: b.query<Result<GetFunction>, Arg<GetFunction>>({
query: (args) => (norbix) => callHC(norbix).getMarketplaceFunction(args),
providesTags: (_res, _err, arg) => [{ type: T, id: functionId(arg) }],
}),
saveMarketplaceFunction: b.mutation<Result<SaveFunction>, Arg<SaveFunction>>({
query: (args) => (norbix) => callHC(norbix).saveMarketplaceFunction(args),
invalidatesTags: (_res, _err, arg) => functions(arg),
}),
deleteMarketplaceFunction: b.mutation<Result<DeleteFunction>, Arg<DeleteFunction>>({
query: (args) => (norbix) => callHC(norbix).deleteMarketplaceFunction(args),
invalidatesTags: (_res, _err, arg) => functions(arg),
}),
enableMarketplaceFunction: b.mutation<Result<EnableFunction>, Arg<EnableFunction>>({
query: (args) => (norbix) => callHC(norbix).enableMarketplaceFunction(args),
invalidatesTags: (_res, _err, arg) => functions(arg),
}),
disableMarketplaceFunction: b.mutation<Result<DisableFunction>, Arg<DisableFunction>>({
query: (args) => (norbix) => callHC(norbix).disableMarketplaceFunction(args),
invalidatesTags: (_res, _err, arg) => functions(arg),
}),
getMarketplaceFunctionTokens: b.query<Result<GetFunctionTokens>, Arg<GetFunctionTokens>>({
query: (args) => (norbix) => callHC(norbix).getMarketplaceFunctionTokens(args),
providesTags: (_res, _err, arg) => [{ type: T, id: functionId(arg) }],
}),
invokeMarketplaceFunction: b.mutation<Result<InvokeFunction>, Arg<InvokeFunction>>({
query: (args) => (norbix) => callHC(norbix).invokeMarketplaceFunction(args),
}),

// ---- Last runs (core SDK 4.21.0) ----
getMarketplaceFunctionRuns: b.query<Result<GetRuns>, Arg<GetRuns>>({
query: (args) => (norbix) => callHC(norbix).getMarketplaceFunctionRuns(args),
providesTags: [{ type: T, id: 'RUNS' }],
}),
};
};
2 changes: 2 additions & 0 deletions src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { hubEmail } from './hub/email.js';
import { hubEnvironments } from './hub/environments.js';
import { hubFiles } from './hub/files.js';
import { hubLogs } from './hub/logs.js';
import { hubCodeMarketplace } from './hub/marketplace.js';
import { hubMembership } from './hub/membership.js';
import { hubNotifications } from './hub/notifications.js';
import { hubPayments } from './hub/payments.js';
Expand Down Expand Up @@ -145,6 +146,7 @@ export function buildEndpoints(builder: Builder) {
...hubAi(builder),
...hubApikeys(builder),
...hubCode(builder),
...hubCodeMarketplace(builder),
...hubMembership(builder),
...hubDatabase(builder),
...hubFiles(builder),
Expand Down
Loading