d3ployer 0.0.13 → 0.0.15
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 +48 -8
- package/dist/config.d.ts +2 -1
- package/dist/config.js +3 -0
- package/dist/def.d.ts +17 -8
- package/dist/index.d.ts +2 -3
- 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 -6
- package/dist/tasks/index.d.ts +0 -1
- package/dist/tasks/upload.d.ts +2 -2
- package/dist/tasks/upload.js +21 -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,9 +103,32 @@ 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
|
|
110
|
+
}
|
|
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
|
+
|
|
122
|
+
Each entry can also include per-entry rsync options:
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
files: {
|
|
126
|
+
localPath: './dist',
|
|
127
|
+
exclude: ['node_modules'],
|
|
128
|
+
rsync: {
|
|
129
|
+
delete: false, // don't delete extra files on remote (default: true for upload, false for download)
|
|
130
|
+
dryRun: true, // preview changes without applying them
|
|
131
|
+
},
|
|
109
132
|
}
|
|
110
133
|
```
|
|
111
134
|
|
|
@@ -188,9 +211,26 @@ tasks: {
|
|
|
188
211
|
}
|
|
189
212
|
```
|
|
190
213
|
|
|
214
|
+
Use `defineTask` for type-safe task definitions with a typed config:
|
|
215
|
+
|
|
216
|
+
```ts
|
|
217
|
+
import { defineConfig, defineTask } from 'd3ployer';
|
|
218
|
+
|
|
219
|
+
export default defineConfig({
|
|
220
|
+
tasks: {
|
|
221
|
+
myTask: defineTask<{ retries: number }>({
|
|
222
|
+
task: async (ctx) => {
|
|
223
|
+
const retries = ctx.taskConfig!.retries; // typed as number
|
|
224
|
+
},
|
|
225
|
+
config: { retries: 3 },
|
|
226
|
+
}),
|
|
227
|
+
},
|
|
228
|
+
});
|
|
229
|
+
```
|
|
230
|
+
|
|
191
231
|
Task keys are auto-converted from camelCase to colon:case (e.g. `depInstall` becomes `dep:install`).
|
|
192
232
|
|
|
193
|
-
**TaskContext
|
|
233
|
+
**TaskContext\<C\>** provides:
|
|
194
234
|
- `run(cmd, options?)` - execute a command on the remote server (auto cd's to `deployPath`)
|
|
195
235
|
- `test(cmd)` - execute a command on the remote server, returns `boolean`
|
|
196
236
|
- `runLocal(cmd, options?)` - execute a command locally
|
|
@@ -198,7 +238,7 @@ Task keys are auto-converted from camelCase to colon:case (e.g. `depInstall` bec
|
|
|
198
238
|
- `server` - current server config (includes `name`)
|
|
199
239
|
- `ssh` - SSH2Promise connection
|
|
200
240
|
- `config` - full deployer config
|
|
201
|
-
- `taskConfig` - per-task config from task definition
|
|
241
|
+
- `taskConfig` - per-task config from task definition (typed as `C` when using `defineTask<C>`)
|
|
202
242
|
|
|
203
243
|
**RunOptions** (for `run` and `runLocal`):
|
|
204
244
|
- `printOutput` - print stdout/stderr (default: `true`)
|
|
@@ -234,8 +274,8 @@ scenarios: {
|
|
|
234
274
|
|
|
235
275
|
| Task | Description |
|
|
236
276
|
| ------------------- | -------------------------------------------------------- |
|
|
237
|
-
| `upload` | Rsync files to the remote server
|
|
238
|
-
| `download` | Rsync files from the remote server (uses task config)
|
|
277
|
+
| `upload` | Rsync files to the remote server (supports multiple file entries) |
|
|
278
|
+
| `download` | Rsync files from the remote server (uses task config, supports multiple file entries) |
|
|
239
279
|
| `symlinks` | Create configured symlinks on the remote server |
|
|
240
280
|
| `install:packages` | Install dependencies via npm/yarn/pnpm |
|
|
241
281
|
| `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,18 @@ export interface ServerConfig {
|
|
|
19
19
|
initCmd?: string;
|
|
20
20
|
}
|
|
21
21
|
export type ServerConfigInput = Partial<ServerConfig> & Pick<ServerConfig, 'host' | 'deployPath'>;
|
|
22
|
-
export
|
|
23
|
-
|
|
22
|
+
export type RsyncOptions = {
|
|
23
|
+
delete?: boolean;
|
|
24
|
+
dryRun?: boolean;
|
|
25
|
+
};
|
|
26
|
+
export interface FilesConfigBase {
|
|
27
|
+
localPath?: string;
|
|
28
|
+
remotePath?: string;
|
|
24
29
|
include?: string[];
|
|
25
30
|
exclude?: string[];
|
|
31
|
+
rsync?: RsyncOptions;
|
|
26
32
|
}
|
|
33
|
+
export type FilesConfig = FilesConfigBase | FilesConfigBase[];
|
|
27
34
|
export interface SymlinkConfig {
|
|
28
35
|
path: string;
|
|
29
36
|
target: string;
|
|
@@ -77,7 +84,7 @@ export type RunOptions = {
|
|
|
77
84
|
printOutput?: boolean;
|
|
78
85
|
ignoreError?: boolean;
|
|
79
86
|
};
|
|
80
|
-
export interface TaskContext {
|
|
87
|
+
export interface TaskContext<C = any> {
|
|
81
88
|
server: ServerConfig & {
|
|
82
89
|
name: string;
|
|
83
90
|
};
|
|
@@ -87,16 +94,18 @@ export interface TaskContext {
|
|
|
87
94
|
testLocal: (cmd: string) => Promise<boolean>;
|
|
88
95
|
run: (cmd: string, options?: RunOptions) => Promise<ExecResult>;
|
|
89
96
|
test: (cmd: string) => Promise<boolean>;
|
|
90
|
-
taskConfig?:
|
|
97
|
+
taskConfig?: C;
|
|
91
98
|
}
|
|
92
|
-
export type TaskFn = (ctx: TaskContext
|
|
99
|
+
export type TaskFn<C = any> = (ctx: TaskContext<C>, ph: Placeholders, task: ListrTaskWrapper<any, any, any>) => Promise<void>;
|
|
93
100
|
export type TaskSkipFn = (ctx: TaskContext, ph: Placeholders) => Promise<boolean | string> | boolean | string;
|
|
94
|
-
export type
|
|
101
|
+
export type TaskConfigBase<C = any> = {
|
|
95
102
|
name?: string;
|
|
96
|
-
task: TaskFn
|
|
103
|
+
task: TaskFn<C>;
|
|
97
104
|
skip?: TaskSkipFn;
|
|
98
|
-
config?:
|
|
105
|
+
config?: C;
|
|
99
106
|
};
|
|
107
|
+
export type TaskConfig<T = any> = T extends TaskFn<infer C> ? TaskConfigBase<C> : TaskConfigBase;
|
|
108
|
+
export type TaskInput<C = any> = TaskFn<C> | TaskConfig<C>;
|
|
100
109
|
export interface ScenarioDef {
|
|
101
110
|
name: string;
|
|
102
111
|
tasks: string[];
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
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';
|
|
1
|
+
export type { AuthMethod, DeployerConfig, DeployerConfigInput, FilesConfig, LogsConfig, Placeholders, RsyncOptions, ScenarioDef, ScenarioInput, ServerConfig, ServerConfigInput, SymlinkConfig, TaskContext, TaskDef, TaskFn, TaskInput, TaskSkipFn, } from './def.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';
|
|
6
|
-
export type { RsyncOptions } 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
|
+
...filesEntry.rsync,
|
|
30
|
+
});
|
|
31
|
+
console.log(chalk.grey(command));
|
|
32
|
+
await ctx.runLocal(command);
|
|
33
|
+
}
|
|
28
34
|
};
|
|
@@ -1,6 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export
|
|
3
|
-
delete?: boolean;
|
|
4
|
-
dryRun?: boolean;
|
|
5
|
-
};
|
|
6
|
-
export declare function buildRsyncCommand(server: ServerConfig, source: string, dest: string, files: FilesConfig, options?: RsyncOptions): string;
|
|
1
|
+
import type { FilesConfigBase, RsyncOptions, ServerConfig } from '../../def.js';
|
|
2
|
+
export declare function buildRsyncCommand(server: ServerConfig, source: string, dest: string, files: FilesConfigBase, options?: RsyncOptions): string;
|
package/dist/tasks/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { ScenarioDef, TaskDef } from '../def.js';
|
|
2
2
|
export { buildRsyncCommand } from './helpers/rsync.js';
|
|
3
|
-
export type { RsyncOptions } from './helpers/rsync.js';
|
|
4
3
|
export { downloadSkip, downloadTask } from './download.js';
|
|
5
4
|
export declare const defaultTasks: Record<string, TaskDef>;
|
|
6
5
|
export declare const defaultScenarios: Record<string, ScenarioDef>;
|
package/dist/tasks/upload.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 uploadSkip: TaskSkipFn;
|
|
3
|
-
export declare const uploadTask: TaskFn
|
|
3
|
+
export declare const uploadTask: TaskFn<FilesConfig>;
|
package/dist/tasks/upload.js
CHANGED
|
@@ -8,18 +8,25 @@ export const uploadSkip = (ctx) => {
|
|
|
8
8
|
: false;
|
|
9
9
|
};
|
|
10
10
|
export const uploadTask = async (ctx, ph) => {
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
?
|
|
14
|
-
:
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
11
|
+
const configSource = ctx.taskConfig ?? ctx.config.files;
|
|
12
|
+
const filesArray = configSource instanceof Array
|
|
13
|
+
? configSource
|
|
14
|
+
: [configSource];
|
|
15
|
+
for (const filesEntry of filesArray) {
|
|
16
|
+
const localBase = filesEntry.localPath?.startsWith('/')
|
|
17
|
+
? filesEntry.localPath
|
|
18
|
+
: path.resolve(ctx.config.rootDir, filesEntry.localPath ?? '.');
|
|
19
|
+
const remotePath = filesEntry.remotePath?.startsWith('/')
|
|
20
|
+
? filesEntry.remotePath
|
|
21
|
+
: path.join(ctx.server.deployPath, filesEntry.remotePath ?? '.');
|
|
22
|
+
const dest = `${ctx.server.username}@${ctx.server.host}:${remotePath}`;
|
|
23
|
+
const source = localBase.endsWith('/') ? localBase : localBase + '/';
|
|
24
|
+
await ctx.run(`mkdir -p ${remotePath}`);
|
|
25
|
+
const command = buildRsyncCommand(ctx.server, source, dest, filesEntry, {
|
|
26
|
+
delete: true,
|
|
27
|
+
...filesEntry.rsync,
|
|
28
|
+
});
|
|
29
|
+
console.log(chalk.grey(command));
|
|
30
|
+
await ctx.runLocal(command);
|
|
31
|
+
}
|
|
25
32
|
};
|