farm-orchestrator 1.0.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/README.md +276 -0
- package/dist/src/bundle.js +1 -0
- package/dist/src/scripts/db-utils.d.ts +2 -0
- package/dist/src/scripts/db-utils.js +191 -0
- package/dist/src/scripts/prepare-wda.d.ts +16 -0
- package/dist/src/scripts/prepare-wda.js +609 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +115 -0
package/README.md
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
# @device-farm/hub
|
|
2
|
+
|
|
3
|
+
Hub package with PostgreSQL database support using Sequelize ORM.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- PostgreSQL database connection management
|
|
8
|
+
- Sequelize ORM integration
|
|
9
|
+
- Type-safe database configuration
|
|
10
|
+
- Connection pooling
|
|
11
|
+
- Model initialization support
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
Dependencies are managed at the root level. Run:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
### Basic Setup
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { Database, initializeModels } from '@device-farm/hub';
|
|
27
|
+
|
|
28
|
+
// Create database instance
|
|
29
|
+
const db = new Database({
|
|
30
|
+
host: 'localhost',
|
|
31
|
+
port: 5432,
|
|
32
|
+
database: 'device_farm',
|
|
33
|
+
username: 'postgres',
|
|
34
|
+
password: 'password',
|
|
35
|
+
pool: {
|
|
36
|
+
max: 5,
|
|
37
|
+
min: 0,
|
|
38
|
+
acquire: 30000,
|
|
39
|
+
idle: 10000,
|
|
40
|
+
},
|
|
41
|
+
logging: console.log, // Optional: log SQL queries
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Initialize models
|
|
45
|
+
initializeModels(db.getSequelize());
|
|
46
|
+
|
|
47
|
+
// Connect to database
|
|
48
|
+
await db.connect();
|
|
49
|
+
|
|
50
|
+
// Sync models (development only - use migrations in production)
|
|
51
|
+
await db.sync({ alter: true });
|
|
52
|
+
|
|
53
|
+
// ... use your database connection
|
|
54
|
+
|
|
55
|
+
// Disconnect when done
|
|
56
|
+
await db.disconnect();
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Creating Models
|
|
60
|
+
|
|
61
|
+
Create models in `src/models/` directory:
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
import { Model, DataTypes, Sequelize } from 'sequelize';
|
|
65
|
+
|
|
66
|
+
export class User extends Model {
|
|
67
|
+
public id!: number;
|
|
68
|
+
public name!: string;
|
|
69
|
+
public email!: string;
|
|
70
|
+
public readonly createdAt!: Date;
|
|
71
|
+
public readonly updatedAt!: Date;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export const initUser = (sequelize: Sequelize): typeof User => {
|
|
75
|
+
User.init(
|
|
76
|
+
{
|
|
77
|
+
id: {
|
|
78
|
+
type: DataTypes.INTEGER,
|
|
79
|
+
autoIncrement: true,
|
|
80
|
+
primaryKey: true,
|
|
81
|
+
},
|
|
82
|
+
name: {
|
|
83
|
+
type: DataTypes.STRING,
|
|
84
|
+
allowNull: false,
|
|
85
|
+
},
|
|
86
|
+
email: {
|
|
87
|
+
type: DataTypes.STRING,
|
|
88
|
+
allowNull: false,
|
|
89
|
+
unique: true,
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
sequelize,
|
|
94
|
+
modelName: 'User',
|
|
95
|
+
tableName: 'users',
|
|
96
|
+
}
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
return User;
|
|
100
|
+
};
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Then register it in `src/models/index.ts`:
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
import { initUser } from './user';
|
|
107
|
+
|
|
108
|
+
export const initializeModels = (sequelize: Sequelize): void => {
|
|
109
|
+
initUser(sequelize);
|
|
110
|
+
// Add more models here
|
|
111
|
+
};
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Configuration
|
|
115
|
+
|
|
116
|
+
### Environment Variables
|
|
117
|
+
|
|
118
|
+
It's recommended to use environment variables for database configuration:
|
|
119
|
+
|
|
120
|
+
```env
|
|
121
|
+
DB_HOST=localhost
|
|
122
|
+
DB_PORT=5432
|
|
123
|
+
DB_NAME=device_farm
|
|
124
|
+
DB_USER=postgres
|
|
125
|
+
DB_PASSWORD=your_password
|
|
126
|
+
DB_POOL_MAX=5
|
|
127
|
+
DB_POOL_MIN=0
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Then use them in your code:
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
const db = new Database({
|
|
134
|
+
host: process.env.DB_HOST || 'localhost',
|
|
135
|
+
port: parseInt(process.env.DB_PORT || '5432', 10),
|
|
136
|
+
database: process.env.DB_NAME || 'device_farm',
|
|
137
|
+
username: process.env.DB_USER || 'postgres',
|
|
138
|
+
password: process.env.DB_PASSWORD || '',
|
|
139
|
+
pool: {
|
|
140
|
+
max: parseInt(process.env.DB_POOL_MAX || '5', 10),
|
|
141
|
+
min: parseInt(process.env.DB_POOL_MIN || '0', 10),
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### WebDriver Session Path Configuration
|
|
147
|
+
|
|
148
|
+
The WebDriver session endpoint path is configurable. The `webdriverSessionPath` specifies the base path, and the router automatically appends `/session` to it. For example, if `webdriverSessionPath` is `/wd/hub`, the final endpoint will be `/wd/hub/session`.
|
|
149
|
+
|
|
150
|
+
You can set it via:
|
|
151
|
+
|
|
152
|
+
1. **Configuration File** (`hub.config.json`):
|
|
153
|
+
|
|
154
|
+
```json
|
|
155
|
+
{
|
|
156
|
+
"webdriverSessionPath": "/wd/hub"
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
2. **CLI Arguments**:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
npm run start -- --webdriver-session-path /custom/path
|
|
164
|
+
# or short form:
|
|
165
|
+
npm run start -- -w /custom/path
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
3. **Environment Variable**:
|
|
169
|
+
|
|
170
|
+
```env
|
|
171
|
+
WEBDRIVER_SESSION_PATH=/wd/hub
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
4. **Custom Config File**:
|
|
175
|
+
```bash
|
|
176
|
+
npm run start -- --config /path/to/hub.config.json
|
|
177
|
+
# or short form:
|
|
178
|
+
npm run start -- -c /path/to/hub.config.json
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**Priority Order:** Environment variables > CLI arguments > Config file > Default (`/wd/hub`)
|
|
182
|
+
|
|
183
|
+
**Note:** The router automatically appends `/session` to the configured path, so the default endpoint will be available at `POST /wd/hub/session`.
|
|
184
|
+
|
|
185
|
+
### Prepare WDA Command (iOS)
|
|
186
|
+
|
|
187
|
+
The hub includes a command to build and sign WebDriverAgent (WDA) for iOS real device testing. This command:
|
|
188
|
+
|
|
189
|
+
- Finds or builds WebDriverAgent from Appium
|
|
190
|
+
- Signs it with a mobile provisioning profile
|
|
191
|
+
- Creates a signed IPA file ready for deployment
|
|
192
|
+
|
|
193
|
+
**Usage:**
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
# Interactive mode (will prompt for provisioning profile)
|
|
197
|
+
npm run start -- prepare-wda
|
|
198
|
+
|
|
199
|
+
# With specific provisioning file
|
|
200
|
+
npm run start -- prepare-wda --mobile-provisioning-file /path/to/profile.mobileprovision
|
|
201
|
+
|
|
202
|
+
# With custom WDA project path
|
|
203
|
+
npm run start -- prepare-wda --wda-project-path /path/to/WebDriverAgent
|
|
204
|
+
|
|
205
|
+
# Specify platform (ios, tvos, or both)
|
|
206
|
+
npm run start -- prepare-wda --platform both
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
**Options:**
|
|
210
|
+
|
|
211
|
+
| Option | Short | Description |
|
|
212
|
+
| ---------------------------- | ----- | -------------------------------------------------------- |
|
|
213
|
+
| `--mobile-provisioning-file` | `-m` | Path to the mobile provisioning file for signing |
|
|
214
|
+
| `--wda-project-path` | `-p` | Path to WebDriverAgent Xcode project |
|
|
215
|
+
| `--platform` | | Platform type: `ios`, `tvos`, or `both` (default: `ios`) |
|
|
216
|
+
|
|
217
|
+
**Requirements:**
|
|
218
|
+
|
|
219
|
+
- macOS with Xcode installed
|
|
220
|
+
- Valid Apple Developer provisioning profile
|
|
221
|
+
- Appium with XCUITest driver installed (for automatic WDA discovery)
|
|
222
|
+
|
|
223
|
+
### Node Monitor Configuration
|
|
224
|
+
|
|
225
|
+
The hub includes a node monitor service that tracks node liveness by checking for heartbeat signals. You can configure it using environment variables:
|
|
226
|
+
|
|
227
|
+
```env
|
|
228
|
+
# Node monitor check interval (default: 60000ms = 60 seconds)
|
|
229
|
+
NODE_MONITOR_INTERVAL=60000
|
|
230
|
+
|
|
231
|
+
# Timeout before marking a node as offline (default: 120000ms = 2 minutes)
|
|
232
|
+
NODE_TIMEOUT_MS=120000
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
The node monitor service is configured as follows:
|
|
236
|
+
|
|
237
|
+
```typescript
|
|
238
|
+
export const nodeMonitorService = new NodeMonitorService({
|
|
239
|
+
checkInterval: parseInt(process.env.NODE_MONITOR_INTERVAL || '60000', 10),
|
|
240
|
+
timeoutMs: parseInt(process.env.NODE_TIMEOUT_MS || '120000', 10),
|
|
241
|
+
});
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
**Configuration Details:**
|
|
245
|
+
|
|
246
|
+
- **`NODE_MONITOR_INTERVAL`**: How often the monitor checks for offline nodes (in milliseconds). Default is 60 seconds.
|
|
247
|
+
- **`NODE_TIMEOUT_MS`**: How long a node can go without sending a heartbeat before being marked offline (in milliseconds). Default is 2 minutes.
|
|
248
|
+
|
|
249
|
+
The monitor waits for the first interval before checking, giving nodes a grace period after hub restart to register and start sending heartbeats.
|
|
250
|
+
|
|
251
|
+
## Development
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
# Build the package
|
|
255
|
+
npm run build
|
|
256
|
+
|
|
257
|
+
# Watch mode
|
|
258
|
+
npm run build:watch
|
|
259
|
+
|
|
260
|
+
# Type check
|
|
261
|
+
npm run typecheck
|
|
262
|
+
|
|
263
|
+
# Lint
|
|
264
|
+
npm run lint
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## Dependencies
|
|
268
|
+
|
|
269
|
+
- **sequelize**: ORM for Node.js
|
|
270
|
+
- **pg**: PostgreSQL client for Node.js
|
|
271
|
+
- **pg-hstore**: Serialization/deserialization of hstore data type
|
|
272
|
+
|
|
273
|
+
## Resources
|
|
274
|
+
|
|
275
|
+
- [Sequelize Documentation](https://sequelize.org/)
|
|
276
|
+
- [PostgreSQL Documentation](https://www.postgresql.org/docs/)
|