@savioruz/owi 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/LICENSE +21 -0
- package/README.md +372 -0
- package/install.js +107 -0
- package/package.json +44 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Owi Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
# Owi - Simple Database Migrations for Swift
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
A clean and simple database migration tool for Swift, designed to work seamlessly with Vapor and other Swift web frameworks.
|
|
9
|
+
See [Changelogs](CHANGELOG.md)
|
|
10
|
+
|
|
11
|
+
# Table of Contents
|
|
12
|
+
|
|
13
|
+
1. [Overview](#overview)
|
|
14
|
+
- [Introduction](#overview)
|
|
15
|
+
- [Features](#overview)
|
|
16
|
+
|
|
17
|
+
2. [Installation](#installation)
|
|
18
|
+
- [As a Library (for Vapor apps)](#as-a-library-for-vapor-apps)
|
|
19
|
+
- [As a CLI Tool](#as-a-cli-tool)
|
|
20
|
+
- [Quick Install](#quick-install)
|
|
21
|
+
- [Homebrew Installation](#homebrew)
|
|
22
|
+
- [Manual Installation](#manual-installation)
|
|
23
|
+
|
|
24
|
+
3. [Migration File Format](#migration-file-format)
|
|
25
|
+
- [Example](#migration-file-format)
|
|
26
|
+
- [Rules](#rules)
|
|
27
|
+
|
|
28
|
+
4. [CLI Usage](#cli-usage)
|
|
29
|
+
- [Create a New Migration](#create-a-new-migration)
|
|
30
|
+
- [Run Migrations](#run-migrations)
|
|
31
|
+
- [Rollback Migrations](#rollback-migrations)
|
|
32
|
+
- [Check Status](#check-status)
|
|
33
|
+
- [CLI Options](#cli-options)
|
|
34
|
+
|
|
35
|
+
5. [Library Usage (Vapor Integration)](#library-usage-vapor-integration)
|
|
36
|
+
- [Using Vapor’s Database Connection](#using-vapors-database-connection-recommended)
|
|
37
|
+
- [Integration in `configure.swift`](#in-configureswift)
|
|
38
|
+
- [Standalone Usage (Without Vapor)](#standalone-usage-without-vapor)
|
|
39
|
+
- [Key Differences](#key-difference)
|
|
40
|
+
|
|
41
|
+
6. [API Reference](#api-reference)
|
|
42
|
+
- [`Runner`](#runner)
|
|
43
|
+
- [`Parser`](#parser)
|
|
44
|
+
- [`Migration`](#migration)
|
|
45
|
+
- [`SchemaVersion`](#schemaversion)
|
|
46
|
+
|
|
47
|
+
7. [Database Schema](#database-schema)
|
|
48
|
+
- [Schema Tracking Table (`owi_schema`)](#database-schema)
|
|
49
|
+
- [Example Table Content](#database-schema)
|
|
50
|
+
|
|
51
|
+
8. [Contributing](#contributing)
|
|
52
|
+
|
|
53
|
+
9. [License](#license)
|
|
54
|
+
|
|
55
|
+
10. [Inspiration](#inspiration)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
## Installation
|
|
59
|
+
|
|
60
|
+
### As a Library (for Vapor apps)
|
|
61
|
+
|
|
62
|
+
Add to your `Package.swift`:
|
|
63
|
+
|
|
64
|
+
```swift
|
|
65
|
+
.package(url: "https://github.com/savioruz/owi.git", from: "0.0.1")
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Then add to your target:
|
|
69
|
+
|
|
70
|
+
```swift
|
|
71
|
+
.product(name: "Owi", package: "owi")
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### As a CLI Tool
|
|
75
|
+
|
|
76
|
+
#### Quick Install
|
|
77
|
+
|
|
78
|
+
Using the install script:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
curl -fsSL https://raw.githubusercontent.com/savioruz/owi/main/install.sh | sh
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Or download and run:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
curl -fsSL -o install.sh https://raw.githubusercontent.com/savioruz/owi/main/install.sh
|
|
88
|
+
chmod +x install.sh
|
|
89
|
+
./install.sh
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
#### Homebrew
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
brew tap savioruz/homebrew-tap
|
|
96
|
+
brew install owi
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
#### Manual Installation
|
|
100
|
+
|
|
101
|
+
Download the latest release from [GitHub Releases](https://github.com/savioruz/owi/releases):
|
|
102
|
+
|
|
103
|
+
## Migration File Format
|
|
104
|
+
|
|
105
|
+
Migrations are written in SQL files with a specific format:
|
|
106
|
+
|
|
107
|
+
```sql
|
|
108
|
+
-- migrate:up
|
|
109
|
+
CREATE TABLE users (id SERIAL PRIMARY KEY);
|
|
110
|
+
|
|
111
|
+
-- migrate:down
|
|
112
|
+
DROP TABLE users;
|
|
113
|
+
|
|
114
|
+
-- migrate:up
|
|
115
|
+
ALTER TABLE users ADD COLUMN email VARCHAR(255);
|
|
116
|
+
|
|
117
|
+
-- migrate:down
|
|
118
|
+
ALTER TABLE users DROP COLUMN email;
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Rules
|
|
122
|
+
|
|
123
|
+
1. Each file can contain **single or multiple up/down pairs**
|
|
124
|
+
2. Sections are marked with `-- migrate:up` and `-- migrate:down`
|
|
125
|
+
3. Down sections are applied in **reverse order** during rollback
|
|
126
|
+
4. File names should follow the pattern: `{number}_{description}.sql`
|
|
127
|
+
- Example: `001_create_users_table.sql`
|
|
128
|
+
|
|
129
|
+
## CLI Usage
|
|
130
|
+
|
|
131
|
+
### Create a New Migration
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
owi new create_users_table
|
|
135
|
+
|
|
136
|
+
# With custom directory
|
|
137
|
+
owi new create_users_table -m ./db/migrations
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
This creates a new migration file with an auto-incremented number:
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
migrations/
|
|
144
|
+
001_create_users_table.sql
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Run Migrations
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
# SQLite
|
|
151
|
+
owi migrate -u ./db.sqlite -m ./migrations
|
|
152
|
+
|
|
153
|
+
# PostgreSQL
|
|
154
|
+
owi migrate -u "postgres://user:pass@localhost:5432/mydb" --type postgres -m ./migrations
|
|
155
|
+
|
|
156
|
+
# MySQL
|
|
157
|
+
owi migrate -u "mysql://user:pass@localhost:3306/mydb" --type mysql -m ./migrations
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Rollback Migrations
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
# Rollback last migration
|
|
164
|
+
owi rollback -u ./db.sqlite
|
|
165
|
+
|
|
166
|
+
# Rollback last 3 migrations
|
|
167
|
+
owi rollback -u ./db.sqlite --count 3
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Check Status
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
owi status -u ./db.sqlite -m ./migrations
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Output:
|
|
177
|
+
```
|
|
178
|
+
Migration Status:
|
|
179
|
+
─────────────────────────────────────
|
|
180
|
+
✓ 001_create_users_table
|
|
181
|
+
✓ 002_add_email_to_users
|
|
182
|
+
✗ 003_create_posts_table
|
|
183
|
+
─────────────────────────────────────
|
|
184
|
+
Applied: 2, Pending: 1
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### CLI Options
|
|
188
|
+
|
|
189
|
+
All commands support these options:
|
|
190
|
+
|
|
191
|
+
- `-u, --database-url <url>` - Database URL or path
|
|
192
|
+
- `-m, --migrations-dir <dir>` - Migrations directory (default: `./migrations`)
|
|
193
|
+
- `--type <type>` - Database type: `sqlite`, `postgres`, or `mysql` (default: `sqlite`)
|
|
194
|
+
|
|
195
|
+
## Library Usage (Vapor Integration)
|
|
196
|
+
|
|
197
|
+
### Using Vapor's Database Connection (Recommended)
|
|
198
|
+
|
|
199
|
+
When integrating with Vapor, pass your existing database connection to avoid connection pool issues:
|
|
200
|
+
|
|
201
|
+
```swift
|
|
202
|
+
import Vapor
|
|
203
|
+
import Owi
|
|
204
|
+
|
|
205
|
+
func configureMigrations(_ app: Application) async throws {
|
|
206
|
+
// Use Vapor's existing database connection - no pool management needed!
|
|
207
|
+
let driver = PostgresDriver(database: app.db(.psql))
|
|
208
|
+
|
|
209
|
+
// Create runner
|
|
210
|
+
let runner = Runner(
|
|
211
|
+
driver: driver,
|
|
212
|
+
migrationDir: "./Migrations"
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
// Run migrations
|
|
216
|
+
try await runner.migrate()
|
|
217
|
+
|
|
218
|
+
// No need to call close() - Vapor manages the connection!
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**For MySQL:**
|
|
223
|
+
```swift
|
|
224
|
+
let driver = MySQLDriver(database: app.db(.mysql))
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
**For SQLite:**
|
|
228
|
+
```swift
|
|
229
|
+
let driver = SQLiteDriver(database: app.db(.sqlite))
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### In `configure.swift`
|
|
233
|
+
|
|
234
|
+
```swift
|
|
235
|
+
public func configure(_ app: Application) async throws {
|
|
236
|
+
// ... your database configuration
|
|
237
|
+
|
|
238
|
+
// Run migrations on startup (optional)
|
|
239
|
+
try await configureMigrations(app)
|
|
240
|
+
|
|
241
|
+
// ... rest of configuration
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Standalone Usage (Without Vapor)
|
|
246
|
+
|
|
247
|
+
If you're building a CLI tool or not using Vapor, create your own connection:
|
|
248
|
+
|
|
249
|
+
```swift
|
|
250
|
+
import Owi
|
|
251
|
+
import PostgresKit
|
|
252
|
+
|
|
253
|
+
// Create configuration using native PostgresKit types
|
|
254
|
+
let config = PostgresConfiguration(
|
|
255
|
+
hostname: "localhost",
|
|
256
|
+
port: 5432,
|
|
257
|
+
username: "postgres",
|
|
258
|
+
password: "postgres",
|
|
259
|
+
database: "myapp",
|
|
260
|
+
tls: .disable
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
// Create driver (manages its own connection pool)
|
|
264
|
+
let driver = try await PostgresDriver(configuration: config)
|
|
265
|
+
|
|
266
|
+
// Create runner
|
|
267
|
+
let runner = Runner(driver: driver, migrationDir: "./Migrations")
|
|
268
|
+
|
|
269
|
+
// Run migrations
|
|
270
|
+
try await runner.migrate()
|
|
271
|
+
|
|
272
|
+
// Check status
|
|
273
|
+
try await runner.status()
|
|
274
|
+
|
|
275
|
+
// Rollback
|
|
276
|
+
try await runner.rollback(count: 1)
|
|
277
|
+
|
|
278
|
+
// IMPORTANT: Close the connection when done!
|
|
279
|
+
try await runner.close()
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
**Key Difference:**
|
|
283
|
+
- **With Vapor database**: `PostgresDriver(database: app.db(.psql))` - NO `close()` needed
|
|
284
|
+
- **With configuration**: `PostgresDriver(configuration: config)` - MUST call `close()`
|
|
285
|
+
|
|
286
|
+
## API Reference
|
|
287
|
+
|
|
288
|
+
### `Runner`
|
|
289
|
+
|
|
290
|
+
Main migration runner.
|
|
291
|
+
|
|
292
|
+
```swift
|
|
293
|
+
public struct Runner {
|
|
294
|
+
public init(
|
|
295
|
+
driver: any DatabaseDriver,
|
|
296
|
+
migrationDir: String,
|
|
297
|
+
schemaTableName: String = "owi_schema"
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
public func migrate() async throws
|
|
301
|
+
public func rollback(count: Int = 1) async throws
|
|
302
|
+
public func status() async throws
|
|
303
|
+
public func close() async throws
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### `Parser`
|
|
308
|
+
|
|
309
|
+
Parses migration files.
|
|
310
|
+
|
|
311
|
+
```swift
|
|
312
|
+
public struct Parser {
|
|
313
|
+
public func parse(fileURL: URL) throws -> Migration
|
|
314
|
+
public func loadMigrations(from directoryURL: URL) throws -> [Migration]
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### `Migration`
|
|
319
|
+
|
|
320
|
+
Represents a single migration.
|
|
321
|
+
|
|
322
|
+
```swift
|
|
323
|
+
public struct Migration {
|
|
324
|
+
public let id: String
|
|
325
|
+
public let upSQL: String
|
|
326
|
+
public let downSQL: String
|
|
327
|
+
public let filePath: String
|
|
328
|
+
public var version: Int? // Extracted from ID (e.g., "001" -> 1)
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### `SchemaVersion`
|
|
333
|
+
|
|
334
|
+
Represents the current schema version state in the database.
|
|
335
|
+
|
|
336
|
+
```swift
|
|
337
|
+
public struct SchemaVersion {
|
|
338
|
+
public let id: Int // Always 1
|
|
339
|
+
public let version: Int // Current migration version
|
|
340
|
+
public let dirty: Bool // Is a migration in progress?
|
|
341
|
+
public let modifiedAt: Date // Last modification time
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### Database Schema
|
|
346
|
+
|
|
347
|
+
The schema tracking table (`owi_schema` by default, customizable) stores **a single row**:
|
|
348
|
+
|
|
349
|
+
| Column | Type | Description |
|
|
350
|
+
|--------|------|-------------|
|
|
351
|
+
| `id` | INTEGER | Always 1 (enforced by CHECK constraint) |
|
|
352
|
+
| `version` | INTEGER | Current migration version (e.g., 0, 1, 2, 3) |
|
|
353
|
+
| `dirty` | BOOLEAN/INTEGER | Migration in progress flag |
|
|
354
|
+
| `modified_at` | TIMESTAMP/TEXT | Last modification timestamp |
|
|
355
|
+
|
|
356
|
+
Example table content:
|
|
357
|
+
```
|
|
358
|
+
id | version | dirty | modified_at
|
|
359
|
+
1 | 3 | 0 | 2025-10-26 20:08:53
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
## Contributing
|
|
363
|
+
|
|
364
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
365
|
+
|
|
366
|
+
## License
|
|
367
|
+
|
|
368
|
+
[MIT License](LICENSE) - feel free to use in your projects!
|
|
369
|
+
|
|
370
|
+
## Inspiration
|
|
371
|
+
|
|
372
|
+
Inspired by tools like [dbmate](https://github.com/amacneil/dbmate.git), but designed specifically for Swift and Vapor.
|
package/install.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { execSync } = require('child_process');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const https = require('https');
|
|
7
|
+
|
|
8
|
+
const REPO = 'savioruz/owi';
|
|
9
|
+
|
|
10
|
+
function getPlatform() {
|
|
11
|
+
const platform = process.platform;
|
|
12
|
+
const arch = process.arch;
|
|
13
|
+
|
|
14
|
+
if (platform === 'darwin') {
|
|
15
|
+
return 'owi-macos.tar.gz';
|
|
16
|
+
} else if (platform === 'linux') {
|
|
17
|
+
if (arch === 'x64') {
|
|
18
|
+
return 'owi-linux-x86_64.tar.gz';
|
|
19
|
+
} else if (arch === 'arm64') {
|
|
20
|
+
return 'owi-linux-aarch64.tar.gz';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
throw new Error(`Unsupported platform: ${platform} ${arch}`);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function getVersion() {
|
|
28
|
+
const packageJson = require('./package.json');
|
|
29
|
+
return packageJson.version;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function download(url, dest) {
|
|
33
|
+
return new Promise((resolve, reject) => {
|
|
34
|
+
const file = fs.createWriteStream(dest);
|
|
35
|
+
|
|
36
|
+
https.get(url, {
|
|
37
|
+
headers: { 'User-Agent': 'owi-npm-installer' },
|
|
38
|
+
followRedirect: true
|
|
39
|
+
}, (response) => {
|
|
40
|
+
// Handle redirects
|
|
41
|
+
if (response.statusCode === 302 || response.statusCode === 301) {
|
|
42
|
+
download(response.headers.location, dest).then(resolve).catch(reject);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (response.statusCode !== 200) {
|
|
47
|
+
reject(new Error(`Failed to download: ${response.statusCode}`));
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
response.pipe(file);
|
|
52
|
+
|
|
53
|
+
file.on('finish', () => {
|
|
54
|
+
file.close();
|
|
55
|
+
resolve();
|
|
56
|
+
});
|
|
57
|
+
}).on('error', (err) => {
|
|
58
|
+
fs.unlink(dest, () => {});
|
|
59
|
+
reject(err);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function install() {
|
|
65
|
+
try {
|
|
66
|
+
const platformFile = getPlatform();
|
|
67
|
+
const version = getVersion();
|
|
68
|
+
|
|
69
|
+
// Use latest if version is development
|
|
70
|
+
const versionTag = version === '0.0.5' ? 'latest/download' : `download/v${version}`;
|
|
71
|
+
const url = `https://github.com/${REPO}/releases/${versionTag}/${platformFile}`;
|
|
72
|
+
|
|
73
|
+
console.log(`Downloading owi from ${url}...`);
|
|
74
|
+
|
|
75
|
+
const binDir = path.join(__dirname, 'bin');
|
|
76
|
+
const tarPath = path.join(__dirname, platformFile);
|
|
77
|
+
|
|
78
|
+
// Create bin directory
|
|
79
|
+
if (!fs.existsSync(binDir)) {
|
|
80
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Download the tarball
|
|
84
|
+
await download(url, tarPath);
|
|
85
|
+
|
|
86
|
+
// Extract the binary
|
|
87
|
+
console.log('Extracting binary...');
|
|
88
|
+
execSync(`tar -xzf ${tarPath} -C ${binDir}`, { stdio: 'inherit' });
|
|
89
|
+
|
|
90
|
+
// Make it executable
|
|
91
|
+
const binaryPath = path.join(binDir, 'owi');
|
|
92
|
+
fs.chmodSync(binaryPath, '755');
|
|
93
|
+
|
|
94
|
+
// Clean up
|
|
95
|
+
fs.unlinkSync(tarPath);
|
|
96
|
+
|
|
97
|
+
console.log('✓ owi installed successfully!');
|
|
98
|
+
console.log('Run "owi --help" to get started.');
|
|
99
|
+
} catch (error) {
|
|
100
|
+
console.error('Installation failed:', error.message);
|
|
101
|
+
console.error('\nYou can download the binary manually from:');
|
|
102
|
+
console.error(`https://github.com/${REPO}/releases/latest`);
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
install();
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@savioruz/owi",
|
|
3
|
+
"version": "0.0.5",
|
|
4
|
+
"description": "Simple database migration tool for Swift and Vapor",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"owi": "./bin/owi"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"postinstall": "node install.js"
|
|
11
|
+
},
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/savioruz/owi.git"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"migration",
|
|
18
|
+
"database",
|
|
19
|
+
"swift",
|
|
20
|
+
"vapor",
|
|
21
|
+
"cli",
|
|
22
|
+
"postgres",
|
|
23
|
+
"mysql",
|
|
24
|
+
"sqlite"
|
|
25
|
+
],
|
|
26
|
+
"author": "savioruz",
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"bugs": {
|
|
29
|
+
"url": "https://github.com/savioruz/owi/issues"
|
|
30
|
+
},
|
|
31
|
+
"homepage": "https://github.com/savioruz/owi#readme",
|
|
32
|
+
"os": [
|
|
33
|
+
"darwin",
|
|
34
|
+
"linux"
|
|
35
|
+
],
|
|
36
|
+
"cpu": [
|
|
37
|
+
"x64",
|
|
38
|
+
"arm64"
|
|
39
|
+
],
|
|
40
|
+
"files": [
|
|
41
|
+
"install.js",
|
|
42
|
+
"bin/"
|
|
43
|
+
]
|
|
44
|
+
}
|