d3ployer 0.0.13 → 0.0.14
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 +35 -8
- package/dist/config.d.ts +2 -1
- package/dist/config.js +3 -0
- package/dist/def.d.ts +12 -8
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/tasks/download.d.ts +2 -2
- package/dist/tasks/download.js +20 -14
- package/dist/tasks/helpers/rsync.d.ts +2 -2
- package/dist/tasks/upload.js +20 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ export default defineConfig({
|
|
|
25
25
|
},
|
|
26
26
|
},
|
|
27
27
|
files: {
|
|
28
|
-
|
|
28
|
+
localPath: './dist',
|
|
29
29
|
exclude: ['node_modules', '.git'],
|
|
30
30
|
},
|
|
31
31
|
symlinks: [
|
|
@@ -103,12 +103,22 @@ Configure rsync file upload.
|
|
|
103
103
|
|
|
104
104
|
```ts
|
|
105
105
|
files: {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
106
|
+
localPath: './dist', // local directory to sync (relative to rootDir or absolute, default: '.')
|
|
107
|
+
remotePath: 'app', // remote directory (relative to deployPath or absolute, default: deployPath)
|
|
108
|
+
include: ['src/**'], // rsync include patterns
|
|
109
|
+
exclude: ['node_modules'], // rsync exclude patterns
|
|
109
110
|
}
|
|
110
111
|
```
|
|
111
112
|
|
|
113
|
+
Or as an array of entries to sync multiple directories:
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
files: [
|
|
117
|
+
{ localPath: './dist', remotePath: 'app', exclude: ['*.map'] },
|
|
118
|
+
{ localPath: './config', remotePath: 'config' },
|
|
119
|
+
]
|
|
120
|
+
```
|
|
121
|
+
|
|
112
122
|
### `symlinks`
|
|
113
123
|
|
|
114
124
|
Create symlinks on the remote server.
|
|
@@ -188,9 +198,26 @@ tasks: {
|
|
|
188
198
|
}
|
|
189
199
|
```
|
|
190
200
|
|
|
201
|
+
Use `defineTask` for type-safe task definitions with a typed config:
|
|
202
|
+
|
|
203
|
+
```ts
|
|
204
|
+
import { defineConfig, defineTask } from 'd3ployer';
|
|
205
|
+
|
|
206
|
+
export default defineConfig({
|
|
207
|
+
tasks: {
|
|
208
|
+
myTask: defineTask<{ retries: number }>({
|
|
209
|
+
task: async (ctx) => {
|
|
210
|
+
const retries = ctx.taskConfig!.retries; // typed as number
|
|
211
|
+
},
|
|
212
|
+
config: { retries: 3 },
|
|
213
|
+
}),
|
|
214
|
+
},
|
|
215
|
+
});
|
|
216
|
+
```
|
|
217
|
+
|
|
191
218
|
Task keys are auto-converted from camelCase to colon:case (e.g. `depInstall` becomes `dep:install`).
|
|
192
219
|
|
|
193
|
-
**TaskContext
|
|
220
|
+
**TaskContext\<C\>** provides:
|
|
194
221
|
- `run(cmd, options?)` - execute a command on the remote server (auto cd's to `deployPath`)
|
|
195
222
|
- `test(cmd)` - execute a command on the remote server, returns `boolean`
|
|
196
223
|
- `runLocal(cmd, options?)` - execute a command locally
|
|
@@ -198,7 +225,7 @@ Task keys are auto-converted from camelCase to colon:case (e.g. `depInstall` bec
|
|
|
198
225
|
- `server` - current server config (includes `name`)
|
|
199
226
|
- `ssh` - SSH2Promise connection
|
|
200
227
|
- `config` - full deployer config
|
|
201
|
-
- `taskConfig` - per-task config from task definition
|
|
228
|
+
- `taskConfig` - per-task config from task definition (typed as `C` when using `defineTask<C>`)
|
|
202
229
|
|
|
203
230
|
**RunOptions** (for `run` and `runLocal`):
|
|
204
231
|
- `printOutput` - print stdout/stderr (default: `true`)
|
|
@@ -234,8 +261,8 @@ scenarios: {
|
|
|
234
261
|
|
|
235
262
|
| Task | Description |
|
|
236
263
|
| ------------------- | -------------------------------------------------------- |
|
|
237
|
-
| `upload` | Rsync files to the remote server
|
|
238
|
-
| `download` | Rsync files from the remote server (uses task config)
|
|
264
|
+
| `upload` | Rsync files to the remote server (supports multiple file entries) |
|
|
265
|
+
| `download` | Rsync files from the remote server (uses task config, supports multiple file entries) |
|
|
239
266
|
| `symlinks` | Create configured symlinks on the remote server |
|
|
240
267
|
| `install:packages` | Install dependencies via npm/yarn/pnpm |
|
|
241
268
|
| `setup:pm2` | Start/restart PM2 processes (auto-detects pm2.config.*) |
|
package/dist/config.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import type { DeployerConfig, DeployerConfigInput } from './def.js';
|
|
1
|
+
import type { DeployerConfig, DeployerConfigInput, TaskConfigBase } from './def.js';
|
|
2
|
+
export declare function defineTask<C>(input: TaskConfigBase<C>): TaskConfigBase<C>;
|
|
2
3
|
export declare function defineConfig(input: DeployerConfigInput): DeployerConfig;
|
package/dist/config.js
CHANGED
|
@@ -35,6 +35,9 @@ function normalizeScenario(key, input) {
|
|
|
35
35
|
tasks: input.tasks,
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
|
+
export function defineTask(input) {
|
|
39
|
+
return input;
|
|
40
|
+
}
|
|
38
41
|
export function defineConfig(input) {
|
|
39
42
|
const servers = {};
|
|
40
43
|
for (const [name, serverInput] of Object.entries(input.servers)) {
|
package/dist/def.d.ts
CHANGED
|
@@ -19,11 +19,13 @@ export interface ServerConfig {
|
|
|
19
19
|
initCmd?: string;
|
|
20
20
|
}
|
|
21
21
|
export type ServerConfigInput = Partial<ServerConfig> & Pick<ServerConfig, 'host' | 'deployPath'>;
|
|
22
|
-
export interface
|
|
23
|
-
|
|
22
|
+
export interface FilesConfigBase {
|
|
23
|
+
localPath?: string;
|
|
24
|
+
remotePath?: string;
|
|
24
25
|
include?: string[];
|
|
25
26
|
exclude?: string[];
|
|
26
27
|
}
|
|
28
|
+
export type FilesConfig = FilesConfigBase | FilesConfigBase[];
|
|
27
29
|
export interface SymlinkConfig {
|
|
28
30
|
path: string;
|
|
29
31
|
target: string;
|
|
@@ -77,7 +79,7 @@ export type RunOptions = {
|
|
|
77
79
|
printOutput?: boolean;
|
|
78
80
|
ignoreError?: boolean;
|
|
79
81
|
};
|
|
80
|
-
export interface TaskContext {
|
|
82
|
+
export interface TaskContext<C = any> {
|
|
81
83
|
server: ServerConfig & {
|
|
82
84
|
name: string;
|
|
83
85
|
};
|
|
@@ -87,16 +89,18 @@ export interface TaskContext {
|
|
|
87
89
|
testLocal: (cmd: string) => Promise<boolean>;
|
|
88
90
|
run: (cmd: string, options?: RunOptions) => Promise<ExecResult>;
|
|
89
91
|
test: (cmd: string) => Promise<boolean>;
|
|
90
|
-
taskConfig?:
|
|
92
|
+
taskConfig?: C;
|
|
91
93
|
}
|
|
92
|
-
export type TaskFn = (ctx: TaskContext
|
|
94
|
+
export type TaskFn<C = any> = (ctx: TaskContext<C>, ph: Placeholders, task: ListrTaskWrapper<any, any, any>) => Promise<void>;
|
|
93
95
|
export type TaskSkipFn = (ctx: TaskContext, ph: Placeholders) => Promise<boolean | string> | boolean | string;
|
|
94
|
-
export type
|
|
96
|
+
export type TaskConfigBase<C = any> = {
|
|
95
97
|
name?: string;
|
|
96
|
-
task: TaskFn
|
|
98
|
+
task: TaskFn<C>;
|
|
97
99
|
skip?: TaskSkipFn;
|
|
98
|
-
config?:
|
|
100
|
+
config?: C;
|
|
99
101
|
};
|
|
102
|
+
export type TaskConfig<T = any> = T extends TaskFn<infer C> ? TaskConfigBase<C> : TaskConfigBase;
|
|
103
|
+
export type TaskInput<C = any> = TaskFn<C> | TaskConfig<C>;
|
|
100
104
|
export interface ScenarioDef {
|
|
101
105
|
name: string;
|
|
102
106
|
tasks: string[];
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export type { AuthMethod, DeployerConfig, DeployerConfigInput, FilesConfig, LogsConfig, Placeholders, ScenarioDef, ScenarioInput, ServerConfig, ServerConfigInput, SymlinkConfig, TaskContext, TaskDef, TaskFn, TaskInput, TaskSkipFn, } from './def.js';
|
|
2
|
-
export { defineConfig } from './config.js';
|
|
2
|
+
export { defineConfig, defineTask } from './config.js';
|
|
3
3
|
export { runScenario, runTask } from './runner.js';
|
|
4
4
|
export { loadConfig, findConfigFile } from './configLoader.js';
|
|
5
5
|
export { buildRsyncCommand, downloadSkip, downloadTask } from './tasks/index.js';
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { defineConfig } from './config.js';
|
|
1
|
+
export { defineConfig, defineTask } from './config.js';
|
|
2
2
|
export { runScenario, runTask } from './runner.js';
|
|
3
3
|
export { loadConfig, findConfigFile } from './configLoader.js';
|
|
4
4
|
export { buildRsyncCommand, downloadSkip, downloadTask } from './tasks/index.js';
|
package/dist/tasks/download.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { TaskFn, TaskSkipFn } from '../def.js';
|
|
1
|
+
import type { FilesConfig, TaskFn, TaskSkipFn } from '../def.js';
|
|
2
2
|
export declare const downloadSkip: TaskSkipFn;
|
|
3
|
-
export declare const downloadTask: TaskFn
|
|
3
|
+
export declare const downloadTask: TaskFn<FilesConfig>;
|
package/dist/tasks/download.js
CHANGED
|
@@ -9,20 +9,26 @@ export const downloadSkip = (ctx) => {
|
|
|
9
9
|
: false;
|
|
10
10
|
};
|
|
11
11
|
export const downloadTask = async (ctx, ph) => {
|
|
12
|
-
|
|
13
|
-
if (!files) {
|
|
12
|
+
if (!ctx.taskConfig) {
|
|
14
13
|
throw new Exception('No files configuration provided in task config', 1784523741234);
|
|
15
14
|
}
|
|
16
|
-
const
|
|
17
|
-
?
|
|
18
|
-
:
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
15
|
+
const filesArray = ctx.taskConfig instanceof Array
|
|
16
|
+
? ctx.taskConfig
|
|
17
|
+
: [ctx.taskConfig];
|
|
18
|
+
for (const filesEntry of filesArray) {
|
|
19
|
+
const localBase = filesEntry.localPath?.startsWith('/')
|
|
20
|
+
? filesEntry.localPath
|
|
21
|
+
: path.resolve(ctx.config.rootDir, filesEntry.localPath ?? '.');
|
|
22
|
+
const remotePath = filesEntry.remotePath?.startsWith('/')
|
|
23
|
+
? filesEntry.remotePath
|
|
24
|
+
: path.join(ctx.server.deployPath, filesEntry.remotePath ?? '.');
|
|
25
|
+
const source = `${ctx.server.username}@${ctx.server.host}:${remotePath}/`;
|
|
26
|
+
const dest = localBase.endsWith('/') ? localBase : localBase + '/';
|
|
27
|
+
const command = buildRsyncCommand(ctx.server, source, dest, filesEntry, {
|
|
28
|
+
delete: false,
|
|
29
|
+
...ctx.taskConfig,
|
|
30
|
+
});
|
|
31
|
+
console.log(chalk.grey(command));
|
|
32
|
+
await ctx.runLocal(command);
|
|
33
|
+
}
|
|
28
34
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { FilesConfigBase, ServerConfig } from '../../def.js';
|
|
2
2
|
export type RsyncOptions = {
|
|
3
3
|
delete?: boolean;
|
|
4
4
|
dryRun?: boolean;
|
|
5
5
|
};
|
|
6
|
-
export declare function buildRsyncCommand(server: ServerConfig, source: string, dest: string, files:
|
|
6
|
+
export declare function buildRsyncCommand(server: ServerConfig, source: string, dest: string, files: FilesConfigBase, options?: RsyncOptions): string;
|
package/dist/tasks/upload.js
CHANGED
|
@@ -8,18 +8,24 @@ export const uploadSkip = (ctx) => {
|
|
|
8
8
|
: false;
|
|
9
9
|
};
|
|
10
10
|
export const uploadTask = async (ctx, ph) => {
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
11
|
+
const filesArray = ctx.config.files instanceof Array
|
|
12
|
+
? ctx.config.files
|
|
13
|
+
: [ctx.config.files];
|
|
14
|
+
for (const filesEntry of filesArray) {
|
|
15
|
+
const localBase = filesEntry.localPath?.startsWith('/')
|
|
16
|
+
? filesEntry.localPath
|
|
17
|
+
: path.resolve(ctx.config.rootDir, filesEntry.localPath ?? '.');
|
|
18
|
+
const remotePath = filesEntry.remotePath?.startsWith('/')
|
|
19
|
+
? filesEntry.remotePath
|
|
20
|
+
: path.join(ctx.server.deployPath, filesEntry.remotePath ?? '.');
|
|
21
|
+
const dest = `${ctx.server.username}@${ctx.server.host}:${remotePath}`;
|
|
22
|
+
const source = localBase.endsWith('/') ? localBase : localBase + '/';
|
|
23
|
+
await ctx.run(`mkdir -p ${remotePath}`);
|
|
24
|
+
const command = buildRsyncCommand(ctx.server, source, dest, filesEntry, {
|
|
25
|
+
delete: true,
|
|
26
|
+
...ctx.taskConfig,
|
|
27
|
+
});
|
|
28
|
+
console.log(chalk.grey(command));
|
|
29
|
+
await ctx.runLocal(command);
|
|
30
|
+
}
|
|
25
31
|
};
|