kappmaker 1.0.2 → 1.2.0

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.
Files changed (92) hide show
  1. package/README.md +481 -33
  2. package/dist/cli.js +146 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/adapty-setup.js +5 -4
  5. package/dist/commands/adapty-setup.js.map +1 -1
  6. package/dist/commands/android-release-build.d.ts +7 -0
  7. package/dist/commands/android-release-build.js +51 -0
  8. package/dist/commands/android-release-build.js.map +1 -0
  9. package/dist/commands/config.js +11 -1
  10. package/dist/commands/config.js.map +1 -1
  11. package/dist/commands/create-appstore-app.js +18 -1
  12. package/dist/commands/create-appstore-app.js.map +1 -1
  13. package/dist/commands/create-logo.js +16 -5
  14. package/dist/commands/create-logo.js.map +1 -1
  15. package/dist/commands/create-play-app.d.ts +2 -0
  16. package/dist/commands/create-play-app.js +399 -0
  17. package/dist/commands/create-play-app.js.map +1 -0
  18. package/dist/commands/create.js +138 -64
  19. package/dist/commands/create.js.map +1 -1
  20. package/dist/commands/enhance.js +12 -4
  21. package/dist/commands/enhance.js.map +1 -1
  22. package/dist/commands/fastlane-configure.d.ts +1 -0
  23. package/dist/commands/fastlane-configure.js +9 -0
  24. package/dist/commands/fastlane-configure.js.map +1 -0
  25. package/dist/commands/generate-keystore.d.ts +7 -0
  26. package/dist/commands/generate-keystore.js +14 -0
  27. package/dist/commands/generate-keystore.js.map +1 -0
  28. package/dist/commands/generate-screenshots.js +22 -7
  29. package/dist/commands/generate-screenshots.js.map +1 -1
  30. package/dist/commands/gpc.d.ts +29 -0
  31. package/dist/commands/gpc.js +174 -0
  32. package/dist/commands/gpc.js.map +1 -0
  33. package/dist/commands/publish.d.ts +10 -0
  34. package/dist/commands/publish.js +38 -0
  35. package/dist/commands/publish.js.map +1 -0
  36. package/dist/commands/refactor.d.ts +9 -0
  37. package/dist/commands/refactor.js +9 -0
  38. package/dist/commands/refactor.js.map +1 -0
  39. package/dist/commands/remove-bg.js +12 -4
  40. package/dist/commands/remove-bg.js.map +1 -1
  41. package/dist/commands/translate-screenshots.js +22 -8
  42. package/dist/commands/translate-screenshots.js.map +1 -1
  43. package/dist/commands/update-version.d.ts +5 -0
  44. package/dist/commands/update-version.js +21 -0
  45. package/dist/commands/update-version.js.map +1 -0
  46. package/dist/services/asc-monetization.service.js +39 -29
  47. package/dist/services/asc-monetization.service.js.map +1 -1
  48. package/dist/services/asc.service.d.ts +1 -1
  49. package/dist/services/asc.service.js +94 -12
  50. package/dist/services/asc.service.js.map +1 -1
  51. package/dist/services/fastlane-setup.service.d.ts +1 -0
  52. package/dist/services/fastlane-setup.service.js +50 -0
  53. package/dist/services/fastlane-setup.service.js.map +1 -0
  54. package/dist/services/fastlane.service.js +20 -8
  55. package/dist/services/fastlane.service.js.map +1 -1
  56. package/dist/services/firebase.service.js +48 -18
  57. package/dist/services/firebase.service.js.map +1 -1
  58. package/dist/services/gpc-data-safety.service.d.ts +11 -0
  59. package/dist/services/gpc-data-safety.service.js +160 -0
  60. package/dist/services/gpc-data-safety.service.js.map +1 -0
  61. package/dist/services/gpc-monetization.service.d.ts +18 -0
  62. package/dist/services/gpc-monetization.service.js +244 -0
  63. package/dist/services/gpc-monetization.service.js.map +1 -0
  64. package/dist/services/gpc.service.d.ts +87 -0
  65. package/dist/services/gpc.service.js +338 -0
  66. package/dist/services/gpc.service.js.map +1 -0
  67. package/dist/services/gradle.service.d.ts +0 -3
  68. package/dist/services/gradle.service.js +0 -24
  69. package/dist/services/gradle.service.js.map +1 -1
  70. package/dist/services/keystore.service.d.ts +6 -0
  71. package/dist/services/keystore.service.js +44 -0
  72. package/dist/services/keystore.service.js.map +1 -0
  73. package/dist/services/publish.service.d.ts +10 -0
  74. package/dist/services/publish.service.js +59 -0
  75. package/dist/services/publish.service.js.map +1 -0
  76. package/dist/services/refactor.service.d.ts +3 -0
  77. package/dist/services/refactor.service.js +207 -0
  78. package/dist/services/refactor.service.js.map +1 -0
  79. package/dist/services/version.service.d.ts +10 -0
  80. package/dist/services/version.service.js +75 -0
  81. package/dist/services/version.service.js.map +1 -0
  82. package/dist/templates/Fastfile.txt +209 -0
  83. package/dist/templates/data-safety-template.json +5483 -0
  84. package/dist/templates/googleplay-config.json +71 -0
  85. package/dist/types/googleplay.d.ts +113 -0
  86. package/dist/types/googleplay.js +2 -0
  87. package/dist/types/googleplay.js.map +1 -0
  88. package/dist/types/index.d.ts +1 -0
  89. package/dist/utils/config.d.ts +1 -0
  90. package/dist/utils/config.js +5 -0
  91. package/dist/utils/config.js.map +1 -1
  92. package/package.json +2 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gpc-data-safety.service.js","sourceRoot":"","sources":["../../src/services/gpc-data-safety.service.ts"],"names":[],"mappings":"AACA,OAAO,QAAQ,MAAM,wCAAwC,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAqBpF,MAAM,IAAI,GAAG,QAAoC,CAAC;AAElD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,kBAAkB,GAAqC;IAC3D,qEAAqE;IACrE,0CAA0C,EAAE,IAAI;IAChD,wCAAwC,EAAE,IAAI;IAE9C,uEAAuE;IACvE,qDAAqD,EAAE,IAAI;IAC3D,+DAA+D;IAC/D,4BAA4B,EAAE,KAAK;IACnC,wEAAwE;IACxE,iEAAiE;IAEjE,sEAAsE;IACtE,0CAA0C,EAAE,IAAI;IAChD,+GAA+G,EAAE,IAAI;IACrH,oEAAoE,EAAE,IAAI;IAC1E,wGAAwG,EAAE,IAAI;IAC9G,+FAA+F,EAAE,IAAI;IAErG,qEAAqE;IACrE,0CAA0C,EAAE,IAAI;IAChD,6EAA6E;IAC7E,4GAA4G,EAAE,IAAI;IAClH,iEAAiE,EAAE,IAAI;IACvE,qGAAqG,EAAE,IAAI;IAC3G,oFAAoF,EAAE,IAAI;IAC1F,4FAA4F,EAAE,IAAI;IAElG,qEAAqE;IACrE,+CAA+C,EAAE,IAAI;IACrD,6GAA6G,EAAE,IAAI;IACnH,kEAAkE,EAAE,IAAI;IACxE,sGAAsG,EAAE,IAAI;IAC5G,qFAAqF,EAAE,IAAI;IAE3F,qEAAqE;IACrE,4DAA4D,EAAE,IAAI;IAClE,0HAA0H,EAAE,IAAI;IAChI,+EAA+E,EAAE,IAAI;IACrF,mHAAmH,EAAE,IAAI;IACzH,kGAAkG,EAAE,IAAI;IAExG,oEAAoE;IACpE,sDAAsD,EAAE,IAAI;IAC5D,oHAAoH,EAAE,IAAI;IAC1H,yEAAyE,EAAE,IAAI;IAC/E,6GAA6G,EAAE,IAAI;IACnH,4FAA4F,EAAE,IAAI;IAElG,gFAAgF;IAChF,kDAAkD,EAAE,IAAI;IACxD,mHAAmH,EAAE,IAAI;IACzH,wEAAwE,EAAE,IAAI;IAC9E,4GAA4G,EAAE,IAAI;IAClH,2FAA2F,EAAE,IAAI;CAClG,CAAC;AAEF,qFAAqF;AACrF,SAAS,YAAY,CAAC,GAAW,EAAE,GAAkB;IACnD,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,GAAG,CAAC;IAC7B,OAAO,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC;AACzB,CAAC;AAED,2DAA2D;AAC3D,SAAS,kBAAkB,CAAC,GAAW;IACrC,+FAA+F;IAC/F,+EAA+E;IAC/E,gFAAgF;IAChF,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,cAAc,CACrB,QAA0C,EAC1C,SAA8D;IAE9D,MAAM,MAAM,GAAG,IAAI,GAAG,EAAmC,CAAC;IAC1D,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;QAAE,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAChE,IAAI,SAAS,EAAE,CAAC;QACd,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;YAC/C,MAAM,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,SAAS,SAAS,CAAC,MAA2B;IAC5C,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACtE,CAAC;AAED,SAAS,SAAS,CAAC,IAA+B;IAChD,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACnD,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;IACtC,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,WAAiC;IAClE,MAAM,aAAa,GAAG,WAAW,CAAC,cAAc,KAAK,KAAK,CAAC,CAAC,eAAe;IAC3E,MAAM,OAAO,GAAG,cAAc,CAC5B,aAAa,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,EACvC,WAAW,CAAC,OAAO,CACpB,CAAC;IAEF,MAAM,MAAM,GAAwB,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACxD,IAAI,GAAG,KAAK,CAAC;YAAE,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,mBAAmB;QACnD,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,AAAD,EAAG,WAAW,EAAE,KAAK,CAAC,GAAG,GAAG,CAAC;QAC7C,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACnC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEhC,IAAI,KAAK,GAAkB,IAAI,CAAC;QAChC,IAAI,MAAM,KAAK,IAAI;YAAE,KAAK,GAAG,MAAM,CAAC;aAC/B,IAAI,MAAM,KAAK,KAAK;YAAE,KAAK,GAAG,OAAO,CAAC;aACtC,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,KAAK,GAAG,MAAM,CAAC;QACpD,iCAAiC;QAEjC,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC;AAC3B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,WAAiC;IACvE,MAAM,OAAO,GAAG,cAAc,CAC5B,WAAW,CAAC,cAAc,KAAK,KAAK,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAC9D,WAAW,CAAC,OAAO,CACpB,CAAC;IACF,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,AAAD,EAAG,WAAW,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAC1C,IAAI,WAAW,KAAK,UAAU;YAAE,SAAS;QACzC,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACnC,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC3B,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI;YAAE,OAAO,EAAE,CAAC;IAC/C,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { GooglePlaySubscription, GooglePlayInAppProduct } from '../types/googleplay.js';
2
+ interface Money {
3
+ currencyCode: string;
4
+ units: string;
5
+ nanos: number;
6
+ }
7
+ /**
8
+ * Convert a human-readable price like "6.99" into the Google Play money
9
+ * representation: { currencyCode, units, nanos }. Nanos are billionths,
10
+ * so "6.99" becomes { units: "6", nanos: 990000000 }.
11
+ */
12
+ export declare function priceToMoney(price: string, currencyCode: string): Money;
13
+ export declare function listSubscriptions(packageName: string): Promise<Set<string>>;
14
+ export declare function setupSubscriptions(packageName: string, subscriptions: GooglePlaySubscription[], playDefaultLanguage: string): Promise<void>;
15
+ export declare function activateBasePlan(packageName: string, productId: string, basePlanId: string): Promise<void>;
16
+ export declare function listInAppProducts(packageName: string): Promise<Set<string>>;
17
+ export declare function setupInAppProducts(packageName: string, products: GooglePlayInAppProduct[]): Promise<void>;
18
+ export {};
@@ -0,0 +1,244 @@
1
+ import { logger } from '../utils/logger.js';
2
+ import { apiRequest } from './gpc.service.js';
3
+ /**
4
+ * Convert a human-readable price like "6.99" into the Google Play money
5
+ * representation: { currencyCode, units, nanos }. Nanos are billionths,
6
+ * so "6.99" becomes { units: "6", nanos: 990000000 }.
7
+ */
8
+ export function priceToMoney(price, currencyCode) {
9
+ const [wholeRaw, fractionRaw = ''] = price.trim().split('.');
10
+ const whole = wholeRaw.replace(/^-/, '') || '0';
11
+ // Pad or truncate fractional part to 9 digits (nanos)
12
+ const fractionPadded = (fractionRaw + '000000000').slice(0, 9);
13
+ const nanos = Number(fractionPadded) || 0;
14
+ return {
15
+ currencyCode,
16
+ units: whole,
17
+ nanos: price.startsWith('-') ? -nanos : nanos,
18
+ };
19
+ }
20
+ function buildRegionalConfigs(prices) {
21
+ const out = {};
22
+ for (const p of prices) {
23
+ out[p.region_code] = {
24
+ newSubscriberAvailability: true,
25
+ price: priceToMoney(p.price, p.currency_code),
26
+ };
27
+ }
28
+ return out;
29
+ }
30
+ export async function listSubscriptions(packageName) {
31
+ const result = await apiRequest({
32
+ method: 'GET',
33
+ path: `/applications/${encodeURIComponent(packageName)}/subscriptions`,
34
+ label: 'Looking up existing subscriptions',
35
+ allowFailure: true,
36
+ });
37
+ if (!result.ok || !result.data?.subscriptions)
38
+ return new Set();
39
+ return new Set(result.data.subscriptions.map((s) => s.productId));
40
+ }
41
+ export async function setupSubscriptions(packageName, subscriptions, playDefaultLanguage) {
42
+ if (subscriptions.length === 0) {
43
+ logger.info('No subscriptions configured, skipping.');
44
+ return;
45
+ }
46
+ const existing = await listSubscriptions(packageName);
47
+ for (const sub of subscriptions) {
48
+ if (existing.has(sub.product_id)) {
49
+ logger.info(`Subscription "${sub.product_id}" already exists, skipping create.`);
50
+ // Still (best-effort) try to activate any base plans that aren't active.
51
+ for (const basePlan of sub.base_plans) {
52
+ await activateBasePlan(packageName, sub.product_id, basePlan.base_plan_id);
53
+ }
54
+ continue;
55
+ }
56
+ await createSubscriptionWithBasePlans(packageName, sub, playDefaultLanguage);
57
+ }
58
+ }
59
+ // Google Play's new monetization API ties pricing regions to a "regionsVersion"
60
+ // — bump this constant if Google publishes a newer region catalog.
61
+ const REGIONS_VERSION = '2022/02';
62
+ async function createSubscriptionWithBasePlans(packageName, sub, playDefaultLanguage) {
63
+ // Play rejects subscriptions that don't have a listing in the app's current
64
+ // default language. If the config's listings don't cover it, clone the first
65
+ // entry with the Play default language tacked on.
66
+ const listings = [...sub.listings];
67
+ const hasDefault = listings.some((l) => l.locale === playDefaultLanguage);
68
+ if (!hasDefault && listings.length > 0) {
69
+ const first = listings[0];
70
+ listings.unshift({
71
+ locale: playDefaultLanguage,
72
+ title: first.title,
73
+ description: first.description,
74
+ benefits: first.benefits,
75
+ });
76
+ logger.info(`Cloned "${first.locale}" listing to "${playDefaultLanguage}" (Play default language).`);
77
+ }
78
+ // Create subscription + base plans in a single call. The new monetization API
79
+ // requires productId and regionsVersion.version as QUERY PARAMETERS (not body)
80
+ // — passing productId in the body triggers "Product ID must be specified".
81
+ const body = {
82
+ packageName,
83
+ productId: sub.product_id,
84
+ listings: listings.map((l) => ({
85
+ languageCode: l.locale,
86
+ title: l.title,
87
+ description: l.description ?? '',
88
+ benefits: l.benefits ?? [],
89
+ })),
90
+ basePlans: sub.base_plans.map((bp) => buildBasePlanBody(bp)),
91
+ };
92
+ const result = await apiRequest({
93
+ method: 'POST',
94
+ path: `/applications/${encodeURIComponent(packageName)}/subscriptions`,
95
+ query: {
96
+ productId: sub.product_id,
97
+ 'regionsVersion.version': REGIONS_VERSION,
98
+ },
99
+ body,
100
+ label: `Creating subscription: ${sub.product_id}`,
101
+ allowFailure: true,
102
+ });
103
+ if (!result.ok) {
104
+ logger.warn(`Could not create subscription ${sub.product_id}. Skipping its base plans.`);
105
+ return;
106
+ }
107
+ // 2. Activate each base plan so it's available to buyers
108
+ for (const basePlan of sub.base_plans) {
109
+ await activateBasePlan(packageName, sub.product_id, basePlan.base_plan_id);
110
+ }
111
+ }
112
+ function buildBasePlanBody(basePlan) {
113
+ const body = {
114
+ basePlanId: basePlan.base_plan_id,
115
+ state: 'DRAFT', // activated in a separate call
116
+ autoRenewingBasePlanType: {
117
+ billingPeriodDuration: basePlan.billing_period,
118
+ resubscribeState: 'RESUBSCRIBE_STATE_ACTIVE',
119
+ ...(basePlan.grace_period ? { gracePeriodDuration: basePlan.grace_period } : {}),
120
+ },
121
+ regionalConfigs: Object.entries(buildRegionalConfigs(basePlan.regional_configs)).map(([region, cfg]) => ({
122
+ regionCode: region,
123
+ newSubscriberAvailability: cfg.newSubscriberAvailability,
124
+ price: cfg.price,
125
+ })),
126
+ };
127
+ return body;
128
+ }
129
+ export async function activateBasePlan(packageName, productId, basePlanId) {
130
+ await apiRequest({
131
+ method: 'POST',
132
+ path: `/applications/${encodeURIComponent(packageName)}/subscriptions/${encodeURIComponent(productId)}/basePlans/${encodeURIComponent(basePlanId)}:activate`,
133
+ body: {},
134
+ label: `Activating base plan ${productId}/${basePlanId}`,
135
+ allowFailure: true,
136
+ });
137
+ }
138
+ export async function listInAppProducts(packageName) {
139
+ const existing = new Set();
140
+ let pageToken;
141
+ do {
142
+ const result = await apiRequest({
143
+ method: 'GET',
144
+ path: `/applications/${encodeURIComponent(packageName)}/oneTimeProducts`,
145
+ query: pageToken ? { pageToken } : undefined,
146
+ label: 'Looking up existing one-time products',
147
+ allowFailure: true,
148
+ });
149
+ if (!result.ok)
150
+ return existing;
151
+ for (const p of result.data?.oneTimeProducts ?? []) {
152
+ existing.add(p.productId);
153
+ }
154
+ pageToken = result.data?.nextPageToken;
155
+ } while (pageToken);
156
+ return existing;
157
+ }
158
+ export async function setupInAppProducts(packageName, products) {
159
+ if (products.length === 0) {
160
+ logger.info('No one-time in-app products configured, skipping.');
161
+ return;
162
+ }
163
+ const existing = await listInAppProducts(packageName);
164
+ for (const product of products) {
165
+ if (existing.has(product.sku)) {
166
+ logger.info(`One-time product "${product.sku}" already exists, skipping.`);
167
+ continue;
168
+ }
169
+ await createInAppProduct(packageName, product);
170
+ }
171
+ }
172
+ async function createInAppProduct(packageName, product) {
173
+ const listings = product.listings.map((loc) => ({
174
+ languageCode: loc.locale,
175
+ title: loc.title,
176
+ description: loc.description ?? '',
177
+ }));
178
+ // Build one purchase option with regional pricing from the config.
179
+ // We default to a single "default" purchase option covering the base price
180
+ // and any per-region overrides the user supplied.
181
+ const allPrices = [product.default_price, ...(product.prices ?? [])];
182
+ // Dedupe by region — if the user listed the same region twice, last wins.
183
+ const byRegion = new Map();
184
+ for (const p of allPrices)
185
+ byRegion.set(p.region_code, p);
186
+ const regionalPricingAndAvailabilityConfigs = Array.from(byRegion.values()).map((p) => ({
187
+ regionCode: p.region_code,
188
+ price: priceToMoney(p.price, p.currency_code),
189
+ availability: 'AVAILABLE',
190
+ }));
191
+ const body = {
192
+ packageName,
193
+ productId: product.sku,
194
+ listings,
195
+ purchaseOptions: [
196
+ {
197
+ purchaseOptionId: 'default',
198
+ buyOption: { legacyCompatible: true },
199
+ regionalPricingAndAvailabilityConfigs,
200
+ },
201
+ ],
202
+ };
203
+ // Note: patch path is lowercase `onetimeproducts` even though list/get use
204
+ // camelCase `oneTimeProducts`. Matches Google's v3 discovery document.
205
+ const result = await apiRequest({
206
+ method: 'PATCH',
207
+ path: `/applications/${encodeURIComponent(packageName)}/onetimeproducts/${encodeURIComponent(product.sku)}`,
208
+ query: {
209
+ allowMissing: 'true',
210
+ 'regionsVersion.version': REGIONS_VERSION,
211
+ updateMask: 'listings,purchaseOptions',
212
+ },
213
+ body,
214
+ label: `Creating one-time product: ${product.sku}`,
215
+ allowFailure: true,
216
+ });
217
+ if (!result.ok) {
218
+ logger.warn(`Could not create one-time product ${product.sku}.`);
219
+ return;
220
+ }
221
+ // New purchase options land in DRAFT state — activate so buyers can see it.
222
+ await activatePurchaseOption(packageName, product.sku, 'default');
223
+ }
224
+ async function activatePurchaseOption(packageName, productId, purchaseOptionId) {
225
+ await apiRequest({
226
+ method: 'POST',
227
+ path: `/applications/${encodeURIComponent(packageName)}/oneTimeProducts/${encodeURIComponent(productId)}/purchaseOptions:batchUpdateStates`,
228
+ body: {
229
+ requests: [
230
+ {
231
+ activatePurchaseOptionRequest: {
232
+ packageName,
233
+ productId,
234
+ purchaseOptionId,
235
+ latencyTolerance: 'PRODUCT_UPDATE_LATENCY_TOLERANCE_LATENCY_SENSITIVE',
236
+ },
237
+ },
238
+ ],
239
+ },
240
+ label: `Activating purchase option ${productId}/${purchaseOptionId}`,
241
+ allowFailure: true,
242
+ });
243
+ }
244
+ //# sourceMappingURL=gpc-monetization.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gpc-monetization.service.js","sourceRoot":"","sources":["../../src/services/gpc-monetization.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ import type { GooglePlayAppDetails, GooglePlayListing } from '../types/googleplay.js';
2
+ export declare const PLAY_CONSOLE_URL = "https://play.google.com/console/u/0/developers";
3
+ export declare function getAccessToken(): Promise<string>;
4
+ export interface ApiRequestOptions {
5
+ method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
6
+ path: string;
7
+ query?: Record<string, string | undefined>;
8
+ body?: unknown;
9
+ /** Swallow non-2xx responses and return null instead of exiting. */
10
+ allowFailure?: boolean;
11
+ label?: string;
12
+ }
13
+ export interface ApiResponse<T> {
14
+ ok: boolean;
15
+ status: number;
16
+ data: T | null;
17
+ error?: string;
18
+ }
19
+ export declare function apiRequest<T = unknown>(options: ApiRequestOptions): Promise<ApiResponse<T>>;
20
+ /**
21
+ * Probe whether an app exists on Play Console WITHOUT starting an edit.
22
+ * Uses GET /subscriptions (the new monetization API) which is read-only and
23
+ * works on apps that have been migrated to the new publishing API. The older
24
+ * `/inappproducts` endpoint returns 403 "Please migrate to the new publishing
25
+ * API" for such apps, so we avoid it here.
26
+ *
27
+ * Returns true on 200, false on 404, exits fatal on any other error.
28
+ */
29
+ export declare function checkAppExists(packageName: string): Promise<boolean>;
30
+ export declare function validateServiceAccount(): Promise<void>;
31
+ export interface AppEdit {
32
+ id: string;
33
+ expiryTimeSeconds?: string;
34
+ }
35
+ export declare function insertEdit(packageName: string): Promise<string>;
36
+ export declare function commitEdit(packageName: string, editId: string): Promise<void>;
37
+ export declare function deleteEdit(packageName: string, editId: string): Promise<void>;
38
+ export interface PlayAppDetails {
39
+ defaultLanguage?: string;
40
+ contactWebsite?: string;
41
+ contactEmail?: string;
42
+ contactPhone?: string;
43
+ }
44
+ /**
45
+ * Read current app details (default language + contact info) inside an existing
46
+ * edit. Used to discover the app's actual default language before pushing
47
+ * subscriptions — Play rejects subscriptions that don't have a listing in that
48
+ * language, so the caller needs to ensure one exists.
49
+ */
50
+ export declare function getEditDetails(packageName: string, editId: string): Promise<PlayAppDetails | null>;
51
+ /**
52
+ * Probe Play Console for the app's current default language via a short-lived
53
+ * edit (insert → get details → delete). Returns null if the probe fails so
54
+ * callers can fall back to whatever default they had in their config.
55
+ */
56
+ export declare function fetchDefaultLanguage(packageName: string): Promise<string | null>;
57
+ export interface PlayAppState {
58
+ defaultLanguage: string | null;
59
+ hasUploadedBuild: boolean;
60
+ tracksWithReleases: string[];
61
+ }
62
+ /**
63
+ * One-shot probe that starts an edit, reads the details and tracks, and
64
+ * discards the edit — returns everything the orchestrator needs to know about
65
+ * the app's current state in a single transaction. Useful for pre-flight
66
+ * checks before monetization writes.
67
+ *
68
+ * Graceful: returns null if the probe fails (no network, restricted service
69
+ * account, etc.).
70
+ */
71
+ export declare function fetchAppState(packageName: string): Promise<PlayAppState | null>;
72
+ export declare function withEdit<T>(packageName: string, fn: (editId: string) => Promise<T>): Promise<T>;
73
+ export declare function updateAppDetails(packageName: string, editId: string, defaultLanguage: string, details: GooglePlayAppDetails): Promise<void>;
74
+ export declare function updateListing(packageName: string, editId: string, listing: GooglePlayListing): Promise<void>;
75
+ /**
76
+ * Upload a Play Console Data Safety declaration. The API does NOT take
77
+ * structured JSON — it takes a JSON object with a single `safetyLabels` field
78
+ * whose value is the raw CSV content exported from Play Console:
79
+ *
80
+ * POST /applications/{pkg}/dataSafety
81
+ * body: { "safetyLabels": "<csv file contents as string>" }
82
+ *
83
+ * The CSV is app-specific (Google generates different question sets based on
84
+ * the app's category/permissions), so callers must provide the contents of a
85
+ * real CSV exported from this app's Play Console page.
86
+ */
87
+ export declare function updateDataSafety(packageName: string, csvContents: string): Promise<void>;