@palettelab/cli 0.3.18 → 0.3.20
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 +32 -9
- package/lib/cli.js +18 -4
- package/lib/commands/dev.js +3 -2
- package/lib/commands/doctor.js +22 -10
- package/lib/commands/login.js +51 -0
- package/lib/environments.js +64 -3
- package/package.json +1 -1
- package/template-fallback/package.json +1 -1
- package/template-fallback/templates/dashboard/package.json +1 -1
- package/template-fallback/templates/database/backend/migrations/env.py +3 -35
- package/template-fallback/templates/database/package.json +1 -1
- package/template-fallback/templates/external-service/package.json +1 -1
- package/template-fallback/templates/frontend-only/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,8 @@ The installed executable is `pltt`.
|
|
|
8
8
|
|
|
9
9
|
- Node.js 18+
|
|
10
10
|
- Python 3.12+ for local backend simulation
|
|
11
|
-
- Docker
|
|
11
|
+
- No Docker is required for normal app development, testing, or publishing.
|
|
12
|
+
- Docker Desktop is only for internal `pltt dev --platform` parity checks.
|
|
12
13
|
|
|
13
14
|
## Install
|
|
14
15
|
|
|
@@ -48,8 +49,10 @@ Run a no-Docker local SDK simulator with your plugin mounted live. Run this from
|
|
|
48
49
|
|
|
49
50
|
```bash
|
|
50
51
|
pltt dev
|
|
51
|
-
pltt
|
|
52
|
+
pltt sandbox --env staging
|
|
53
|
+
pltt dev --sandbox --env staging
|
|
52
54
|
pltt dev --cloud --env staging
|
|
55
|
+
pltt dev --platform
|
|
53
56
|
```
|
|
54
57
|
|
|
55
58
|
By default this starts:
|
|
@@ -70,11 +73,14 @@ the declared Alembic migrations and platform-managed Postgres/RLS.
|
|
|
70
73
|
|
|
71
74
|
`3000` and `8000` are preferred defaults, not hard requirements. If either port is already in use, `pltt dev` automatically picks the next free port and prints the actual URLs.
|
|
72
75
|
|
|
73
|
-
`pltt dev --
|
|
74
|
-
|
|
75
|
-
|
|
76
|
+
`pltt dev --sandbox` skips Docker and publishes a reviewable preview to a configured Palette sandbox. This is the payment-gateway-style flow: your app uses local SDKs, while real platform services such as login, Data Room, storage, database policies, logs, review, and publish lifecycle run in the hosted sandbox. It defaults to `--env staging` unless `--env` or `PALETTE_ENV` is set, adds a 24-hour preview TTL by default, and prints the preview/status/log commands returned by the platform.
|
|
77
|
+
|
|
78
|
+
`pltt dev --cloud` is kept as an alias for `--sandbox`.
|
|
79
|
+
|
|
80
|
+
`pltt sandbox --env staging` is the same hosted preview flow as
|
|
81
|
+
`pltt dev --sandbox --env staging`.
|
|
76
82
|
|
|
77
|
-
`pltt dev --
|
|
83
|
+
`pltt dev --platform` runs the full Docker `platform-dev` image for internal platform parity testing. App developers should not need it. It pulls `ghcr.io/palette-lab/platform-dev:latest` and mounts your plugin at `/plugins/<your-id>`.
|
|
78
84
|
|
|
79
85
|
Environment variables:
|
|
80
86
|
|
|
@@ -85,6 +91,15 @@ Environment variables:
|
|
|
85
91
|
| `PALETTE_BACKEND_PORT` | `8000` | Preferred starting host port for the backend |
|
|
86
92
|
| `PALETTE_DEV_DATABASE_URL` | `.palette/dev/<plugin-id>.sqlite3` | Override the local dev database URL |
|
|
87
93
|
|
|
94
|
+
### `pltt login`
|
|
95
|
+
|
|
96
|
+
Save a Palette sandbox or production environment URL plus token in `~/.palette/config.json` with file mode `0600`. Environment variables still override the stored token when present.
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
pltt login --env staging --url https://sandbox.pltt.ai --token <publish-token>
|
|
100
|
+
pltt dev --sandbox --env staging
|
|
101
|
+
```
|
|
102
|
+
|
|
88
103
|
### `pltt doctor`
|
|
89
104
|
|
|
90
105
|
Check local tooling and common setup problems.
|
|
@@ -93,7 +108,15 @@ Check local tooling and common setup problems.
|
|
|
93
108
|
pltt doctor
|
|
94
109
|
```
|
|
95
110
|
|
|
96
|
-
Checks include Node version,
|
|
111
|
+
Checks include Node version, port availability, manifest validity, entry files, and frontend bundling.
|
|
112
|
+
|
|
113
|
+
Docker is intentionally skipped by default:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
pltt doctor --platform
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Use `--platform` only when validating the internal Docker parity harness.
|
|
97
120
|
|
|
98
121
|
### `pltt build`
|
|
99
122
|
|
|
@@ -142,7 +165,7 @@ pltt publish --env staging --ttl-hours 24
|
|
|
142
165
|
|
|
143
166
|
Publishing first runs the same contract checks as `pltt test`. If preflight passes, it bundles frontend/backend artifacts, uploads them, creates a `pending_review` publish record, and prints review/preview URLs when the platform returns them.
|
|
144
167
|
|
|
145
|
-
`--ttl-hours` sets an expiration on the preview URL. It is mainly used by `pltt dev --
|
|
168
|
+
`--ttl-hours` sets an expiration on the preview URL. It is mainly used by `pltt dev --sandbox`, which defaults previews to 24 hours.
|
|
146
169
|
|
|
147
170
|
Environment config is read from `./palette.config.json`, `~/.palette/config.json`, or `PALETTE_<ENV>_URL` plus `PALETTE_<ENV>_TOKEN` / `PALETTE_PUBLISH_TOKEN`.
|
|
148
171
|
|
|
@@ -183,7 +206,7 @@ If no plugin ID is provided, the CLI uses the current `palette-plugin.json` or `
|
|
|
183
206
|
- `bin/pltt.js` — entry point
|
|
184
207
|
- `backend-sdk/` — backend SDK files used by local contract tests and simulator
|
|
185
208
|
- `lib/` — pure-Node command implementations (no runtime dependencies)
|
|
186
|
-
- `platform-dev/docker-compose.yml` — compose file for `pltt dev --platform`
|
|
209
|
+
- `platform-dev/docker-compose.yml` — compose file for internal `pltt dev --platform` parity checks
|
|
187
210
|
- `template-fallback/` — offline fallback for `pltt init` if git is unavailable
|
|
188
211
|
|
|
189
212
|
## See also
|
package/lib/cli.js
CHANGED
|
@@ -6,6 +6,7 @@ const doctor = require("./commands/doctor")
|
|
|
6
6
|
const build = require("./commands/build")
|
|
7
7
|
const test = require("./commands/test")
|
|
8
8
|
const publish = require("./commands/publish")
|
|
9
|
+
const login = require("./commands/login")
|
|
9
10
|
const pkg = require("./commands/package")
|
|
10
11
|
const status = require("./commands/status")
|
|
11
12
|
const logs = require("./commands/logs")
|
|
@@ -14,11 +15,16 @@ const COMMANDS = {
|
|
|
14
15
|
init: { run: init, help: "Scaffold a new plugin directory from the template" },
|
|
15
16
|
dev: {
|
|
16
17
|
run: dev,
|
|
17
|
-
help: "Run the
|
|
18
|
+
help: "Run the no-Docker SDK simulator; use --sandbox for hosted preview",
|
|
18
19
|
},
|
|
20
|
+
sandbox: {
|
|
21
|
+
run: (args, ctx) => dev([...args, "--sandbox"], ctx),
|
|
22
|
+
help: "Publish a no-Docker hosted sandbox preview",
|
|
23
|
+
},
|
|
24
|
+
login: { run: login, help: "Save a Palette sandbox environment for publish/dev preview" },
|
|
19
25
|
doctor: {
|
|
20
26
|
run: doctor,
|
|
21
|
-
help: "Check local tooling, ports, manifest,
|
|
27
|
+
help: "Check local tooling, ports, manifest, and frontend bundling",
|
|
22
28
|
},
|
|
23
29
|
build: { run: build, help: "Validate palette-plugin.json and check entry points exist" },
|
|
24
30
|
test: { run: test, help: "Run local plugin contract checks before publishing" },
|
|
@@ -50,8 +56,13 @@ function printHelp() {
|
|
|
50
56
|
console.log(" --env <name> Target environment from ~/.palette/config.json (default: local)")
|
|
51
57
|
console.log(" -y, --yes Skip interactive confirmation for production pushes")
|
|
52
58
|
console.log("\nDev flags:")
|
|
53
|
-
console.log(" --
|
|
54
|
-
console.log(" --cloud
|
|
59
|
+
console.log(" --sandbox Publish a reviewable preview to a configured Palette sandbox (no Docker)")
|
|
60
|
+
console.log(" --cloud Alias for --sandbox")
|
|
61
|
+
console.log(" --platform Internal only: run the Docker platform-dev parity container")
|
|
62
|
+
console.log("\nLogin flags:")
|
|
63
|
+
console.log(" --url <url> Palette platform URL for pltt login")
|
|
64
|
+
console.log(" --token <token> Publish token for pltt login")
|
|
65
|
+
console.log(" --no-default Do not make this environment the default")
|
|
55
66
|
console.log("\nInit flags:")
|
|
56
67
|
console.log(" --template <name> One of: dashboard, agent-tool, external-service, database, frontend-only")
|
|
57
68
|
console.log("\nLogs flags:")
|
|
@@ -59,7 +70,10 @@ function printHelp() {
|
|
|
59
70
|
console.log(" -f, --follow Stream events (poll every 3s)")
|
|
60
71
|
console.log("\nExamples:")
|
|
61
72
|
console.log(" pltt init my-app --template database")
|
|
73
|
+
console.log(" pltt login --env staging --url https://sandbox.pltt.ai --token <token>")
|
|
62
74
|
console.log(" cd my-app && pltt dev")
|
|
75
|
+
console.log(" pltt sandbox --env staging")
|
|
76
|
+
console.log(" pltt dev --sandbox --env staging")
|
|
63
77
|
console.log(" pltt package")
|
|
64
78
|
console.log(" pltt publish --env staging")
|
|
65
79
|
console.log(" pltt status")
|
package/lib/commands/dev.js
CHANGED
|
@@ -76,7 +76,7 @@ function imagePullHelp(image, output) {
|
|
|
76
76
|
|
|
77
77
|
async function run(args, { cwd }) {
|
|
78
78
|
const { flags, rest } = parseFlags(args)
|
|
79
|
-
const cloud = rest.includes("--cloud")
|
|
79
|
+
const cloud = rest.includes("--cloud") || rest.includes("--sandbox")
|
|
80
80
|
const platform = rest.includes("--platform")
|
|
81
81
|
if (cloud) {
|
|
82
82
|
const json = args.includes("--json")
|
|
@@ -92,7 +92,7 @@ async function run(args, { cwd }) {
|
|
|
92
92
|
if (!flags.env && !process.env.PALETTE_ENV) publishArgs.push("--env", "staging")
|
|
93
93
|
if (!json) {
|
|
94
94
|
console.log(
|
|
95
|
-
"[pltt]
|
|
95
|
+
"[pltt] sandbox dev publishes a reviewable preview to the configured Palette sandbox.",
|
|
96
96
|
)
|
|
97
97
|
}
|
|
98
98
|
const record = await publish(publishArgs, { cwd })
|
|
@@ -146,6 +146,7 @@ async function run(args, { cwd }) {
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
console.log(`[pltt] starting ${DEFAULT_IMAGE} via docker compose`)
|
|
149
|
+
console.log("[pltt] --platform is for internal parity testing; app developers should use `pltt dev` or `pltt dev --sandbox`.")
|
|
149
150
|
console.log(`[pltt] mounting ${cwd} → /plugins/${pluginId}`)
|
|
150
151
|
if (ports.frontend !== ports.preferredFrontend) {
|
|
151
152
|
console.log(`[pltt] frontend port ${ports.preferredFrontend} is busy; using ${ports.frontend}`)
|
package/lib/commands/doctor.js
CHANGED
|
@@ -51,27 +51,39 @@ function checkEntry(cwd, label, rel) {
|
|
|
51
51
|
|
|
52
52
|
async function run(args, { cwd }) {
|
|
53
53
|
let failures = 0
|
|
54
|
+
const platform = args.includes("--platform")
|
|
54
55
|
|
|
55
56
|
if (nodeMajor() >= 18) ok(`Node ${process.versions.node}`)
|
|
56
57
|
else failures += fail("Node 18+ is required", "Install Node.js 18 or newer.")
|
|
57
58
|
|
|
58
|
-
if (
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
if (platform) {
|
|
60
|
+
if (dockerRunning()) ok("Docker is running")
|
|
61
|
+
else failures += fail(
|
|
62
|
+
"Docker is not running",
|
|
63
|
+
"Start Docker Desktop, then rerun pltt doctor --platform.",
|
|
64
|
+
)
|
|
63
65
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
+
if (imageExistsLocally(DEFAULT_IMAGE)) {
|
|
67
|
+
ok(`platform image is available locally: ${DEFAULT_IMAGE}`)
|
|
68
|
+
} else {
|
|
69
|
+
warn(
|
|
70
|
+
`platform image is not present locally: ${DEFAULT_IMAGE}`,
|
|
71
|
+
"pltt dev --platform will try to pull it. If that fails, run docker login ghcr.io or set PALETTE_DEV_IMAGE.",
|
|
72
|
+
)
|
|
73
|
+
}
|
|
66
74
|
} else {
|
|
67
75
|
warn(
|
|
68
|
-
|
|
69
|
-
"
|
|
76
|
+
"Docker check skipped",
|
|
77
|
+
"Normal app development uses no Docker. Run `pltt doctor --platform` only for internal platform parity testing.",
|
|
70
78
|
)
|
|
71
79
|
}
|
|
72
80
|
|
|
73
81
|
try {
|
|
74
|
-
const ports = await resolveDevPorts({
|
|
82
|
+
const ports = await resolveDevPorts({
|
|
83
|
+
frontend: FRONTEND_PORT,
|
|
84
|
+
backend: BACKEND_PORT,
|
|
85
|
+
host: platform ? "0.0.0.0" : "127.0.0.1",
|
|
86
|
+
})
|
|
75
87
|
if (ports.frontend === FRONTEND_PORT) ok(`frontend port ${FRONTEND_PORT} is available`)
|
|
76
88
|
else warn(`frontend port ${FRONTEND_PORT} is already in use`, `pltt dev will use ${ports.frontend}`)
|
|
77
89
|
if (ports.backend === BACKEND_PORT) ok(`backend port ${BACKEND_PORT} is available`)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict"
|
|
2
|
+
|
|
3
|
+
const { parseFlags, writeUserEnvironment } = require("../environments")
|
|
4
|
+
|
|
5
|
+
function tokenEnvFor(name) {
|
|
6
|
+
if (name === "production") return "PALETTE_PROD_TOKEN"
|
|
7
|
+
return `PALETTE_${name.toUpperCase().replace(/[^A-Z0-9]+/g, "_")}_TOKEN`
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async function run(argv) {
|
|
11
|
+
const { flags } = parseFlags(argv)
|
|
12
|
+
const name = flags.env || process.env.PALETTE_ENV || "staging"
|
|
13
|
+
const url = flags.url || process.env.PALETTE_PLATFORM_URL || process.env[`PALETTE_${name.toUpperCase()}_URL`]
|
|
14
|
+
const token = flags.token || process.env.PALETTE_PUBLISH_TOKEN || process.env[tokenEnvFor(name)]
|
|
15
|
+
|
|
16
|
+
if (!url) {
|
|
17
|
+
console.error(
|
|
18
|
+
`[pltt] missing platform URL for "${name}".\n` +
|
|
19
|
+
` Usage: pltt login --env ${name} --url https://palette.example.com --token <publish-token>`,
|
|
20
|
+
)
|
|
21
|
+
process.exit(1)
|
|
22
|
+
}
|
|
23
|
+
if (!token) {
|
|
24
|
+
console.error(
|
|
25
|
+
`[pltt] missing publish token for "${name}".\n` +
|
|
26
|
+
` Pass --token <token> or set $PALETTE_PUBLISH_TOKEN.`,
|
|
27
|
+
)
|
|
28
|
+
process.exit(1)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const tokenEnv = tokenEnvFor(name)
|
|
32
|
+
const configPath = writeUserEnvironment({
|
|
33
|
+
name,
|
|
34
|
+
url,
|
|
35
|
+
token,
|
|
36
|
+
tokenEnv,
|
|
37
|
+
defaultEnvironment: flags.default,
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
if (flags.json) {
|
|
41
|
+
console.log(JSON.stringify({ ok: true, env: name, url: url.replace(/\/+$/, ""), token_env: tokenEnv, config: configPath }, null, 2))
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
console.log(`[pltt] saved ${name} → ${url.replace(/\/+$/, "")}`)
|
|
46
|
+
console.log(`[pltt] config: ${configPath}`)
|
|
47
|
+
console.log(`[pltt] token stored in user config with file mode 0600`)
|
|
48
|
+
console.log(`[pltt] env override: ${tokenEnv}`)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
module.exports = run
|
package/lib/environments.js
CHANGED
|
@@ -65,6 +65,40 @@ function loadConfig(cwd) {
|
|
|
65
65
|
return DEFAULTS
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
function mergeConfig(cfg) {
|
|
69
|
+
return {
|
|
70
|
+
...DEFAULTS,
|
|
71
|
+
...cfg,
|
|
72
|
+
environments: {
|
|
73
|
+
...DEFAULTS.environments,
|
|
74
|
+
...(cfg.environments || {}),
|
|
75
|
+
},
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function userConfigPath() {
|
|
80
|
+
return path.join(os.homedir(), ".palette", "config.json")
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function writeUserEnvironment({ name, url, token, tokenEnv, defaultEnvironment = true }) {
|
|
84
|
+
const target = userConfigPath()
|
|
85
|
+
const existing = readJsonIfExists(target) || {}
|
|
86
|
+
const cfg = mergeConfig(existing)
|
|
87
|
+
cfg.environments[name] = {
|
|
88
|
+
...(cfg.environments[name] || {}),
|
|
89
|
+
url: url.replace(/\/+$/, ""),
|
|
90
|
+
token,
|
|
91
|
+
token_env: tokenEnv,
|
|
92
|
+
production: Boolean(cfg.environments[name]?.production),
|
|
93
|
+
}
|
|
94
|
+
if (defaultEnvironment) cfg.default_environment = name
|
|
95
|
+
|
|
96
|
+
fs.mkdirSync(path.dirname(target), { recursive: true, mode: 0o700 })
|
|
97
|
+
fs.writeFileSync(target, `${JSON.stringify(cfg, null, 2)}\n`, { mode: 0o600 })
|
|
98
|
+
fs.chmodSync(target, 0o600)
|
|
99
|
+
return target
|
|
100
|
+
}
|
|
101
|
+
|
|
68
102
|
/**
|
|
69
103
|
* Resolve the effective environment.
|
|
70
104
|
*
|
|
@@ -106,7 +140,7 @@ function resolveEnvironment({ cwd, flags }) {
|
|
|
106
140
|
|
|
107
141
|
const token = useLegacy
|
|
108
142
|
? process.env.PALETTE_PUBLISH_TOKEN || ""
|
|
109
|
-
: process.env[envCfg.token_env] || process.env.PALETTE_PUBLISH_TOKEN || ""
|
|
143
|
+
: process.env[envCfg.token_env] || process.env.PALETTE_PUBLISH_TOKEN || envCfg.token || ""
|
|
110
144
|
|
|
111
145
|
if (!url) {
|
|
112
146
|
throw new Error(
|
|
@@ -130,7 +164,16 @@ function resolveEnvironment({ cwd, flags }) {
|
|
|
130
164
|
* Leaves positional args in `rest`.
|
|
131
165
|
*/
|
|
132
166
|
function parseFlags(argv) {
|
|
133
|
-
const flags = {
|
|
167
|
+
const flags = {
|
|
168
|
+
env: undefined,
|
|
169
|
+
yes: false,
|
|
170
|
+
ttlHours: undefined,
|
|
171
|
+
wait: false,
|
|
172
|
+
json: false,
|
|
173
|
+
url: undefined,
|
|
174
|
+
token: undefined,
|
|
175
|
+
default: true,
|
|
176
|
+
}
|
|
134
177
|
const rest = []
|
|
135
178
|
for (let i = 0; i < argv.length; i++) {
|
|
136
179
|
const a = argv[i]
|
|
@@ -146,6 +189,18 @@ function parseFlags(argv) {
|
|
|
146
189
|
flags.ttlHours = Number.parseInt(a.slice("--ttl-hours=".length), 10)
|
|
147
190
|
} else if (a === "--wait") {
|
|
148
191
|
flags.wait = true
|
|
192
|
+
} else if (a === "--json") {
|
|
193
|
+
flags.json = true
|
|
194
|
+
} else if (a === "--url") {
|
|
195
|
+
flags.url = argv[++i]
|
|
196
|
+
} else if (a.startsWith("--url=")) {
|
|
197
|
+
flags.url = a.slice("--url=".length)
|
|
198
|
+
} else if (a === "--token") {
|
|
199
|
+
flags.token = argv[++i]
|
|
200
|
+
} else if (a.startsWith("--token=")) {
|
|
201
|
+
flags.token = a.slice("--token=".length)
|
|
202
|
+
} else if (a === "--no-default") {
|
|
203
|
+
flags.default = false
|
|
149
204
|
} else {
|
|
150
205
|
rest.push(a)
|
|
151
206
|
}
|
|
@@ -168,4 +223,10 @@ async function confirmProduction(env) {
|
|
|
168
223
|
})
|
|
169
224
|
}
|
|
170
225
|
|
|
171
|
-
module.exports = {
|
|
226
|
+
module.exports = {
|
|
227
|
+
resolveEnvironment,
|
|
228
|
+
parseFlags,
|
|
229
|
+
confirmProduction,
|
|
230
|
+
loadConfig,
|
|
231
|
+
writeUserEnvironment,
|
|
232
|
+
}
|
package/package.json
CHANGED
|
@@ -1,37 +1,5 @@
|
|
|
1
|
-
"""Alembic environment for
|
|
1
|
+
"""Alembic environment for Palette plugin migrations."""
|
|
2
2
|
|
|
3
|
-
from
|
|
3
|
+
from palette_sdk.db.alembic_env import run_migrations
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
from sqlalchemy import engine_from_config, pool
|
|
7
|
-
|
|
8
|
-
from models import Note # noqa: F401 - registers model metadata
|
|
9
|
-
from palette_sdk.db import PluginBase
|
|
10
|
-
|
|
11
|
-
config = context.config
|
|
12
|
-
target_metadata = PluginBase.metadata
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def run_migrations_offline() -> None:
|
|
16
|
-
url = config.get_main_option("sqlalchemy.url")
|
|
17
|
-
context.configure(url=url, target_metadata=target_metadata, literal_binds=True)
|
|
18
|
-
with context.begin_transaction():
|
|
19
|
-
context.run_migrations()
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def run_migrations_online() -> None:
|
|
23
|
-
connectable = engine_from_config(
|
|
24
|
-
config.get_section(config.config_ini_section, {}),
|
|
25
|
-
prefix="sqlalchemy.",
|
|
26
|
-
poolclass=pool.NullPool,
|
|
27
|
-
)
|
|
28
|
-
with connectable.connect() as connection:
|
|
29
|
-
context.configure(connection=connection, target_metadata=target_metadata)
|
|
30
|
-
with context.begin_transaction():
|
|
31
|
-
context.run_migrations()
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if context.is_offline_mode():
|
|
35
|
-
run_migrations_offline()
|
|
36
|
-
else:
|
|
37
|
-
run_migrations_online()
|
|
5
|
+
run_migrations()
|