@powerhousedao/contributor-billing 0.1.44 → 0.1.46

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.
@@ -1 +1 @@
1
- {"version":3,"file":"TemplateInfo.d.ts","sourceRoot":"","sources":["../../../../editors/resource-template-editor/components/TemplateInfo.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EACV,wBAAwB,EACxB,sBAAsB,EAIvB,MAAM,sEAAsE,CAAC;AAmB9E,UAAU,iBAAiB;IACzB,QAAQ,EAAE,wBAAwB,CAAC;IACnC,QAAQ,EAAE,gBAAgB,CAAC,sBAAsB,CAAC,CAAC;CACpD;AA0FD,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,iBAAiB,2CA25CrE"}
1
+ {"version":3,"file":"TemplateInfo.d.ts","sourceRoot":"","sources":["../../../../editors/resource-template-editor/components/TemplateInfo.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EACV,wBAAwB,EACxB,sBAAsB,EAIvB,MAAM,sEAAsE,CAAC;AAmB9E,UAAU,iBAAiB;IACzB,QAAQ,EAAE,wBAAwB,CAAC;IACnC,QAAQ,EAAE,gBAAgB,CAAC,sBAAsB,CAAC,CAAC;CACpD;AA0FD,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,iBAAiB,2CAk6CrE"}
@@ -1 +1 @@
1
- {"version":3,"file":"resolvers.d.ts","sourceRoot":"","sources":["../../../subgraphs/budget-statements/resolvers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,4BAA4B,CAAC;AA0E5D,eAAO,MAAM,YAAY,GAAI,UAAU,SAAS,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CA0RxE,CAAC"}
1
+ {"version":3,"file":"resolvers.d.ts","sourceRoot":"","sources":["../../../subgraphs/budget-statements/resolvers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,4BAA4B,CAAC;AA0E5D,eAAO,MAAM,YAAY,GAAI,UAAU,SAAS,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAmSxE,CAAC"}
@@ -253,10 +253,16 @@ export const getResolvers = (subgraph) => {
253
253
  groups: [],
254
254
  wallets: [],
255
255
  };
256
+ // Get status from expense report state (default to empty string if not available)
257
+ const status = expenseReport?.state.global.status || "DRAFT";
258
+ // Get lastModifiedAtUtcIso from the expense report document header
259
+ const lastModifiedAtUtcIso = expenseReport?.header.lastModifiedAtUtcIso || "";
256
260
  budgetStatements.push({
257
261
  id: key,
258
262
  owner,
259
263
  month,
264
+ status,
265
+ lastModifiedAtUtcIso,
260
266
  snapshotReport: snapshotReportData,
261
267
  expenseReport: expenseReportData,
262
268
  });
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../subgraphs/budget-statements/schema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,eAAO,MAAM,MAAM,EAAE,YAkIpB,CAAC"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../subgraphs/budget-statements/schema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,eAAO,MAAM,MAAM,EAAE,YAoIpB,CAAC"}
@@ -16,6 +16,8 @@ export const schema = gql `
16
16
  id: OID!
17
17
  owner: BudgetStatementOwner!
18
18
  month: String! ## JAN2026
19
+ status: String!
20
+ lastModifiedAtUtcIso: DateTime!
19
21
  snapshotReport: BudgetStatementSnapshotReport!
20
22
  expenseReport: BudgetStatementExpenseReport!
21
23
  }
@@ -2,4 +2,5 @@ export * as InvoiceAddonSubgraph from "./invoice-addon/index.js";
2
2
  export * as AccTxsAddonSubgraph from "./acc-txs-addon/index.js";
3
3
  export * as BudgetStatementsSubgraph from "./budget-statements/index.js";
4
4
  export * as ExpenseReportSubgraph from "./expense-report/index.js";
5
+ export * as ResourcesServicesSubgraph from "./resources-services/index.js";
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../subgraphs/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,oBAAoB,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,mBAAmB,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,wBAAwB,MAAM,8BAA8B,CAAC;AACzE,OAAO,KAAK,qBAAqB,MAAM,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../subgraphs/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,oBAAoB,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,mBAAmB,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,wBAAwB,MAAM,8BAA8B,CAAC;AACzE,OAAO,KAAK,qBAAqB,MAAM,2BAA2B,CAAC;AACnE,OAAO,KAAK,yBAAyB,MAAM,+BAA+B,CAAC"}
@@ -2,3 +2,4 @@ export * as InvoiceAddonSubgraph from "./invoice-addon/index.js";
2
2
  export * as AccTxsAddonSubgraph from "./acc-txs-addon/index.js";
3
3
  export * as BudgetStatementsSubgraph from "./budget-statements/index.js";
4
4
  export * as ExpenseReportSubgraph from "./expense-report/index.js";
5
+ export * as ResourcesServicesSubgraph from "./resources-services/index.js";
@@ -0,0 +1,11 @@
1
+ import { BaseSubgraph } from "@powerhousedao/reactor-api";
2
+ import type { DocumentNode } from "graphql";
3
+ export declare class ResourcesServicesSubgraph extends BaseSubgraph {
4
+ name: string;
5
+ typeDefs: DocumentNode;
6
+ resolvers: Record<string, unknown>;
7
+ additionalContextFields: {};
8
+ onSetup(): Promise<void>;
9
+ onDisconnect(): Promise<void>;
10
+ }
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../subgraphs/resources-services/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAI5C,qBAAa,yBAA0B,SAAQ,YAAY;IACzD,IAAI,SAAwB;IAC5B,QAAQ,EAAE,YAAY,CAAU;IAChC,SAAS,0BAAsB;IAC/B,uBAAuB,KAAM;IACvB,OAAO;IACP,YAAY;CACnB"}
@@ -0,0 +1,11 @@
1
+ import { BaseSubgraph } from "@powerhousedao/reactor-api";
2
+ import { schema } from "./schema.js";
3
+ import { getResolvers } from "./resolvers.js";
4
+ export class ResourcesServicesSubgraph extends BaseSubgraph {
5
+ name = "resources-services";
6
+ typeDefs = schema;
7
+ resolvers = getResolvers(this);
8
+ additionalContextFields = {};
9
+ async onSetup() { }
10
+ async onDisconnect() { }
11
+ }
@@ -0,0 +1,3 @@
1
+ import { type ISubgraph } from "@powerhousedao/reactor-api";
2
+ export declare const getResolvers: (subgraph: ISubgraph) => Record<string, unknown>;
3
+ //# sourceMappingURL=resolvers.d.ts.map
@@ -0,0 +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;AAyB5D,eAAO,MAAM,YAAY,GAAI,UAAU,SAAS,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAkMxE,CAAC"}
@@ -0,0 +1,313 @@
1
+ import {} from "@powerhousedao/reactor-api";
2
+ export const getResolvers = (subgraph) => {
3
+ const reactor = subgraph.reactor;
4
+ return {
5
+ Query: {
6
+ resourceTemplates: async (_, args) => {
7
+ const { id, status, operatorId } = args.filter || {};
8
+ // If filtering by specific id, try to fetch directly
9
+ if (id) {
10
+ try {
11
+ const doc = await reactor.getDocument(id);
12
+ if (doc &&
13
+ doc.header.documentType === "powerhouse/resource-template") {
14
+ const state = doc.state.global;
15
+ // Check status filter if provided
16
+ if (status &&
17
+ status.length > 0 &&
18
+ !status.includes(state.status)) {
19
+ return [];
20
+ }
21
+ // Check operatorId filter if provided
22
+ if (operatorId && state.operatorId !== operatorId) {
23
+ return [];
24
+ }
25
+ return [mapResourceTemplateState(state)];
26
+ }
27
+ }
28
+ catch {
29
+ // Document not found
30
+ }
31
+ return [];
32
+ }
33
+ // Scan all drives for resource template documents
34
+ const drives = await reactor.getDrives();
35
+ const resourceTemplates = [];
36
+ for (const driveId of drives) {
37
+ try {
38
+ const docIds = await reactor.getDocuments(driveId);
39
+ const docs = await Promise.all(docIds.map(async (docId) => {
40
+ try {
41
+ return await reactor.getDocument(docId);
42
+ }
43
+ catch {
44
+ return null;
45
+ }
46
+ }));
47
+ for (const doc of docs) {
48
+ if (doc &&
49
+ doc.header.documentType === "powerhouse/resource-template") {
50
+ const resourceDoc = doc;
51
+ const state = resourceDoc.state.global;
52
+ // Apply status filter if provided
53
+ if (status &&
54
+ status.length > 0 &&
55
+ !status.includes(state.status)) {
56
+ continue;
57
+ }
58
+ // Apply operatorId filter if provided
59
+ if (operatorId && state.operatorId !== operatorId) {
60
+ continue;
61
+ }
62
+ resourceTemplates.push(mapResourceTemplateState(state));
63
+ }
64
+ }
65
+ }
66
+ catch (error) {
67
+ console.warn(`Failed to inspect drive ${driveId}:`, error);
68
+ }
69
+ }
70
+ return resourceTemplates;
71
+ },
72
+ serviceOfferings: async (_, args) => {
73
+ const { id, status, operatorId, resourceTemplateId } = args.filter || {};
74
+ // If filtering by specific id, try to fetch directly
75
+ if (id) {
76
+ try {
77
+ const doc = await reactor.getDocument(id);
78
+ if (doc &&
79
+ doc.header.documentType === "powerhouse/service-offering") {
80
+ const state = doc.state.global;
81
+ // Check status filter if provided
82
+ if (status &&
83
+ status.length > 0 &&
84
+ !status.includes(state.status)) {
85
+ return [];
86
+ }
87
+ // Check operatorId filter if provided
88
+ if (operatorId && state.operatorId !== operatorId) {
89
+ return [];
90
+ }
91
+ // Check resourceTemplateId filter if provided
92
+ if (resourceTemplateId &&
93
+ state.resourceTemplateId !== resourceTemplateId) {
94
+ return [];
95
+ }
96
+ return [mapServiceOfferingState(state)];
97
+ }
98
+ }
99
+ catch {
100
+ // Document not found
101
+ }
102
+ return [];
103
+ }
104
+ // Scan all drives for service offering documents
105
+ const drives = await reactor.getDrives();
106
+ const serviceOfferings = [];
107
+ for (const driveId of drives) {
108
+ try {
109
+ const docIds = await reactor.getDocuments(driveId);
110
+ const docs = await Promise.all(docIds.map(async (docId) => {
111
+ try {
112
+ return await reactor.getDocument(docId);
113
+ }
114
+ catch {
115
+ return null;
116
+ }
117
+ }));
118
+ for (const doc of docs) {
119
+ if (doc &&
120
+ doc.header.documentType === "powerhouse/service-offering") {
121
+ const offeringDoc = doc;
122
+ const state = offeringDoc.state.global;
123
+ // Apply status filter if provided
124
+ if (status &&
125
+ status.length > 0 &&
126
+ !status.includes(state.status)) {
127
+ continue;
128
+ }
129
+ // Apply operatorId filter if provided
130
+ if (operatorId && state.operatorId !== operatorId) {
131
+ continue;
132
+ }
133
+ // Apply resourceTemplateId filter if provided
134
+ if (resourceTemplateId &&
135
+ state.resourceTemplateId !== resourceTemplateId) {
136
+ continue;
137
+ }
138
+ serviceOfferings.push(mapServiceOfferingState(state));
139
+ }
140
+ }
141
+ }
142
+ catch (error) {
143
+ console.warn(`Failed to inspect drive ${driveId}:`, error);
144
+ }
145
+ }
146
+ return serviceOfferings;
147
+ },
148
+ },
149
+ };
150
+ };
151
+ /**
152
+ * Map ResourceTemplateState from document model to GraphQL response
153
+ */
154
+ function mapResourceTemplateState(state) {
155
+ return {
156
+ id: state.id,
157
+ operatorId: state.operatorId,
158
+ title: state.title,
159
+ summary: state.summary,
160
+ description: state.description || null,
161
+ thumbnailUrl: state.thumbnailUrl || null,
162
+ infoLink: state.infoLink || null,
163
+ status: state.status,
164
+ lastModified: state.lastModified,
165
+ targetAudiences: state.targetAudiences.map((audience) => ({
166
+ id: audience.id,
167
+ label: audience.label,
168
+ color: audience.color || null,
169
+ })),
170
+ setupServices: state.setupServices,
171
+ recurringServices: state.recurringServices,
172
+ facetTargets: state.facetTargets.map((facet) => ({
173
+ id: facet.id,
174
+ categoryKey: facet.categoryKey,
175
+ categoryLabel: facet.categoryLabel,
176
+ selectedOptions: facet.selectedOptions,
177
+ })),
178
+ services: state.services.map((service) => ({
179
+ id: service.id,
180
+ title: service.title,
181
+ description: service.description || null,
182
+ displayOrder: service.displayOrder ?? null,
183
+ parentServiceId: service.parentServiceId || null,
184
+ isSetupFormation: service.isSetupFormation,
185
+ optionGroupId: service.optionGroupId || null,
186
+ facetBindings: service.facetBindings.map((binding) => ({
187
+ id: binding.id,
188
+ facetName: binding.facetName,
189
+ facetType: binding.facetType,
190
+ supportedOptions: binding.supportedOptions,
191
+ })),
192
+ })),
193
+ optionGroups: state.optionGroups.map((group) => ({
194
+ id: group.id,
195
+ name: group.name,
196
+ description: group.description || null,
197
+ isAddOn: group.isAddOn,
198
+ defaultSelected: group.defaultSelected,
199
+ })),
200
+ faqFields: (state.faqFields || []).map((faq) => ({
201
+ id: faq.id,
202
+ question: faq.question || null,
203
+ answer: faq.answer || null,
204
+ displayOrder: faq.displayOrder,
205
+ })),
206
+ contentSections: state.contentSections.map((section) => ({
207
+ id: section.id,
208
+ title: section.title,
209
+ content: section.content,
210
+ displayOrder: section.displayOrder,
211
+ })),
212
+ };
213
+ }
214
+ /**
215
+ * Map ServiceOfferingState from document model to GraphQL response
216
+ */
217
+ function mapServiceOfferingState(state) {
218
+ return {
219
+ id: state.id,
220
+ operatorId: state.operatorId,
221
+ resourceTemplateId: state.resourceTemplateId || null,
222
+ title: state.title,
223
+ summary: state.summary,
224
+ description: state.description || null,
225
+ thumbnailUrl: state.thumbnailUrl || null,
226
+ infoLink: state.infoLink || null,
227
+ status: state.status,
228
+ lastModified: state.lastModified,
229
+ targetAudiences: state.targetAudiences.map((audience) => ({
230
+ id: audience.id,
231
+ label: audience.label,
232
+ color: audience.color || null,
233
+ })),
234
+ setupServices: state.setupServices,
235
+ recurringServices: state.recurringServices,
236
+ facetTargets: state.facetTargets.map((facet) => ({
237
+ id: facet.id,
238
+ categoryKey: facet.categoryKey,
239
+ categoryLabel: facet.categoryLabel,
240
+ selectedOptions: facet.selectedOptions,
241
+ })),
242
+ services: state.services.map((service) => ({
243
+ id: service.id,
244
+ title: service.title,
245
+ description: service.description || null,
246
+ displayOrder: service.displayOrder ?? null,
247
+ parentServiceId: service.parentServiceId || null,
248
+ isSetupFormation: service.isSetupFormation,
249
+ isPremiumExclusive: service.isPremiumExclusive,
250
+ optionGroupId: service.optionGroupId || null,
251
+ facetBindings: service.facetBindings.map((binding) => ({
252
+ id: binding.id,
253
+ facetName: binding.facetName,
254
+ facetType: binding.facetType,
255
+ supportedOptions: binding.supportedOptions,
256
+ })),
257
+ })),
258
+ tiers: state.tiers.map((tier) => ({
259
+ id: tier.id,
260
+ name: tier.name,
261
+ description: tier.description || null,
262
+ isCustomPricing: tier.isCustomPricing,
263
+ pricing: {
264
+ amount: tier.pricing.amount ?? null,
265
+ currency: tier.pricing.currency,
266
+ billingCycle: tier.pricing.billingCycle,
267
+ setupFee: tier.pricing.setupFee ?? null,
268
+ perSeatAmount: tier.pricing.perSeatAmount ?? null,
269
+ perSeatCurrency: tier.pricing.perSeatCurrency || null,
270
+ perSeatBillingCycle: tier.pricing.perSeatBillingCycle || null,
271
+ perSeatLabel: tier.pricing.perSeatLabel || null,
272
+ },
273
+ pricingOptions: tier.pricingOptions.map((option) => ({
274
+ id: option.id,
275
+ billingCycle: option.billingCycle,
276
+ amount: option.amount,
277
+ currency: option.currency,
278
+ setupFee: option.setupFee ?? null,
279
+ isDefault: option.isDefault,
280
+ perSeatAmount: option.perSeatAmount ?? null,
281
+ })),
282
+ serviceLevels: tier.serviceLevels.map((level) => ({
283
+ id: level.id,
284
+ serviceId: level.serviceId,
285
+ level: level.level,
286
+ customValue: level.customValue || null,
287
+ variations: level.variations || null,
288
+ annexes: level.annexes || null,
289
+ setupFee: level.setupFee ?? null,
290
+ optionGroupId: level.optionGroupId || null,
291
+ })),
292
+ usageLimits: tier.usageLimits.map((limit) => ({
293
+ id: limit.id,
294
+ serviceId: limit.serviceId,
295
+ metric: limit.metric,
296
+ unitName: limit.unitName || null,
297
+ limit: limit.limit ?? null,
298
+ resetPeriod: limit.resetPeriod || null,
299
+ notes: limit.notes || null,
300
+ unitPrice: limit.unitPrice ?? null,
301
+ unitPriceCurrency: limit.unitPriceCurrency || null,
302
+ unitPriceBillingCycle: limit.unitPriceBillingCycle || null,
303
+ })),
304
+ })),
305
+ optionGroups: state.optionGroups.map((group) => ({
306
+ id: group.id,
307
+ name: group.name,
308
+ description: group.description || null,
309
+ isAddOn: group.isAddOn,
310
+ defaultSelected: group.defaultSelected,
311
+ })),
312
+ };
313
+ }
@@ -0,0 +1,3 @@
1
+ import type { DocumentNode } from "graphql";
2
+ export declare const schema: DocumentNode;
3
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../subgraphs/resources-services/schema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,eAAO,MAAM,MAAM,EAAE,YAqOpB,CAAC"}
@@ -0,0 +1,231 @@
1
+ import { gql } from "graphql-tag";
2
+ export const schema = gql `
3
+ """
4
+ Subgraph definition for Resource Templates and Service Offerings
5
+ """
6
+ type Query {
7
+ resourceTemplates(filter: RSResourceTemplatesFilter): [RSResourceTemplate!]!
8
+ serviceOfferings(filter: RSServiceOfferingsFilter): [RSServiceOffering!]!
9
+ }
10
+
11
+ # ============ Filters ============
12
+
13
+ input RSResourceTemplatesFilter {
14
+ id: PHID
15
+ status: [RSTemplateStatus!]
16
+ operatorId: PHID
17
+ }
18
+
19
+ input RSServiceOfferingsFilter {
20
+ id: PHID
21
+ status: [RSServiceStatus!]
22
+ operatorId: PHID
23
+ resourceTemplateId: PHID
24
+ }
25
+
26
+ # ============ Resource Template Types ============
27
+
28
+ enum RSTemplateStatus {
29
+ DRAFT
30
+ COMING_SOON
31
+ ACTIVE
32
+ DEPRECATED
33
+ }
34
+
35
+ type RSResourceTemplate {
36
+ id: PHID!
37
+ operatorId: PHID!
38
+ title: String!
39
+ summary: String!
40
+ description: String
41
+ thumbnailUrl: URL
42
+ infoLink: URL
43
+ status: RSTemplateStatus!
44
+ lastModified: DateTime!
45
+ targetAudiences: [RSTargetAudience!]!
46
+ setupServices: [String!]!
47
+ recurringServices: [String!]!
48
+ facetTargets: [RSFacetTarget!]!
49
+ services: [RSResourceService!]!
50
+ optionGroups: [RSOptionGroup!]!
51
+ faqFields: [RSFaqField!]!
52
+ contentSections: [RSContentSection!]!
53
+ }
54
+
55
+ type RSTargetAudience {
56
+ id: OID!
57
+ label: String!
58
+ color: String
59
+ }
60
+
61
+ type RSFacetTarget {
62
+ id: OID!
63
+ categoryKey: String!
64
+ categoryLabel: String!
65
+ selectedOptions: [String!]!
66
+ }
67
+
68
+ type RSResourceService {
69
+ id: OID!
70
+ title: String!
71
+ description: String
72
+ displayOrder: Int
73
+ parentServiceId: OID
74
+ isSetupFormation: Boolean!
75
+ optionGroupId: OID
76
+ facetBindings: [RSResourceFacetBinding!]!
77
+ }
78
+
79
+ type RSResourceFacetBinding {
80
+ id: OID!
81
+ facetName: String!
82
+ facetType: PHID!
83
+ supportedOptions: [OID!]!
84
+ }
85
+
86
+ type RSOptionGroup {
87
+ id: OID!
88
+ name: String!
89
+ description: String
90
+ isAddOn: Boolean!
91
+ defaultSelected: Boolean!
92
+ }
93
+
94
+ type RSFaqField {
95
+ id: OID!
96
+ question: String
97
+ answer: String
98
+ displayOrder: Int!
99
+ }
100
+
101
+ type RSContentSection {
102
+ id: OID!
103
+ title: String!
104
+ content: String!
105
+ displayOrder: Int!
106
+ }
107
+
108
+ # ============ Service Offering Types ============
109
+
110
+ enum RSServiceStatus {
111
+ DRAFT
112
+ COMING_SOON
113
+ ACTIVE
114
+ DEPRECATED
115
+ }
116
+
117
+ type RSServiceOffering {
118
+ id: PHID!
119
+ operatorId: PHID!
120
+ resourceTemplateId: PHID
121
+ title: String!
122
+ summary: String!
123
+ description: String
124
+ thumbnailUrl: URL
125
+ infoLink: URL
126
+ status: RSServiceStatus!
127
+ lastModified: DateTime!
128
+ targetAudiences: [RSTargetAudience!]!
129
+ setupServices: [String!]!
130
+ recurringServices: [String!]!
131
+ facetTargets: [RSFacetTarget!]!
132
+ services: [RSOfferingService!]!
133
+ tiers: [RSServiceSubscriptionTier!]!
134
+ optionGroups: [RSOptionGroup!]!
135
+ }
136
+
137
+ type RSOfferingService {
138
+ id: OID!
139
+ title: String!
140
+ description: String
141
+ displayOrder: Int
142
+ parentServiceId: OID
143
+ isSetupFormation: Boolean!
144
+ isPremiumExclusive: Boolean!
145
+ optionGroupId: OID
146
+ facetBindings: [RSResourceFacetBinding!]!
147
+ }
148
+
149
+ type RSServiceSubscriptionTier {
150
+ id: OID!
151
+ name: String!
152
+ description: String
153
+ isCustomPricing: Boolean!
154
+ pricing: RSServicePricing!
155
+ pricingOptions: [RSTierPricingOption!]!
156
+ serviceLevels: [RSServiceLevelBinding!]!
157
+ usageLimits: [RSServiceUsageLimit!]!
158
+ }
159
+
160
+ type RSServicePricing {
161
+ amount: Amount_Money
162
+ currency: Currency!
163
+ billingCycle: RSBillingCycle!
164
+ setupFee: Amount_Money
165
+ perSeatAmount: Amount_Money
166
+ perSeatCurrency: Currency
167
+ perSeatBillingCycle: RSBillingCycle
168
+ perSeatLabel: String
169
+ }
170
+
171
+ type RSTierPricingOption {
172
+ id: OID!
173
+ billingCycle: RSBillingCycle!
174
+ amount: Amount_Money!
175
+ currency: Currency!
176
+ setupFee: Amount_Money
177
+ isDefault: Boolean!
178
+ perSeatAmount: Amount_Money
179
+ }
180
+
181
+ enum RSBillingCycle {
182
+ MONTHLY
183
+ QUARTERLY
184
+ SEMI_ANNUAL
185
+ ANNUAL
186
+ ONE_TIME
187
+ }
188
+
189
+ type RSServiceLevelBinding {
190
+ id: OID!
191
+ serviceId: OID!
192
+ level: RSServiceLevel!
193
+ customValue: String
194
+ variations: String
195
+ annexes: String
196
+ setupFee: Amount_Money
197
+ optionGroupId: OID
198
+ }
199
+
200
+ enum RSServiceLevel {
201
+ INCLUDED
202
+ NOT_INCLUDED
203
+ OPTIONAL
204
+ CUSTOM
205
+ VARIABLE
206
+ NOT_APPLICABLE
207
+ }
208
+
209
+ type RSServiceUsageLimit {
210
+ id: OID!
211
+ serviceId: OID!
212
+ metric: String!
213
+ unitName: String
214
+ limit: Int
215
+ resetPeriod: RSResetPeriod
216
+ notes: String
217
+ unitPrice: Amount_Money
218
+ unitPriceCurrency: Currency
219
+ unitPriceBillingCycle: RSBillingCycle
220
+ }
221
+
222
+ enum RSResetPeriod {
223
+ HOURLY
224
+ DAILY
225
+ WEEKLY
226
+ MONTHLY
227
+ QUARTERLY
228
+ SEMI_ANNUAL
229
+ ANNUAL
230
+ }
231
+ `;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@powerhousedao/contributor-billing",
3
3
  "description": "Document models that help contributors of open organisations get paid anonymously for their work on a monthly basis.",
4
- "version": "0.1.44",
4
+ "version": "0.1.46",
5
5
  "license": "AGPL-3.0-only",
6
6
  "type": "module",
7
7
  "files": [