slowlane 1.0.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.
@@ -0,0 +1,175 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.GooglePlayClient = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const googleapis_1 = require("googleapis");
40
+ class GooglePlayClient {
41
+ auth;
42
+ publisher;
43
+ constructor(config, configDir) {
44
+ const keyPath = path.isAbsolute(config.service_account_path)
45
+ ? config.service_account_path
46
+ : path.join(configDir, config.service_account_path);
47
+ const keyFile = JSON.parse(fs.readFileSync(keyPath, 'utf-8'));
48
+ this.auth = new googleapis_1.google.auth.JWT({
49
+ email: keyFile.client_email,
50
+ key: keyFile.private_key,
51
+ scopes: [
52
+ 'https://www.googleapis.com/auth/playdeveloperreporting',
53
+ 'https://www.googleapis.com/auth/androidpublisher',
54
+ ],
55
+ });
56
+ this.publisher = googleapis_1.google.androidpublisher({ version: 'v3', auth: this.auth });
57
+ }
58
+ async listApps() {
59
+ const accessToken = await this.auth.getAccessToken();
60
+ const response = await fetch('https://playdeveloperreporting.googleapis.com/v1beta1/apps:search', {
61
+ headers: {
62
+ Authorization: `Bearer ${accessToken.token}`,
63
+ },
64
+ });
65
+ if (!response.ok) {
66
+ const errorText = await response.text();
67
+ throw new Error(`Google Play API error: ${response.status} ${response.statusText}\n${errorText}`);
68
+ }
69
+ const data = (await response.json());
70
+ return (data.apps ?? []).map(app => ({
71
+ packageName: app.packageName,
72
+ displayName: app.displayName,
73
+ }));
74
+ }
75
+ async getMetadata(packageName) {
76
+ // Create an edit to read the current state
77
+ const editResponse = await this.publisher.edits.insert({ packageName });
78
+ const editId = editResponse.data.id;
79
+ try {
80
+ // Get app details for default language
81
+ const detailsResponse = await this.publisher.edits.details.get({
82
+ packageName,
83
+ editId,
84
+ });
85
+ // Get all listings
86
+ const listingsResponse = await this.publisher.edits.listings.list({
87
+ packageName,
88
+ editId,
89
+ });
90
+ const listings = (listingsResponse.data.listings ?? []).map(listing => ({
91
+ language: listing.language,
92
+ title: listing.title ?? undefined,
93
+ shortDescription: listing.shortDescription ?? undefined,
94
+ fullDescription: listing.fullDescription ?? undefined,
95
+ video: listing.video ?? undefined,
96
+ }));
97
+ // Sort by language
98
+ listings.sort((a, b) => a.language.localeCompare(b.language));
99
+ return {
100
+ packageName,
101
+ defaultLanguage: detailsResponse.data.defaultLanguage ?? undefined,
102
+ listings,
103
+ };
104
+ }
105
+ finally {
106
+ // Delete the edit since we're just reading
107
+ await this.publisher.edits.delete({ packageName, editId });
108
+ }
109
+ }
110
+ async setMetadata(packageName, listings, options = {}) {
111
+ const { sendForReview = true } = options;
112
+ // Create an edit to make changes
113
+ const editResponse = await this.publisher.edits.insert({ packageName });
114
+ const editId = editResponse.data.id;
115
+ const result = {
116
+ listingsUpdated: [],
117
+ listingsCreated: [],
118
+ };
119
+ try {
120
+ // Get existing listings to know which languages already exist
121
+ const existingListingsResponse = await this.publisher.edits.listings.list({
122
+ packageName,
123
+ editId,
124
+ });
125
+ const existingLanguages = new Set((existingListingsResponse.data.listings ?? []).map(l => l.language));
126
+ for (const listing of listings) {
127
+ // Build request body with only the fields that are present
128
+ const requestBody = {};
129
+ if ('title' in listing)
130
+ requestBody.title = listing.title;
131
+ if ('shortDescription' in listing)
132
+ requestBody.shortDescription = listing.shortDescription;
133
+ if ('fullDescription' in listing)
134
+ requestBody.fullDescription = listing.fullDescription;
135
+ if ('video' in listing)
136
+ requestBody.video = listing.video;
137
+ if (existingLanguages.has(listing.language)) {
138
+ // Use patch to update only provided fields
139
+ await this.publisher.edits.listings.patch({
140
+ packageName,
141
+ editId,
142
+ language: listing.language,
143
+ requestBody,
144
+ });
145
+ result.listingsUpdated.push(listing.language);
146
+ }
147
+ else {
148
+ // Use update to create new listing (requires language in body)
149
+ requestBody.language = listing.language;
150
+ await this.publisher.edits.listings.update({
151
+ packageName,
152
+ editId,
153
+ language: listing.language,
154
+ requestBody,
155
+ });
156
+ result.listingsCreated.push(listing.language);
157
+ }
158
+ }
159
+ // Commit the edit to apply changes
160
+ await this.publisher.edits.commit({
161
+ packageName,
162
+ editId,
163
+ changesNotSentForReview: !sendForReview,
164
+ });
165
+ return result;
166
+ }
167
+ catch (error) {
168
+ // Delete the edit if something went wrong
169
+ await this.publisher.edits.delete({ packageName, editId }).catch(() => { });
170
+ throw error;
171
+ }
172
+ }
173
+ }
174
+ exports.GooglePlayClient = GooglePlayClient;
175
+ //# sourceMappingURL=googleplay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"googleplay.js","sourceRoot":"","sources":["../../src/googleplay.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,249 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ var __importDefault = (this && this.__importDefault) || function (mod) {
37
+ return (mod && mod.__esModule) ? mod : { "default": mod };
38
+ };
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ const yargs_1 = __importDefault(require("yargs"));
41
+ const helpers_1 = require("yargs/helpers");
42
+ const fs = __importStar(require("fs"));
43
+ const config_js_1 = require("./config.js");
44
+ const appstoreconnect_js_1 = require("./appstoreconnect.js");
45
+ const output_js_1 = require("./output.js");
46
+ const googleplay_js_1 = require("./googleplay.js");
47
+ function requireAppleConfig(argv) {
48
+ const { config, configDir } = (0, config_js_1.loadConfig)(argv.config);
49
+ if (!config.appstore_connect) {
50
+ throw new Error('Missing [appstore_connect] section in config');
51
+ }
52
+ return { config: config.appstore_connect, configDir };
53
+ }
54
+ const appleCommand = {
55
+ command: 'apple',
56
+ describe: 'App Store Connect commands',
57
+ builder: (y) => {
58
+ return y
59
+ .command({
60
+ command: 'list-apps',
61
+ describe: 'List all apps in App Store Connect',
62
+ handler: async (argv) => {
63
+ const { config, configDir } = requireAppleConfig(argv);
64
+ const client = new appstoreconnect_js_1.AppStoreConnectClient(config, configDir);
65
+ const apps = await client.listApps();
66
+ (0, output_js_1.outputAppList)(apps, { json: argv.json });
67
+ },
68
+ })
69
+ .command({
70
+ command: 'get-metadata <bundleId> [locale]',
71
+ describe: 'Get app metadata (all languages, or full details for one)',
72
+ builder: yargs => yargs
73
+ .positional('bundleId', {
74
+ describe: 'The bundle ID of the app',
75
+ type: 'string',
76
+ demandOption: true,
77
+ })
78
+ .positional('locale', {
79
+ describe: 'Locale to show in full (e.g., en-US)',
80
+ type: 'string',
81
+ })
82
+ .option('from', {
83
+ describe: 'Which version to fetch localizations from',
84
+ choices: ['live', 'editable'],
85
+ default: 'editable',
86
+ }),
87
+ handler: async (argv) => {
88
+ const { config, configDir } = requireAppleConfig(argv);
89
+ const client = new appstoreconnect_js_1.AppStoreConnectClient(config, configDir);
90
+ const metadata = await client.getAppMetadata(argv.bundleId, argv.from);
91
+ (0, output_js_1.outputMetadata)(metadata, argv.locale, argv.from, { json: argv.json });
92
+ },
93
+ })
94
+ .command({
95
+ command: 'create-version <bundleId> <versionString>',
96
+ describe: 'Create a new App Store version',
97
+ builder: yargs => yargs
98
+ .positional('bundleId', {
99
+ describe: 'The bundle ID of the app',
100
+ type: 'string',
101
+ demandOption: true,
102
+ })
103
+ .positional('versionString', {
104
+ describe: 'Version string (e.g., 1.2.0)',
105
+ type: 'string',
106
+ demandOption: true,
107
+ })
108
+ .option('platform', {
109
+ describe: 'Platform (defaults to latest version platform)',
110
+ choices: ['IOS', 'MAC_OS', 'TV_OS', 'VISION_OS'],
111
+ type: 'string',
112
+ }),
113
+ handler: async (argv) => {
114
+ const { config, configDir } = requireAppleConfig(argv);
115
+ const client = new appstoreconnect_js_1.AppStoreConnectClient(config, configDir);
116
+ const version = await client.createVersion(argv.bundleId, argv.versionString, argv.platform);
117
+ (0, output_js_1.outputVersion)(version, { json: argv.json });
118
+ },
119
+ })
120
+ .command({
121
+ command: 'set-metadata <bundleId>',
122
+ describe: 'Update app metadata from a JSON file',
123
+ builder: yargs => yargs
124
+ .positional('bundleId', {
125
+ describe: 'The bundle ID of the app',
126
+ type: 'string',
127
+ demandOption: true,
128
+ })
129
+ .option('filename', {
130
+ alias: 'f',
131
+ describe: 'JSON file containing metadata (same format as show-metadata output)',
132
+ type: 'string',
133
+ demandOption: true,
134
+ }),
135
+ handler: async (argv) => {
136
+ const { config, configDir } = requireAppleConfig(argv);
137
+ const client = new appstoreconnect_js_1.AppStoreConnectClient(config, configDir);
138
+ const fileContent = fs.readFileSync(argv.filename, 'utf-8');
139
+ const metadata = JSON.parse(fileContent);
140
+ if (!metadata.localizations || !Array.isArray(metadata.localizations)) {
141
+ throw new Error('Invalid metadata file: expected "localizations" array');
142
+ }
143
+ const result = await client.setMetadata(argv.bundleId, metadata.localizations);
144
+ (0, output_js_1.outputSetMetadataResult)(result, { json: argv.json });
145
+ },
146
+ });
147
+ },
148
+ handler: () => {
149
+ console.log('Use "slowlane apple --help" for available commands');
150
+ },
151
+ };
152
+ function requireGoogleConfig(argv) {
153
+ const { config, configDir } = (0, config_js_1.loadConfig)(argv.config);
154
+ if (!config.google_play) {
155
+ throw new Error('Missing [google_play] section in config');
156
+ }
157
+ return { config: config.google_play, configDir };
158
+ }
159
+ const googleCommand = {
160
+ command: 'google',
161
+ describe: 'Google Play commands',
162
+ builder: (y) => {
163
+ return y
164
+ .command({
165
+ command: 'list-apps',
166
+ describe: 'List all apps',
167
+ handler: async (argv) => {
168
+ const { config, configDir } = requireGoogleConfig(argv);
169
+ const client = new googleplay_js_1.GooglePlayClient(config, configDir);
170
+ const apps = await client.listApps();
171
+ (0, output_js_1.outputGooglePlayAppList)(apps, { json: argv.json });
172
+ },
173
+ })
174
+ .command({
175
+ command: 'get-metadata <packageName> [language]',
176
+ describe: 'Get app metadata (all languages, or full details for one)',
177
+ builder: yargs => yargs
178
+ .positional('packageName', {
179
+ describe: 'The package name of the app',
180
+ type: 'string',
181
+ demandOption: true,
182
+ })
183
+ .positional('language', {
184
+ describe: 'Language to show in full (e.g., en-US)',
185
+ type: 'string',
186
+ }),
187
+ handler: async (argv) => {
188
+ const { config, configDir } = requireGoogleConfig(argv);
189
+ const client = new googleplay_js_1.GooglePlayClient(config, configDir);
190
+ const metadata = await client.getMetadata(argv.packageName);
191
+ (0, output_js_1.outputGooglePlayMetadata)(metadata, argv.language, { json: argv.json });
192
+ },
193
+ })
194
+ .command({
195
+ command: 'set-metadata <packageName>',
196
+ describe: 'Update app metadata from a JSON file',
197
+ builder: yargs => yargs
198
+ .positional('packageName', {
199
+ describe: 'The package name of the app',
200
+ type: 'string',
201
+ demandOption: true,
202
+ })
203
+ .option('filename', {
204
+ alias: 'f',
205
+ describe: 'JSON file containing metadata (same format as get-metadata output)',
206
+ type: 'string',
207
+ demandOption: true,
208
+ })
209
+ .option('send-for-review', {
210
+ describe: 'Send changes for review immediately',
211
+ type: 'boolean',
212
+ default: false,
213
+ }),
214
+ handler: async (argv) => {
215
+ const { config, configDir } = requireGoogleConfig(argv);
216
+ const client = new googleplay_js_1.GooglePlayClient(config, configDir);
217
+ const fileContent = fs.readFileSync(argv.filename, 'utf-8');
218
+ const metadata = JSON.parse(fileContent);
219
+ if (!metadata.listings || !Array.isArray(metadata.listings)) {
220
+ throw new Error('Invalid metadata file: expected "listings" array');
221
+ }
222
+ const result = await client.setMetadata(argv.packageName, metadata.listings, { sendForReview: argv.sendForReview });
223
+ (0, output_js_1.outputGooglePlaySetMetadataResult)(result, { json: argv.json });
224
+ },
225
+ });
226
+ },
227
+ handler: () => {
228
+ console.log('Use "slowlane google --help" for available commands');
229
+ },
230
+ };
231
+ (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
232
+ .scriptName('slowlane')
233
+ .option('config', {
234
+ alias: 'c',
235
+ type: 'string',
236
+ description: 'Path to config file',
237
+ })
238
+ .option('json', {
239
+ type: 'boolean',
240
+ description: 'Output in JSON format',
241
+ default: false,
242
+ })
243
+ .command(appleCommand)
244
+ .command(googleCommand)
245
+ .demandCommand(1, 'You need to specify a command')
246
+ .strict()
247
+ .help()
248
+ .parse();
249
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import { App, AppMetadata, AppStoreVersion, LocalizedMetadata, Platform, SetMetadataResult } from './appstoreconnect.js';
2
+ import { GooglePlayApp, GooglePlayMetadata, GooglePlaySetMetadataResult } from './googleplay.js';
3
+ export interface OutputOptions {
4
+ json?: boolean;
5
+ }
6
+ export declare function outputJson(data: unknown): void;
7
+ export interface AppListOutput {
8
+ name: string;
9
+ bundleId: string;
10
+ sku: string;
11
+ id: string;
12
+ }
13
+ export declare function outputAppList(apps: App[], options: OutputOptions): void;
14
+ export interface VersionInfo {
15
+ versionString: string;
16
+ state: string;
17
+ }
18
+ export interface MetadataOutput {
19
+ name: string;
20
+ bundleId: string;
21
+ primaryLocale: string;
22
+ liveVersion?: VersionInfo;
23
+ editableVersion?: VersionInfo;
24
+ localizationsFrom: 'live' | 'editable';
25
+ localizations: LocalizedMetadata[];
26
+ }
27
+ export declare function outputMetadata(metadata: AppMetadata, locale: string | undefined, from: "live" | "editable" | undefined, options: OutputOptions): void;
28
+ export interface VersionOutput {
29
+ id: string;
30
+ versionString: string;
31
+ platform: Platform;
32
+ state: string;
33
+ createdDate: string;
34
+ }
35
+ export declare function outputVersion(version: AppStoreVersion, options: OutputOptions): void;
36
+ export declare function outputSetMetadataResult(result: SetMetadataResult, options: OutputOptions): void;
37
+ export declare function outputGooglePlayAppList(apps: GooglePlayApp[], options: OutputOptions): void;
38
+ export declare function outputGooglePlayMetadata(metadata: GooglePlayMetadata, language: string | undefined, options: OutputOptions): void;
39
+ export declare function outputGooglePlaySetMetadataResult(result: GooglePlaySetMetadataResult, options: OutputOptions): void;