@voyant-travel/apps 0.9.1 → 0.10.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/api-runtime.js +14 -1
- package/dist/api-runtime.test.js +72 -5
- package/dist/compiler.test.js +11 -0
- package/dist/contracts.d.ts +2 -0
- package/dist/contracts.js +3 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/installation-routes.test.js +35 -1
- package/dist/installation-service.d.ts +1 -1
- package/dist/marketplace-acquisition.d.ts +93 -0
- package/dist/marketplace-acquisition.js +410 -0
- package/dist/marketplace-acquisition.test.d.ts +1 -0
- package/dist/marketplace-acquisition.test.js +191 -0
- package/dist/oauth-redirect.d.ts +6 -0
- package/dist/oauth-redirect.js +8 -0
- package/dist/oauth-redirect.test.d.ts +1 -0
- package/dist/oauth-redirect.test.js +39 -0
- package/dist/oauth-service.js +2 -2
- package/dist/routes-openapi.d.ts +101 -0
- package/dist/routes-openapi.js +21 -0
- package/dist/routes.d.ts +3 -1
- package/dist/routes.js +52 -4
- package/dist/runtime-contributor.test.js +36 -1
- package/dist/runtime-port.d.ts +36 -0
- package/dist/runtime-port.js +20 -0
- package/dist/voyant.js +6 -2
- package/openapi/admin/apps.json +6 -0
- package/package.json +12 -7
package/dist/api-runtime.js
CHANGED
|
@@ -5,7 +5,7 @@ import { financeAppApiRuntimePort } from "@voyant-travel/finance-contracts/app-a
|
|
|
5
5
|
import { createAppsAppApiRoutes } from "./app-api-routes.js";
|
|
6
6
|
import { createAppOAuthService } from "./oauth-service.js";
|
|
7
7
|
import { createAppsAdminRoutes } from "./routes.js";
|
|
8
|
-
import { appsManagedAuthRuntimePort } from "./runtime-port.js";
|
|
8
|
+
import { appsManagedAuthRuntimePort, appsManagedMarketplaceRuntimePort, } from "./runtime-port.js";
|
|
9
9
|
export const createAppsApiModule = defineGraphRuntimeFactory(async ({ getPort, getPorts, graph, hasPort }) => {
|
|
10
10
|
const customFieldTargets = createCustomFieldTargetRegistry(graph.customFieldTargets ?? []);
|
|
11
11
|
const customFieldValueLifecycles = await getPorts(customFieldValueLifecycleRuntimePort);
|
|
@@ -16,6 +16,15 @@ export const createAppsApiModule = defineGraphRuntimeFactory(async ({ getPort, g
|
|
|
16
16
|
const managedAuth = hasPort(appsManagedAuthRuntimePort)
|
|
17
17
|
? await getPort(appsManagedAuthRuntimePort)
|
|
18
18
|
: undefined;
|
|
19
|
+
const managedMarketplace = hasPort(appsManagedMarketplaceRuntimePort)
|
|
20
|
+
? await getPort(appsManagedMarketplaceRuntimePort)
|
|
21
|
+
: undefined;
|
|
22
|
+
if (managedAuth &&
|
|
23
|
+
managedMarketplace &&
|
|
24
|
+
managedAuth.runtimeAudience !== managedMarketplace.deploymentId) {
|
|
25
|
+
throw new TypeError("apps.managed-auth runtimeAudience must match apps.managed-marketplace deploymentId.");
|
|
26
|
+
}
|
|
27
|
+
const deploymentId = managedAuth?.runtimeAudience ?? managedMarketplace?.deploymentId;
|
|
19
28
|
const oauthOptions = managedAuth
|
|
20
29
|
? {
|
|
21
30
|
accessCatalog: graph.accessCatalog,
|
|
@@ -29,6 +38,10 @@ export const createAppsApiModule = defineGraphRuntimeFactory(async ({ getPort, g
|
|
|
29
38
|
module: { name: "apps" },
|
|
30
39
|
adminRoutes: createAppsAdminRoutes({
|
|
31
40
|
eventCatalog: graph.eventCatalog,
|
|
41
|
+
...(deploymentId ? { deploymentId } : {}),
|
|
42
|
+
...(managedMarketplace
|
|
43
|
+
? { managedMarketplace: managedMarketplace.acquisitionResolver }
|
|
44
|
+
: {}),
|
|
32
45
|
...(oauthOptions ? { oauth: oauthOptions } : {}),
|
|
33
46
|
...(managedAuth
|
|
34
47
|
? {
|
package/dist/api-runtime.test.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
3
|
import { createAppsApiModule } from "./api-runtime.js";
|
|
3
|
-
import { appsManagedAuthRuntimePort } from "./runtime-port.js";
|
|
4
|
+
import { appsManagedAuthRuntimePort, appsManagedMarketplaceRuntimePort } from "./runtime-port.js";
|
|
4
5
|
const graph = {
|
|
5
6
|
providerSelections: {},
|
|
6
7
|
customFieldTargets: [],
|
|
@@ -10,18 +11,25 @@ const graph = {
|
|
|
10
11
|
references: [],
|
|
11
12
|
setupSteps: [],
|
|
12
13
|
};
|
|
13
|
-
function context(managedAuth) {
|
|
14
|
+
function context(managedAuth, managedMarketplace) {
|
|
14
15
|
return {
|
|
15
16
|
unitId: "@voyant-travel/apps",
|
|
16
17
|
projectConfig: {},
|
|
17
18
|
getUnitProjectConfig: () => undefined,
|
|
18
19
|
api: [],
|
|
19
20
|
graph,
|
|
20
|
-
runtimePorts:
|
|
21
|
-
|
|
21
|
+
runtimePorts: {
|
|
22
|
+
...(managedAuth ? { [appsManagedAuthRuntimePort.id]: managedAuth } : {}),
|
|
23
|
+
...(managedMarketplace ? { [appsManagedMarketplaceRuntimePort.id]: managedMarketplace } : {}),
|
|
24
|
+
},
|
|
25
|
+
hasPort: (port) => (port.id === appsManagedAuthRuntimePort.id && managedAuth !== undefined) ||
|
|
26
|
+
(port.id === appsManagedMarketplaceRuntimePort.id && managedMarketplace !== undefined),
|
|
22
27
|
getPort: async (port) => {
|
|
23
28
|
if (port.id === appsManagedAuthRuntimePort.id && managedAuth)
|
|
24
29
|
return managedAuth;
|
|
30
|
+
if (port.id === appsManagedMarketplaceRuntimePort.id && managedMarketplace) {
|
|
31
|
+
return managedMarketplace;
|
|
32
|
+
}
|
|
25
33
|
throw new Error(`missing ${port.id}`);
|
|
26
34
|
},
|
|
27
35
|
getPorts: async () => [],
|
|
@@ -55,4 +63,63 @@ describe("createAppsApiModule", () => {
|
|
|
55
63
|
token: "test-token",
|
|
56
64
|
})).resolves.toBeNull();
|
|
57
65
|
});
|
|
66
|
+
it("composes managed acquisition independently from OAuth authority", async () => {
|
|
67
|
+
const module = await createAppsApiModule(context(undefined, {
|
|
68
|
+
deploymentId: "deployment-marketplace-1",
|
|
69
|
+
acquisitionResolver: {
|
|
70
|
+
resolveAcquisitionIntent: async () => null,
|
|
71
|
+
createSetupHandoff: async () => ({
|
|
72
|
+
redirectUrl: "https://app.example.com/setup?code=opaque",
|
|
73
|
+
}),
|
|
74
|
+
notifyInstallationLifecycle: async () => undefined,
|
|
75
|
+
},
|
|
76
|
+
}));
|
|
77
|
+
expect(module.adminRoutes).toBeDefined();
|
|
78
|
+
expect(module.clientAuthenticated).toBeUndefined();
|
|
79
|
+
if (!module.adminRoutes)
|
|
80
|
+
throw new Error("apps admin routes are required");
|
|
81
|
+
const transaction = vi.fn(async () => {
|
|
82
|
+
throw new Error("installation transaction reached");
|
|
83
|
+
});
|
|
84
|
+
const app = new Hono();
|
|
85
|
+
app.onError((error, c) => c.json({ error: error.message }, 500));
|
|
86
|
+
app.use("*", async (c, next) => {
|
|
87
|
+
c.set("db", { transaction });
|
|
88
|
+
await next();
|
|
89
|
+
});
|
|
90
|
+
app.route("/", module.adminRoutes);
|
|
91
|
+
const response = await app.request("/install", {
|
|
92
|
+
method: "POST",
|
|
93
|
+
headers: { "content-type": "application/json" },
|
|
94
|
+
body: JSON.stringify({
|
|
95
|
+
appId: "app-1",
|
|
96
|
+
releaseId: "release-1",
|
|
97
|
+
actorId: "actor-1",
|
|
98
|
+
}),
|
|
99
|
+
});
|
|
100
|
+
expect(response.status).toBe(500);
|
|
101
|
+
await expect(response.json()).resolves.toEqual({
|
|
102
|
+
error: "installation transaction reached",
|
|
103
|
+
});
|
|
104
|
+
expect(transaction).toHaveBeenCalledOnce();
|
|
105
|
+
});
|
|
106
|
+
it("rejects conflicting managed deployment identities", async () => {
|
|
107
|
+
await expect(createAppsApiModule(context({
|
|
108
|
+
runtimeAudience: "deployment-auth-1",
|
|
109
|
+
installationAuthority: {
|
|
110
|
+
workloadEnvironmentId: "workload-environment-1",
|
|
111
|
+
resolveInstallationContract: async () => ({ contractGeneration: 1 }),
|
|
112
|
+
},
|
|
113
|
+
sessionTokenSigningSecret: "s".repeat(32),
|
|
114
|
+
}, {
|
|
115
|
+
deploymentId: "deployment-marketplace-2",
|
|
116
|
+
acquisitionResolver: {
|
|
117
|
+
resolveAcquisitionIntent: async () => null,
|
|
118
|
+
createSetupHandoff: async () => ({
|
|
119
|
+
redirectUrl: "https://app.example.com/setup?code=opaque",
|
|
120
|
+
}),
|
|
121
|
+
notifyInstallationLifecycle: async () => undefined,
|
|
122
|
+
},
|
|
123
|
+
}))).rejects.toThrow(/must match/);
|
|
124
|
+
});
|
|
58
125
|
});
|
package/dist/compiler.test.js
CHANGED
|
@@ -10,6 +10,17 @@ describe("app manifest compiler", () => {
|
|
|
10
10
|
});
|
|
11
11
|
expect(parsed.data.storesSecrets).toBe(true);
|
|
12
12
|
});
|
|
13
|
+
it("admits an explicit HTTPS managed lifecycle endpoint", () => {
|
|
14
|
+
const parsed = appManifestSchema.parse({
|
|
15
|
+
...validManifest,
|
|
16
|
+
urls: { ...validManifest.urls, lifecycle: "https://app.example.com/lifecycle" },
|
|
17
|
+
});
|
|
18
|
+
expect(parsed.urls.lifecycle).toBe("https://app.example.com/lifecycle");
|
|
19
|
+
expect(() => appManifestSchema.parse({
|
|
20
|
+
...validManifest,
|
|
21
|
+
urls: { ...validManifest.urls, lifecycle: "http://app.example.com/lifecycle" },
|
|
22
|
+
})).toThrow(/https/i);
|
|
23
|
+
});
|
|
13
24
|
it("accepts a closed v1 manifest and produces a stable digest", () => {
|
|
14
25
|
const first = compileAppManifest(validManifest);
|
|
15
26
|
const second = compileAppManifest({
|
package/dist/contracts.d.ts
CHANGED
|
@@ -127,6 +127,7 @@ export declare const appManifestSchema: z.ZodPipe<z.ZodRecord<z.ZodString, z.Zod
|
|
|
127
127
|
}, z.core.$strict>;
|
|
128
128
|
urls: z.ZodObject<{
|
|
129
129
|
setup: z.ZodOptional<z.ZodString>;
|
|
130
|
+
lifecycle: z.ZodOptional<z.ZodString>;
|
|
130
131
|
health: z.ZodString;
|
|
131
132
|
launch: z.ZodString;
|
|
132
133
|
privacy: z.ZodString;
|
|
@@ -220,6 +221,7 @@ export declare const appOAuthAuthorizeQuerySchema: z.ZodObject<{
|
|
|
220
221
|
release_id: z.ZodString;
|
|
221
222
|
redirect_uri: z.ZodString;
|
|
222
223
|
state: z.ZodString;
|
|
224
|
+
nonce: z.ZodOptional<z.ZodString>;
|
|
223
225
|
code_challenge: z.ZodString;
|
|
224
226
|
code_challenge_method: z.ZodLiteral<"S256">;
|
|
225
227
|
actor_id: z.ZodOptional<z.ZodString>;
|
package/dist/contracts.js
CHANGED
|
@@ -151,6 +151,7 @@ export const appManifestSchema = manifestDisallowedKeySchema.pipe(z
|
|
|
151
151
|
urls: z
|
|
152
152
|
.object({
|
|
153
153
|
setup: httpsUrlSchema.optional(),
|
|
154
|
+
lifecycle: httpsUrlSchema.optional(),
|
|
154
155
|
health: httpsUrlSchema,
|
|
155
156
|
launch: httpsUrlSchema,
|
|
156
157
|
privacy: httpsUrlSchema,
|
|
@@ -269,6 +270,8 @@ export const appOAuthAuthorizeQuerySchema = z
|
|
|
269
270
|
release_id: z.string().trim().min(1),
|
|
270
271
|
redirect_uri: z.string().url(),
|
|
271
272
|
state: z.string().trim().min(1),
|
|
273
|
+
/** Optional app-generated ceremony binding echoed to the redirect URI. */
|
|
274
|
+
nonce: z.string().trim().min(43).max(128).optional(),
|
|
272
275
|
code_challenge: z.string().trim().min(1),
|
|
273
276
|
code_challenge_method: z.literal("S256"),
|
|
274
277
|
/** Deprecated input; the route derives the actor from the staff session. */
|
package/dist/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export * from "./ingestion.js";
|
|
|
10
10
|
export * from "./installation-read-model.js";
|
|
11
11
|
export * from "./installation-service.js";
|
|
12
12
|
export * from "./locale-resolution.js";
|
|
13
|
+
export * from "./marketplace-acquisition.js";
|
|
13
14
|
export * from "./oauth-crypto.js";
|
|
14
15
|
export * from "./oauth-service.js";
|
|
15
16
|
export { createAppsAdminRoutes } from "./routes.js";
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,7 @@ export * from "./ingestion.js";
|
|
|
10
10
|
export * from "./installation-read-model.js";
|
|
11
11
|
export * from "./installation-service.js";
|
|
12
12
|
export * from "./locale-resolution.js";
|
|
13
|
+
export * from "./marketplace-acquisition.js";
|
|
13
14
|
export * from "./oauth-crypto.js";
|
|
14
15
|
export * from "./oauth-service.js";
|
|
15
16
|
export { createAppsAdminRoutes } from "./routes.js";
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { handleApiError } from "@voyant-travel/hono";
|
|
2
|
+
import { eq } from "drizzle-orm";
|
|
2
3
|
import { Hono } from "hono";
|
|
3
|
-
import { beforeAll, beforeEach, describe, expect, it } from "vitest";
|
|
4
|
+
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
|
4
5
|
import { createAppsAdminRoutes } from "./routes.js";
|
|
6
|
+
import { apps } from "./schema.js";
|
|
5
7
|
import { createAppsService } from "./service.js";
|
|
6
8
|
import { validManifest } from "./test-fixtures.js";
|
|
7
9
|
const DB_AVAILABLE = !!process.env.TEST_DATABASE_URL;
|
|
@@ -158,4 +160,36 @@ describe.skipIf(!DB_AVAILABLE)("apps installation admin routes", () => {
|
|
|
158
160
|
expect(body.data.installation.status).toBe("active");
|
|
159
161
|
expect(body.data.outcome).toBe("created");
|
|
160
162
|
});
|
|
163
|
+
it("notifies managed authority after a Marketplace uninstall", async () => {
|
|
164
|
+
const { appId, releaseV1 } = await seedAppWithReleases();
|
|
165
|
+
await db.update(apps).set({ distribution: "marketplace" }).where(eq(apps.id, appId));
|
|
166
|
+
const notifyInstallationLifecycle = vi.fn(async () => undefined);
|
|
167
|
+
const managedApp = new Hono();
|
|
168
|
+
managedApp.onError((err, c) => handleApiError(err, c));
|
|
169
|
+
managedApp.use("*", async (c, next) => {
|
|
170
|
+
c.set("db", db);
|
|
171
|
+
await next();
|
|
172
|
+
});
|
|
173
|
+
managedApp.route("/", createAppsAdminRoutes({
|
|
174
|
+
deploymentId: DEPLOYMENT_ID,
|
|
175
|
+
managedMarketplace: {
|
|
176
|
+
resolveAcquisitionIntent: async () => null,
|
|
177
|
+
createSetupHandoff: async () => ({
|
|
178
|
+
redirectUrl: "https://app.example.com/setup?code=opaque",
|
|
179
|
+
}),
|
|
180
|
+
notifyInstallationLifecycle,
|
|
181
|
+
},
|
|
182
|
+
}));
|
|
183
|
+
const installed = await managedApp.request("/install", json({ appId, releaseId: releaseV1.id, actorId: "actor_1" }));
|
|
184
|
+
const installationId = (await installed.json())
|
|
185
|
+
.data.installation.id;
|
|
186
|
+
const response = await managedApp.request(`/installations/${installationId}/uninstall`, json({ actorId: "actor_1" }));
|
|
187
|
+
expect(response.status).toBe(200);
|
|
188
|
+
expect(notifyInstallationLifecycle).toHaveBeenCalledWith({
|
|
189
|
+
event: "uninstalled",
|
|
190
|
+
installationId,
|
|
191
|
+
appId,
|
|
192
|
+
releaseId: releaseV1.id,
|
|
193
|
+
});
|
|
194
|
+
});
|
|
161
195
|
});
|
|
@@ -106,7 +106,7 @@ export declare function createAppInstallationService(options?: AppInstallationSe
|
|
|
106
106
|
uninstalledAt: Date | null;
|
|
107
107
|
purgedAt: Date | null;
|
|
108
108
|
};
|
|
109
|
-
outcome: "
|
|
109
|
+
outcome: "created" | "reinstalled";
|
|
110
110
|
}>;
|
|
111
111
|
upgrade: (db: PostgresJsDatabase, input: UpgradeAppInput) => Promise<{
|
|
112
112
|
installation: {
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { type CompileAppManifestOptions } from "./compiler.js";
|
|
4
|
+
/**
|
|
5
|
+
* Provider-neutral, host-verified input to the deployment-local app registry.
|
|
6
|
+
* A managed host adapts its private catalog model to this closed contract only
|
|
7
|
+
* after it has authenticated the deployment and verified artifact provenance.
|
|
8
|
+
*/
|
|
9
|
+
export declare const hostVerifiedMarketplaceAcquisitionSchema: z.ZodObject<{
|
|
10
|
+
schemaVersion: z.ZodLiteral<"voyant.runtime-marketplace-acquisition.v1">;
|
|
11
|
+
acquisitionId: z.ZodString;
|
|
12
|
+
app: z.ZodObject<{
|
|
13
|
+
id: z.ZodString;
|
|
14
|
+
ownerId: z.ZodString;
|
|
15
|
+
displayName: z.ZodString;
|
|
16
|
+
slug: z.ZodString;
|
|
17
|
+
redirectUris: z.ZodArray<z.ZodString>;
|
|
18
|
+
oauthClient: z.ZodObject<{
|
|
19
|
+
method: z.ZodLiteral<"client_secret_post">;
|
|
20
|
+
secretSha256: z.ZodString;
|
|
21
|
+
}, z.core.$strict>;
|
|
22
|
+
}, z.core.$strict>;
|
|
23
|
+
release: z.ZodObject<{
|
|
24
|
+
id: z.ZodString;
|
|
25
|
+
manifest: z.ZodUnknown;
|
|
26
|
+
digest: z.ZodString;
|
|
27
|
+
signature: z.ZodOptional<z.ZodString>;
|
|
28
|
+
provenance: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
29
|
+
assetInventory: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
30
|
+
}, z.core.$strict>;
|
|
31
|
+
}, z.core.$strict>;
|
|
32
|
+
export type HostVerifiedMarketplaceAcquisition = z.infer<typeof hostVerifiedMarketplaceAcquisitionSchema>;
|
|
33
|
+
export declare const resolveMarketplaceInstallIntentSchema: z.ZodObject<{
|
|
34
|
+
intent: z.ZodString;
|
|
35
|
+
}, z.core.$strict>;
|
|
36
|
+
export declare const marketplaceInstallIntentResultSchema: z.ZodObject<{
|
|
37
|
+
data: z.ZodObject<{
|
|
38
|
+
appId: z.ZodString;
|
|
39
|
+
releaseId: z.ZodString;
|
|
40
|
+
acquisitionId: z.ZodString;
|
|
41
|
+
created: z.ZodBoolean;
|
|
42
|
+
}, z.core.$strict>;
|
|
43
|
+
}, z.core.$strip>;
|
|
44
|
+
export declare const marketplaceSetupHandoffResultSchema: z.ZodObject<{
|
|
45
|
+
data: z.ZodObject<{
|
|
46
|
+
redirectUrl: z.ZodString;
|
|
47
|
+
}, z.core.$strict>;
|
|
48
|
+
}, z.core.$strip>;
|
|
49
|
+
export declare const MARKETPLACE_SETUP_ASSERTION_TYPE: "voyant-marketplace-setup+jwt";
|
|
50
|
+
/** Claims signed by the managed host and verified by the remote app backend. */
|
|
51
|
+
export declare const marketplaceSetupAssertionClaimsSchema: z.ZodObject<{
|
|
52
|
+
schemaVersion: z.ZodLiteral<"voyant.marketplace-setup-assertion.v1">;
|
|
53
|
+
iss: z.ZodString;
|
|
54
|
+
aud: z.ZodString;
|
|
55
|
+
sub: z.ZodString;
|
|
56
|
+
jti: z.ZodString;
|
|
57
|
+
iat: z.ZodNumber;
|
|
58
|
+
exp: z.ZodNumber;
|
|
59
|
+
installationId: z.ZodString;
|
|
60
|
+
appId: z.ZodString;
|
|
61
|
+
releaseId: z.ZodString;
|
|
62
|
+
authorizationUrl: z.ZodString;
|
|
63
|
+
tokenUrl: z.ZodString;
|
|
64
|
+
redirectUri: z.ZodString;
|
|
65
|
+
}, z.core.$strict>;
|
|
66
|
+
export type MarketplaceSetupAssertionClaims = z.infer<typeof marketplaceSetupAssertionClaimsSchema>;
|
|
67
|
+
export interface MarketplaceInstallIntentResult {
|
|
68
|
+
appId: string;
|
|
69
|
+
releaseId: string;
|
|
70
|
+
acquisitionId: string;
|
|
71
|
+
created: boolean;
|
|
72
|
+
}
|
|
73
|
+
export interface MarketplaceAcquisitionServiceOptions extends CompileAppManifestOptions {
|
|
74
|
+
resolveAcquisitionIntent(input: {
|
|
75
|
+
intent: string;
|
|
76
|
+
}): Promise<HostVerifiedMarketplaceAcquisition | null>;
|
|
77
|
+
createSetupHandoff(input: {
|
|
78
|
+
installationId: string;
|
|
79
|
+
appId: string;
|
|
80
|
+
releaseId: string;
|
|
81
|
+
}): Promise<{
|
|
82
|
+
redirectUrl: string;
|
|
83
|
+
}>;
|
|
84
|
+
}
|
|
85
|
+
export declare function createMarketplaceAcquisitionService(options: MarketplaceAcquisitionServiceOptions): {
|
|
86
|
+
resolveAndAcquire(db: PostgresJsDatabase, input: {
|
|
87
|
+
intent: string;
|
|
88
|
+
actorId: string;
|
|
89
|
+
}): Promise<MarketplaceInstallIntentResult>;
|
|
90
|
+
createSetupHandoff(db: PostgresJsDatabase, installationId: string): Promise<{
|
|
91
|
+
redirectUrl: string;
|
|
92
|
+
}>;
|
|
93
|
+
};
|