@powerhousedao/service-offering 0.0.3 → 0.0.5
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/document-models/document-models.d.ts.map +1 -1
- package/dist/document-models/document-models.js +0 -2
- package/dist/document-models/index.d.ts +0 -1
- package/dist/document-models/index.d.ts.map +1 -1
- package/dist/document-models/index.js +0 -1
- package/dist/document-models/subscription-instance/gen/schema/zod.d.ts +1 -1
- package/dist/subgraphs/resources-services/resolvers.d.ts.map +1 -1
- package/dist/subgraphs/resources-services/resolvers.js +86 -21
- package/dist/subgraphs/resources-services/schema.js +6 -6
- package/package.json +1 -1
- package/dist/editors/service-offering-editor/hooks/useRemoteBuilderProfiles.d.ts +0 -20
- package/dist/editors/service-offering-editor/hooks/useRemoteBuilderProfiles.d.ts.map +0 -1
- package/dist/editors/service-offering-editor/hooks/useRemoteBuilderProfiles.js +0 -57
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document-models.d.ts","sourceRoot":"","sources":["../../document-models/document-models.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"document-models.d.ts","sourceRoot":"","sources":["../../document-models/document-models.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAO1D,eAAO,MAAM,cAAc,EAAE,mBAAmB,CAAC,GAAG,CAAC,EAMpD,CAAC"}
|
|
@@ -2,13 +2,11 @@ import { Facet } from "./facet/module.js";
|
|
|
2
2
|
import { ResourceInstance } from "./resource-instance/module.js";
|
|
3
3
|
import { ResourceTemplate } from "./resource-template/module.js";
|
|
4
4
|
import { ServiceOffering } from "./service-offering/module.js";
|
|
5
|
-
import { ServiceSubscription } from "./service-subscription/module.js";
|
|
6
5
|
import { SubscriptionInstance } from "./subscription-instance/module.js";
|
|
7
6
|
export const documentModels = [
|
|
8
7
|
Facet,
|
|
9
8
|
ResourceInstance,
|
|
10
9
|
ResourceTemplate,
|
|
11
10
|
ServiceOffering,
|
|
12
|
-
ServiceSubscription,
|
|
13
11
|
SubscriptionInstance,
|
|
14
12
|
];
|
|
@@ -2,6 +2,5 @@ export { Facet } from "./facet/module.js";
|
|
|
2
2
|
export { ResourceInstance } from "./resource-instance/module.js";
|
|
3
3
|
export { ResourceTemplate } from "./resource-template/module.js";
|
|
4
4
|
export { ServiceOffering } from "./service-offering/module.js";
|
|
5
|
-
export { ServiceSubscription } from "./service-subscription/module.js";
|
|
6
5
|
export { SubscriptionInstance } from "./subscription-instance/module.js";
|
|
7
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../document-models/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../document-models/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC"}
|
|
@@ -2,5 +2,4 @@ export { Facet } from "./facet/module.js";
|
|
|
2
2
|
export { ResourceInstance } from "./resource-instance/module.js";
|
|
3
3
|
export { ResourceTemplate } from "./resource-template/module.js";
|
|
4
4
|
export { ServiceOffering } from "./service-offering/module.js";
|
|
5
|
-
export { ServiceSubscription } from "./service-subscription/module.js";
|
|
6
5
|
export { SubscriptionInstance } from "./subscription-instance/module.js";
|
|
@@ -41,10 +41,10 @@ export declare const ResetPeriodSchema: z.ZodEnum<{
|
|
|
41
41
|
}>;
|
|
42
42
|
export declare const SubscriptionStatusSchema: z.ZodEnum<{
|
|
43
43
|
ACTIVE: "ACTIVE";
|
|
44
|
-
PENDING: "PENDING";
|
|
45
44
|
CANCELLED: "CANCELLED";
|
|
46
45
|
EXPIRING: "EXPIRING";
|
|
47
46
|
PAUSED: "PAUSED";
|
|
47
|
+
PENDING: "PENDING";
|
|
48
48
|
}>;
|
|
49
49
|
export declare const TierPricingModeSchema: z.ZodEnum<{
|
|
50
50
|
CALCULATED: "CALCULATED";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolvers.d.ts","sourceRoot":"","sources":["../../../subgraphs/resources-services/resolvers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"resolvers.d.ts","sourceRoot":"","sources":["../../../subgraphs/resources-services/resolvers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAqC5D,eAAO,MAAM,YAAY,GAAI,UAAU,SAAS,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CA6ZxE,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {} from "@powerhousedao/reactor-api";
|
|
2
2
|
import { createAction } from "document-model/core";
|
|
3
3
|
import { addFile } from "document-drive";
|
|
4
|
-
import { ResourceInstance } from "@powerhousedao/service-offering/document-models";
|
|
4
|
+
import { ResourceInstance, SubscriptionInstance, } from "@powerhousedao/service-offering/document-models";
|
|
5
5
|
export const getResolvers = (subgraph) => {
|
|
6
6
|
const reactor = subgraph.reactor;
|
|
7
7
|
return {
|
|
@@ -150,15 +150,15 @@ export const getResolvers = (subgraph) => {
|
|
|
150
150
|
},
|
|
151
151
|
},
|
|
152
152
|
Mutation: {
|
|
153
|
-
|
|
153
|
+
createProductInstances: async (_, args) => {
|
|
154
154
|
const { input } = args;
|
|
155
|
-
const {
|
|
155
|
+
const { serviceOfferingId, name, teamName } = input;
|
|
156
156
|
// Validate input
|
|
157
|
-
if (!
|
|
157
|
+
if (!serviceOfferingId) {
|
|
158
158
|
return {
|
|
159
159
|
success: false,
|
|
160
160
|
data: null,
|
|
161
|
-
errors: ["
|
|
161
|
+
errors: ["Service offering ID is required"],
|
|
162
162
|
};
|
|
163
163
|
}
|
|
164
164
|
if (!name) {
|
|
@@ -171,6 +171,32 @@ export const getResolvers = (subgraph) => {
|
|
|
171
171
|
errors: ["Team name is required"],
|
|
172
172
|
};
|
|
173
173
|
}
|
|
174
|
+
// Fetch the service offering to get resourceTemplateId and finalConfiguration
|
|
175
|
+
const serviceOfferingDoc = await reactor.getDocument(serviceOfferingId);
|
|
176
|
+
if (!serviceOfferingDoc) {
|
|
177
|
+
return {
|
|
178
|
+
success: false,
|
|
179
|
+
data: null,
|
|
180
|
+
errors: ["Service offering not found"],
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
const serviceOfferingState = serviceOfferingDoc.state.global;
|
|
184
|
+
const resourceTemplateId = serviceOfferingState.resourceTemplateId;
|
|
185
|
+
if (!resourceTemplateId) {
|
|
186
|
+
return {
|
|
187
|
+
success: false,
|
|
188
|
+
data: null,
|
|
189
|
+
errors: ["Service offering has no associated resource template"],
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
const finalConfiguration = serviceOfferingState.finalConfiguration;
|
|
193
|
+
if (!finalConfiguration) {
|
|
194
|
+
return {
|
|
195
|
+
success: false,
|
|
196
|
+
data: null,
|
|
197
|
+
errors: ["Service offering has no final configuration"],
|
|
198
|
+
};
|
|
199
|
+
}
|
|
174
200
|
const parsedTeamName = teamName.toLowerCase().replace(/ /g, "-");
|
|
175
201
|
const parsedName = name.toLowerCase().replace(/ /g, "-");
|
|
176
202
|
try {
|
|
@@ -184,7 +210,6 @@ export const getResolvers = (subgraph) => {
|
|
|
184
210
|
slug: parsedTeamName,
|
|
185
211
|
preferredEditor: "builder-team-admin",
|
|
186
212
|
});
|
|
187
|
-
teamBuilderAdminDrive.header.id;
|
|
188
213
|
// create builder-profile doc inside the team-builder-admin drive
|
|
189
214
|
const builderProfileDoc = await reactor.addDocument("powerhouse/builder-profile");
|
|
190
215
|
await reactor.addAction(teamBuilderAdminDrive.header.id, addFile({
|
|
@@ -194,25 +219,65 @@ export const getResolvers = (subgraph) => {
|
|
|
194
219
|
parentFolder: teamBuilderAdminDrive.state.global.nodes?.find((node) => node.kind === "folder")?.parentFolder,
|
|
195
220
|
}));
|
|
196
221
|
await reactor.addAction(builderProfileDoc.header.id, createAction("UPDATE_PROFILE", { name }, undefined, undefined, "global"));
|
|
197
|
-
// create resource-instance
|
|
222
|
+
// create resource-instance and subscription-instance docs
|
|
198
223
|
const resourceInstanceDoc = await reactor.addDocument("powerhouse/resource-instance");
|
|
199
|
-
await reactor.
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
name: `${parsedName} Resource Instance`,
|
|
203
|
-
parentFolder: teamBuilderAdminDrive.state.global.nodes?.find((node) => node.kind === "folder")?.parentFolder,
|
|
204
|
-
}));
|
|
205
|
-
await populateResourceInstance(reactor, resourceInstanceDoc.header.id, resourceTemplateId, builderProfileDoc.header.id, name);
|
|
206
|
-
// create copy of resource-instance doc inside the operator's drive
|
|
224
|
+
const subscriptionInstanceDoc = await reactor.addDocument("powerhouse/subscription-instance");
|
|
225
|
+
// resolve parent folders for both drives
|
|
226
|
+
const teamParentFolder = teamBuilderAdminDrive.state.global.nodes?.find((node) => node.kind === "folder")?.parentFolder;
|
|
207
227
|
const operatorDrive = await getOperatorDrive(reactor, resourceTemplateId);
|
|
208
228
|
if (!operatorDrive) {
|
|
209
229
|
throw new Error(`Operator drive not found for resource template ${resourceTemplateId}`);
|
|
210
230
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
231
|
+
const operatorParentFolder = operatorDrive.state.global.nodes?.find((node) => node.kind === "folder")?.parentFolder;
|
|
232
|
+
// batch add resource-instance and subscription-instance to team-builder-admin drive
|
|
233
|
+
await reactor.addActions(teamBuilderAdminDrive.header.id, [
|
|
234
|
+
addFile({
|
|
235
|
+
documentType: "powerhouse/resource-instance",
|
|
236
|
+
id: resourceInstanceDoc.header.id,
|
|
237
|
+
name: `${parsedName} Resource Instance`,
|
|
238
|
+
parentFolder: teamParentFolder,
|
|
239
|
+
}),
|
|
240
|
+
addFile({
|
|
241
|
+
documentType: "powerhouse/subscription-instance",
|
|
242
|
+
id: subscriptionInstanceDoc.header.id,
|
|
243
|
+
name: `${parsedName} Subscription Instance`,
|
|
244
|
+
parentFolder: teamParentFolder,
|
|
245
|
+
}),
|
|
246
|
+
]);
|
|
247
|
+
// batch add resource-instance and subscription-instance to operator drive
|
|
248
|
+
await reactor.addActions(operatorDrive.header.id, [
|
|
249
|
+
addFile({
|
|
250
|
+
documentType: "powerhouse/resource-instance",
|
|
251
|
+
id: resourceInstanceDoc.header.id,
|
|
252
|
+
name: `${parsedName} Resource Instance`,
|
|
253
|
+
parentFolder: operatorParentFolder,
|
|
254
|
+
}),
|
|
255
|
+
addFile({
|
|
256
|
+
documentType: "powerhouse/subscription-instance",
|
|
257
|
+
id: subscriptionInstanceDoc.header.id,
|
|
258
|
+
name: `${parsedName} Subscription Instance`,
|
|
259
|
+
parentFolder: operatorParentFolder,
|
|
260
|
+
}),
|
|
261
|
+
]);
|
|
262
|
+
// populate documents after all files are added to both drives
|
|
263
|
+
await populateResourceInstance(reactor, resourceInstanceDoc.header.id, resourceTemplateId, builderProfileDoc.header.id, name);
|
|
264
|
+
const now = new Date().toISOString();
|
|
265
|
+
// find the selected tier to get its name and pricing details
|
|
266
|
+
const selectedTier = serviceOfferingState.tiers.find((t) => t.id === finalConfiguration.selectedTierId);
|
|
267
|
+
await reactor.addAction(subscriptionInstanceDoc.header.id, SubscriptionInstance.actions.initializeSubscription({
|
|
268
|
+
customerId: builderProfileDoc.header.id,
|
|
269
|
+
customerName: name,
|
|
270
|
+
serviceOfferingId,
|
|
271
|
+
resourceId: resourceInstanceDoc.header.id,
|
|
272
|
+
resourceLabel: name,
|
|
273
|
+
resourceThumbnailUrl: serviceOfferingState.thumbnailUrl,
|
|
274
|
+
tierName: selectedTier?.name || null,
|
|
275
|
+
tierPrice: selectedTier?.pricing?.amount ?? null,
|
|
276
|
+
tierCurrency: selectedTier?.pricing?.currency || null,
|
|
277
|
+
tierPricingMode: selectedTier?.pricingMode || null,
|
|
278
|
+
selectedBillingCycle: finalConfiguration.selectedBillingCycle || null,
|
|
279
|
+
globalCurrency: finalConfiguration.tierCurrency || null,
|
|
280
|
+
createdAt: now,
|
|
216
281
|
}));
|
|
217
282
|
return {
|
|
218
283
|
success: true,
|
|
@@ -223,7 +288,7 @@ export const getResolvers = (subgraph) => {
|
|
|
223
288
|
};
|
|
224
289
|
}
|
|
225
290
|
catch (error) {
|
|
226
|
-
console.error("Failed to create
|
|
291
|
+
console.error("Failed to create product instances:", error);
|
|
227
292
|
return {
|
|
228
293
|
success: false,
|
|
229
294
|
data: null,
|
|
@@ -9,18 +9,18 @@ export const schema = gql `
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
type Mutation {
|
|
12
|
-
|
|
13
|
-
input:
|
|
14
|
-
):
|
|
12
|
+
createProductInstances(
|
|
13
|
+
input: CreateProductInstancesInput!
|
|
14
|
+
): CreateProductInstancesOutput
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
input
|
|
18
|
-
|
|
17
|
+
input CreateProductInstancesInput {
|
|
18
|
+
serviceOfferingId: PHID!
|
|
19
19
|
name: String!
|
|
20
20
|
teamName: String!
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
type
|
|
23
|
+
type CreateProductInstancesOutput {
|
|
24
24
|
success: Boolean!
|
|
25
25
|
data: JSONObject
|
|
26
26
|
errors: [String!]!
|
package/package.json
CHANGED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { type RemoteBuilderProfile } from "../utils/graphql-client.js";
|
|
2
|
-
interface UseRemoteBuilderProfilesResult {
|
|
3
|
-
/** Map of PHID to remote builder profile data */
|
|
4
|
-
profileMap: Map<string, RemoteBuilderProfile>;
|
|
5
|
-
/** All available remote profiles for selection */
|
|
6
|
-
allProfiles: RemoteBuilderProfile[];
|
|
7
|
-
/** Whether remote data is currently loading */
|
|
8
|
-
isLoading: boolean;
|
|
9
|
-
/** Manually refetch all available profiles */
|
|
10
|
-
refetchAll: () => Promise<void>;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Hook for fetching builder profiles from remote Switchboard drives.
|
|
14
|
-
* Used as a fallback when local drives don't have the builder profile documents.
|
|
15
|
-
*
|
|
16
|
-
* @param localProfileMap - Map of PHIDs that are already resolved locally (to avoid using remote data for those)
|
|
17
|
-
*/
|
|
18
|
-
export declare function useRemoteBuilderProfiles(localProfileMap: Map<string, unknown>): UseRemoteBuilderProfilesResult;
|
|
19
|
-
export {};
|
|
20
|
-
//# sourceMappingURL=useRemoteBuilderProfiles.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useRemoteBuilderProfiles.d.ts","sourceRoot":"","sources":["../../../../editors/service-offering-editor/hooks/useRemoteBuilderProfiles.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,4BAA4B,CAAC;AAEpC,UAAU,8BAA8B;IACtC,iDAAiD;IACjD,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;IAC9C,kDAAkD;IAClD,WAAW,EAAE,oBAAoB,EAAE,CAAC;IACpC,+CAA+C;IAC/C,SAAS,EAAE,OAAO,CAAC;IACnB,8CAA8C;IAC9C,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACjC;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GACpC,8BAA8B,CA8DhC"}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { useState, useEffect, useCallback, useRef } from "react";
|
|
2
|
-
import { fetchAllRemoteBuilderProfiles, } from "../utils/graphql-client.js";
|
|
3
|
-
/**
|
|
4
|
-
* Hook for fetching builder profiles from remote Switchboard drives.
|
|
5
|
-
* Used as a fallback when local drives don't have the builder profile documents.
|
|
6
|
-
*
|
|
7
|
-
* @param localProfileMap - Map of PHIDs that are already resolved locally (to avoid using remote data for those)
|
|
8
|
-
*/
|
|
9
|
-
export function useRemoteBuilderProfiles(localProfileMap) {
|
|
10
|
-
const [profileMap, setProfileMap] = useState(new Map());
|
|
11
|
-
const [allProfiles, setAllProfiles] = useState([]);
|
|
12
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
13
|
-
// Track if we've already started fetching to avoid duplicate requests
|
|
14
|
-
const isFetchingRef = useRef(false);
|
|
15
|
-
const hasFetchedRef = useRef(false);
|
|
16
|
-
// Fetch all available profiles
|
|
17
|
-
const refetchAll = useCallback(async () => {
|
|
18
|
-
// Prevent concurrent fetches
|
|
19
|
-
if (isFetchingRef.current) {
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
isFetchingRef.current = true;
|
|
23
|
-
setIsLoading(true);
|
|
24
|
-
try {
|
|
25
|
-
const profiles = await fetchAllRemoteBuilderProfiles();
|
|
26
|
-
hasFetchedRef.current = true;
|
|
27
|
-
setAllProfiles(profiles);
|
|
28
|
-
// Build profile map
|
|
29
|
-
const newMap = new Map();
|
|
30
|
-
profiles.forEach((profile) => {
|
|
31
|
-
newMap.set(profile.id, profile);
|
|
32
|
-
});
|
|
33
|
-
setProfileMap(newMap);
|
|
34
|
-
}
|
|
35
|
-
catch (error) {
|
|
36
|
-
console.warn("[useRemoteBuilderProfiles] Failed to fetch profiles:", error);
|
|
37
|
-
}
|
|
38
|
-
finally {
|
|
39
|
-
setIsLoading(false);
|
|
40
|
-
isFetchingRef.current = false;
|
|
41
|
-
}
|
|
42
|
-
}, []);
|
|
43
|
-
// Auto-fetch all profiles on mount
|
|
44
|
-
useEffect(() => {
|
|
45
|
-
if (!hasFetchedRef.current && !isFetchingRef.current) {
|
|
46
|
-
void refetchAll();
|
|
47
|
-
}
|
|
48
|
-
}, [refetchAll]);
|
|
49
|
-
// Filter out profiles that exist locally from the returned allProfiles
|
|
50
|
-
const filteredAllProfiles = allProfiles.filter((profile) => !localProfileMap.has(profile.id));
|
|
51
|
-
return {
|
|
52
|
-
profileMap,
|
|
53
|
-
allProfiles: filteredAllProfiles,
|
|
54
|
-
isLoading,
|
|
55
|
-
refetchAll,
|
|
56
|
-
};
|
|
57
|
-
}
|