kirby-deploy 0.0.5 → 0.1.0

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/dist/cli.js CHANGED
@@ -4,11 +4,11 @@
4
4
  import { runMain } from "citty";
5
5
 
6
6
  // src/commands/main.ts
7
- import { defineCommand as defineCommand3 } from "citty";
8
- import consola8 from "consola";
9
- import { colors as colors5 } from "consola/utils";
7
+ import { defineCommand as defineCommand4 } from "citty";
8
+ import consola9 from "consola";
9
+ import { colors as colors6 } from "consola/utils";
10
10
  import { readFileSync } from "fs";
11
- import { join as join5, relative } from "path/posix";
11
+ import { join as join6, relative } from "path/posix";
12
12
  import { cwd as cwd2 } from "process";
13
13
 
14
14
  // src/config.ts
@@ -34,7 +34,8 @@ var FolderStructureSchema = object({
34
34
  media: string(),
35
35
  accounts: string(),
36
36
  sessions: string(),
37
- cache: string()
37
+ cache: string(),
38
+ site: string()
38
39
  });
39
40
  var ConfigSchema = object({
40
41
  host: string(),
@@ -73,7 +74,8 @@ var loadConfig = async () => {
73
74
  parse(ConfigSchema, config);
74
75
  } catch (e) {
75
76
  const issues = flatten(e).nested;
76
- const info = Object.entries(issues).map(([key, messages]) => ` - ${key} (${messages.join(", ")})`).join("\n");
77
+ if (!issues) return null;
78
+ const info = Object.entries(issues).map(([key, messages = []]) => ` - ${key} (${messages.join(", ")})`).join("\n");
77
79
  consola.error(`Invalid properties in ${configFile}
78
80
  ${info}`);
79
81
  return null;
@@ -86,7 +88,8 @@ ${info}`);
86
88
  media: "public/media",
87
89
  accounts: "storage/accounts",
88
90
  sessions: "storage/sessions",
89
- cache: "storage/cache"
91
+ cache: "storage/cache",
92
+ site: "site"
90
93
  };
91
94
  } else if (config.folderStructure === "flat") {
92
95
  folderStructure = {
@@ -94,7 +97,8 @@ ${info}`);
94
97
  media: "site/media",
95
98
  accounts: "site/accounts",
96
99
  sessions: "site/sessions",
97
- cache: "site/cache"
100
+ cache: "site/cache",
101
+ site: "site"
98
102
  };
99
103
  } else {
100
104
  folderStructure = config.folderStructure;
@@ -139,8 +143,7 @@ var cat = (file, { host, user, password, lftpSettings }) => {
139
143
  const child = isWindows ? spawnSync("wsl", ["lftp", "-c", commands.join("; ")], {
140
144
  encoding: "utf-8"
141
145
  }) : spawnSync("lftp", ["-c", commands.join("; ")], { encoding: "utf-8" });
142
- if (child.stderr)
143
- consola2.error(child.stderr);
146
+ if (child.stderr) consola2.error(child.stderr);
144
147
  return child.stdout;
145
148
  };
146
149
 
@@ -169,8 +172,7 @@ var mirror = (source, destination, flags, { lftpSettings, host, user, password,
169
172
  let hasErrors = false;
170
173
  let hasChanges = false;
171
174
  const handleData = (data) => {
172
- if (verbose)
173
- consola3.log(`${colors.bgBlue(" LFTP ")} ${data}
175
+ if (verbose) consola3.log(`${colors.bgBlue(" LFTP ")} ${data}
174
176
  `);
175
177
  data.toString().split("\n").forEach((line) => {
176
178
  let match = null;
@@ -220,8 +222,7 @@ import * as readline from "node:readline";
220
222
  var upperFirst = (string2) => string2.charAt(0).toUpperCase() + string2.slice(1);
221
223
  var isGit = () => existsSync(join(cwd(), ".git"));
222
224
  var getBranch = () => {
223
- if (!isGit())
224
- return;
225
+ if (!isGit()) return;
225
226
  const { stderr, stdout } = spawnSync2("git", ["branch", "--show-current"], {
226
227
  encoding: "utf-8"
227
228
  });
@@ -301,8 +302,7 @@ var sync = async (source, mode, config) => {
301
302
  return false;
302
303
  }
303
304
  const shouldContinue = await confirm(`Apply changes to ${targetName}?`);
304
- if (!shouldContinue)
305
- return false;
305
+ if (!shouldContinue) return false;
306
306
  consola5.log("");
307
307
  }
308
308
  consola5.log("Apply changes...\n");
@@ -344,8 +344,7 @@ import { colors as colors3 } from "consola/utils";
344
344
  import { join as join3 } from "path/posix";
345
345
  var syncAccounts = async (mode) => {
346
346
  const config = await loadConfig();
347
- if (!config)
348
- return;
347
+ if (!config) return;
349
348
  const { accounts } = config.folderStructure;
350
349
  const source = `./${accounts}/`;
351
350
  const branch = getBranch();
@@ -381,8 +380,7 @@ import { colors as colors4 } from "consola/utils";
381
380
  import { join as join4 } from "path/posix";
382
381
  var syncContent = async (mode) => {
383
382
  const config = await loadConfig();
384
- if (!config)
385
- return;
383
+ if (!config) return;
386
384
  const { content } = config.folderStructure;
387
385
  const source = `./${content}/`;
388
386
  const branch = getBranch();
@@ -410,17 +408,50 @@ var syncContent = async (mode) => {
410
408
  var contentPush = defineCommand2({ run: () => syncContent("push") });
411
409
  var contentPull = defineCommand2({ run: () => syncContent("pull") });
412
410
 
411
+ // src/commands/languages.ts
412
+ import { defineCommand as defineCommand3 } from "citty";
413
+ import consola8 from "consola";
414
+ import { colors as colors5 } from "consola/utils";
415
+ import { join as join5 } from "path/posix";
416
+ var syncLanguages = async (mode) => {
417
+ const config = await loadConfig();
418
+ if (!config) return;
419
+ const { site } = config.folderStructure;
420
+ const source = `./${site}/languages/`;
421
+ const branch = getBranch();
422
+ const displaySource = colors5.magenta(
423
+ `${source}${branch ? colors5.cyan(` (${branch})`) : ""}`
424
+ );
425
+ const displayDestination = colors5.magenta(
426
+ join5(config.host, config.remoteDir, source)
427
+ );
428
+ const direction = mode === "pull" ? "from" : "to";
429
+ consola8.log(
430
+ `\u{1F511} ${upperFirst(mode)} ${displaySource} ${direction} ${displayDestination}
431
+ `
432
+ );
433
+ return sync(source, mode, {
434
+ ...config,
435
+ // User provided includes/excludes can only be used in the main command
436
+ // because they are relative to the base directory, so we reset them.
437
+ exclude: [],
438
+ excludeGlob: [".*", ".*/"],
439
+ include: [],
440
+ includeGlob: []
441
+ });
442
+ };
443
+ var languagesPush = defineCommand3({ run: () => syncLanguages("push") });
444
+ var languagesPull = defineCommand3({ run: () => syncLanguages("pull") });
445
+
413
446
  // src/commands/main.ts
414
- var main = defineCommand3({
447
+ var main = defineCommand4({
415
448
  run: async ({ rawArgs, cmd }) => {
416
449
  const [firstArg] = rawArgs;
417
450
  const subCommands = Object.keys(cmd.subCommands ?? {});
418
451
  const isSubCommand = subCommands.includes(firstArg);
419
- if (isSubCommand)
420
- return;
452
+ if (isSubCommand) return;
421
453
  const config = await loadConfig();
422
- if (!config)
423
- return;
454
+ if (!config) return;
424
455
  const { folderStructure } = config;
425
456
  const exclude = [
426
457
  ...config.exclude,
@@ -429,17 +460,18 @@ var main = defineCommand3({
429
460
  `^${relative(cwd2(), folderStructure.media)}`,
430
461
  `^${relative(cwd2(), folderStructure.accounts)}`,
431
462
  `^${relative(cwd2(), folderStructure.sessions)}`,
432
- `^${relative(cwd2(), folderStructure.cache)}`
463
+ `^${relative(cwd2(), folderStructure.cache)}`,
464
+ `^${relative(cwd2(), join6(folderStructure.site, "languages"))}`
433
465
  ];
434
466
  const excludeGlob = [...config.excludeGlob, ".*", ".*/"];
435
467
  const include = config.include;
436
468
  const includeGlob = [...config.includeGlob, ".htaccess", ".vite/"];
437
469
  const branch = getBranch();
438
- const displaySource = branch ? colors5.cyan(` ${branch} `) : " ";
439
- const displayDestination = colors5.magenta(
440
- join5(config.host, config.remoteDir)
470
+ const displaySource = branch ? colors6.cyan(` ${branch} `) : " ";
471
+ const displayDestination = colors6.magenta(
472
+ join6(config.host, config.remoteDir)
441
473
  );
442
- consola8.log(`\u{1F680} Deploy${displaySource}to ${displayDestination}
474
+ consola9.log(`\u{1F680} Deploy${displaySource}to ${displayDestination}
443
475
  `);
444
476
  if (config.checkComposerLock) {
445
477
  const localComposerLock = readFileSync("./composer.lock", {
@@ -449,7 +481,7 @@ var main = defineCommand3({
449
481
  const skipVendor = localComposerLock === remoteComposerLock;
450
482
  if (skipVendor) {
451
483
  exclude.push("^vendor/", "^kirby/");
452
- consola8.info("Skipping vendor\n");
484
+ consola9.info("Skipping vendor\n");
453
485
  }
454
486
  }
455
487
  await sync("./", "push", {
@@ -464,7 +496,9 @@ var main = defineCommand3({
464
496
  ["content-push"]: contentPush,
465
497
  ["content-pull"]: contentPull,
466
498
  ["accounts-push"]: accountsPush,
467
- ["accounts-pull"]: accountsPull
499
+ ["accounts-pull"]: accountsPull,
500
+ ["languages-push"]: languagesPush,
501
+ ["languages-pull"]: languagesPull
468
502
  }
469
503
  });
470
504
 
package/dist/index.d.ts CHANGED
@@ -1,82 +1,34 @@
1
1
  import * as valibot from 'valibot';
2
- import { Output } from 'valibot';
2
+ import { InferInput } from 'valibot';
3
3
 
4
4
  declare const ConfigSchema: valibot.ObjectSchema<{
5
- host: valibot.StringSchema<string>;
6
- user: valibot.StringSchema<string>;
7
- password: valibot.StringSchema<string>;
8
- url: valibot.OptionalSchema<valibot.StringSchema<string>, undefined, string | undefined>;
9
- token: valibot.OptionalSchema<valibot.StringSchema<string>, undefined, string | undefined>;
10
- remoteDir: valibot.OptionalSchema<valibot.StringSchema<string>, undefined, string | undefined>;
11
- folderStructure: valibot.OptionalSchema<valibot.UnionSchema<(valibot.LiteralSchema<"flat", "flat"> | valibot.LiteralSchema<"public", "public"> | valibot.ObjectSchema<{
12
- content: valibot.StringSchema<string>;
13
- media: valibot.StringSchema<string>;
14
- accounts: valibot.StringSchema<string>;
15
- sessions: valibot.StringSchema<string>;
16
- cache: valibot.StringSchema<string>;
17
- }, undefined, {
18
- content: string;
19
- media: string;
20
- accounts: string;
21
- sessions: string;
22
- cache: string;
23
- }>)[], "flat" | "public" | {
24
- content: string;
25
- media: string;
26
- accounts: string;
27
- sessions: string;
28
- cache: string;
29
- }>, undefined, "flat" | "public" | {
30
- content: string;
31
- media: string;
32
- accounts: string;
33
- sessions: string;
34
- cache: string;
35
- } | undefined>;
36
- checkComposerLock: valibot.OptionalSchema<valibot.BooleanSchema<boolean>, undefined, boolean | undefined>;
37
- callWebhooks: valibot.OptionalSchema<valibot.BooleanSchema<boolean>, undefined, boolean | undefined>;
38
- dryRun: valibot.OptionalSchema<valibot.BooleanSchema<boolean>, undefined, boolean | undefined>;
39
- verbose: valibot.OptionalSchema<valibot.BooleanSchema<boolean>, undefined, boolean | undefined>;
40
- parallel: valibot.OptionalSchema<valibot.NumberSchema<number>, undefined, number | undefined>;
41
- exclude: valibot.OptionalSchema<valibot.ArraySchema<valibot.StringSchema<string>, string[]>, undefined, string[] | undefined>;
42
- excludeGlob: valibot.OptionalSchema<valibot.ArraySchema<valibot.StringSchema<string>, string[]>, undefined, string[] | undefined>;
43
- include: valibot.OptionalSchema<valibot.ArraySchema<valibot.StringSchema<string>, string[]>, undefined, string[] | undefined>;
44
- includeGlob: valibot.OptionalSchema<valibot.ArraySchema<valibot.StringSchema<string>, string[]>, undefined, string[] | undefined>;
45
- lftpSettings: valibot.OptionalSchema<valibot.RecordSchema<valibot.StringSchema<string>, valibot.AnySchema<any>, {
46
- [x: string]: any;
47
- }>, undefined, {
48
- [x: string]: any;
49
- } | undefined>;
50
- lftpFlags: valibot.OptionalSchema<valibot.ArraySchema<valibot.StringSchema<string>, string[]>, undefined, string[] | undefined>;
51
- }, undefined, {
52
- host: string;
53
- user: string;
54
- password: string;
55
- url?: string | undefined;
56
- token?: string | undefined;
57
- remoteDir?: string | undefined;
58
- folderStructure?: "flat" | "public" | {
59
- content: string;
60
- media: string;
61
- accounts: string;
62
- sessions: string;
63
- cache: string;
64
- } | undefined;
65
- checkComposerLock?: boolean | undefined;
66
- callWebhooks?: boolean | undefined;
67
- dryRun?: boolean | undefined;
68
- verbose?: boolean | undefined;
69
- parallel?: number | undefined;
70
- exclude?: string[] | undefined;
71
- excludeGlob?: string[] | undefined;
72
- include?: string[] | undefined;
73
- includeGlob?: string[] | undefined;
74
- lftpSettings?: {
75
- [x: string]: any;
76
- } | undefined;
77
- lftpFlags?: string[] | undefined;
78
- }>;
79
- type Config = Output<typeof ConfigSchema>;
5
+ readonly host: valibot.StringSchema<undefined>;
6
+ readonly user: valibot.StringSchema<undefined>;
7
+ readonly password: valibot.StringSchema<undefined>;
8
+ readonly url: valibot.OptionalSchema<valibot.StringSchema<undefined>, never>;
9
+ readonly token: valibot.OptionalSchema<valibot.StringSchema<undefined>, never>;
10
+ readonly remoteDir: valibot.OptionalSchema<valibot.StringSchema<undefined>, never>;
11
+ readonly folderStructure: valibot.OptionalSchema<valibot.UnionSchema<[valibot.LiteralSchema<"flat", undefined>, valibot.LiteralSchema<"public", undefined>, valibot.ObjectSchema<{
12
+ readonly content: valibot.StringSchema<undefined>;
13
+ readonly media: valibot.StringSchema<undefined>;
14
+ readonly accounts: valibot.StringSchema<undefined>;
15
+ readonly sessions: valibot.StringSchema<undefined>;
16
+ readonly cache: valibot.StringSchema<undefined>;
17
+ readonly site: valibot.StringSchema<undefined>;
18
+ }, undefined>], undefined>, never>;
19
+ readonly checkComposerLock: valibot.OptionalSchema<valibot.BooleanSchema<undefined>, never>;
20
+ readonly callWebhooks: valibot.OptionalSchema<valibot.BooleanSchema<undefined>, never>;
21
+ readonly dryRun: valibot.OptionalSchema<valibot.BooleanSchema<undefined>, never>;
22
+ readonly verbose: valibot.OptionalSchema<valibot.BooleanSchema<undefined>, never>;
23
+ readonly parallel: valibot.OptionalSchema<valibot.NumberSchema<undefined>, never>;
24
+ readonly exclude: valibot.OptionalSchema<valibot.ArraySchema<valibot.StringSchema<undefined>, undefined>, never>;
25
+ readonly excludeGlob: valibot.OptionalSchema<valibot.ArraySchema<valibot.StringSchema<undefined>, undefined>, never>;
26
+ readonly include: valibot.OptionalSchema<valibot.ArraySchema<valibot.StringSchema<undefined>, undefined>, never>;
27
+ readonly includeGlob: valibot.OptionalSchema<valibot.ArraySchema<valibot.StringSchema<undefined>, undefined>, never>;
28
+ readonly lftpSettings: valibot.OptionalSchema<valibot.RecordSchema<valibot.StringSchema<undefined>, valibot.AnySchema, undefined>, never>;
29
+ readonly lftpFlags: valibot.OptionalSchema<valibot.ArraySchema<valibot.StringSchema<undefined>, undefined>, never>;
30
+ }, undefined>;
31
+ type Config = InferInput<typeof ConfigSchema>;
80
32
 
81
33
  declare const defineConfig: (config: Config) => {
82
34
  host: string;
@@ -91,6 +43,7 @@ declare const defineConfig: (config: Config) => {
91
43
  accounts: string;
92
44
  sessions: string;
93
45
  cache: string;
46
+ site: string;
94
47
  } | undefined;
95
48
  checkComposerLock?: boolean | undefined;
96
49
  callWebhooks?: boolean | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kirby-deploy",
3
- "version": "0.0.5",
3
+ "version": "0.1.0",
4
4
  "main": "./dist/index.js",
5
5
  "type": "module",
6
6
  "bin": {
@@ -11,16 +11,16 @@
11
11
  "license": "MIT",
12
12
  "devDependencies": {
13
13
  "@prettier/plugin-php": "^0.22.2",
14
- "@types/node": "^20.11.19",
15
- "prettier": "^3.2.5",
16
- "tsup": "^8.0.2",
17
- "typescript": "^5.3.3"
14
+ "@types/node": "^20.16.10",
15
+ "prettier": "^3.3.3",
16
+ "tsup": "^8.3.0",
17
+ "typescript": "^5.6.2"
18
18
  },
19
19
  "dependencies": {
20
- "c12": "^1.8.0",
20
+ "c12": "^2.0.0",
21
21
  "citty": "^0.1.6",
22
22
  "consola": "^3.2.3",
23
- "valibot": "^0.28.1"
23
+ "valibot": "^0.42.1"
24
24
  },
25
25
  "scripts": {
26
26
  "build": "tsup src/index.ts src/cli.ts --format esm --dts",
@@ -0,0 +1,40 @@
1
+ import { defineCommand } from 'citty'
2
+ import consola from 'consola'
3
+ import { colors } from 'consola/utils'
4
+ import { join } from 'path/posix'
5
+ import { loadConfig } from '../config'
6
+ import { sync } from '../sync'
7
+ import { getBranch, upperFirst } from '../utils'
8
+
9
+ const syncLanguages = async (mode: 'pull' | 'push') => {
10
+ const config = await loadConfig()
11
+ if (!config) return
12
+
13
+ const { site } = config.folderStructure
14
+ const source = `./${site}/languages/`
15
+
16
+ const branch = getBranch()
17
+ const displaySource = colors.magenta(
18
+ `${source}${branch ? colors.cyan(` (${branch})`) : ''}`,
19
+ )
20
+ const displayDestination = colors.magenta(
21
+ join(config.host, config.remoteDir, source),
22
+ )
23
+ const direction = mode === 'pull' ? 'from' : 'to'
24
+ consola.log(
25
+ `🔑 ${upperFirst(mode)} ${displaySource} ${direction} ${displayDestination}\n`,
26
+ )
27
+
28
+ return sync(source, mode, {
29
+ ...config,
30
+ // User provided includes/excludes can only be used in the main command
31
+ // because they are relative to the base directory, so we reset them.
32
+ exclude: [],
33
+ excludeGlob: ['.*', '.*/'],
34
+ include: [],
35
+ includeGlob: [],
36
+ })
37
+ }
38
+
39
+ export const languagesPush = defineCommand({ run: () => syncLanguages('push') })
40
+ export const languagesPull = defineCommand({ run: () => syncLanguages('pull') })
@@ -10,6 +10,7 @@ import { sync } from '../sync'
10
10
  import { getBranch } from '../utils'
11
11
  import { accountsPull, accountsPush } from './accounts'
12
12
  import { contentPull, contentPush } from './content'
13
+ import { languagesPull, languagesPush } from './languages'
13
14
 
14
15
  export const main = defineCommand({
15
16
  run: async ({ rawArgs, cmd }) => {
@@ -32,6 +33,7 @@ export const main = defineCommand({
32
33
  `^${relative(cwd(), folderStructure.accounts)}`,
33
34
  `^${relative(cwd(), folderStructure.sessions)}`,
34
35
  `^${relative(cwd(), folderStructure.cache)}`,
36
+ `^${relative(cwd(), join(folderStructure.site, 'languages'))}`,
35
37
  ]
36
38
  const excludeGlob = [...config.excludeGlob, '.*', '.*/']
37
39
  const include = config.include
@@ -67,7 +69,11 @@ export const main = defineCommand({
67
69
  subCommands: {
68
70
  ['content-push']: contentPush,
69
71
  ['content-pull']: contentPull,
72
+
70
73
  ['accounts-push']: accountsPush,
71
74
  ['accounts-pull']: accountsPull,
75
+
76
+ ['languages-push']: languagesPush,
77
+ ['languages-pull']: languagesPull,
72
78
  },
73
79
  })
package/src/config.ts CHANGED
@@ -19,8 +19,9 @@ export const loadConfig = async (): Promise<ConfigResolved | null> => {
19
19
  parse(ConfigSchema, config)
20
20
  } catch (e: any) {
21
21
  const issues = flatten<typeof ConfigSchema>(e).nested
22
+ if (!issues) return null
22
23
  const info = Object.entries(issues)
23
- .map(([key, messages]) => ` - ${key} (${messages.join(', ')})`)
24
+ .map(([key, messages = []]) => ` - ${key} (${messages.join(', ')})`)
24
25
  .join('\n')
25
26
  consola.error(`Invalid properties in ${configFile}\n${info}`)
26
27
  return null
@@ -37,6 +38,7 @@ export const loadConfig = async (): Promise<ConfigResolved | null> => {
37
38
  accounts: 'storage/accounts',
38
39
  sessions: 'storage/sessions',
39
40
  cache: 'storage/cache',
41
+ site: 'site',
40
42
  }
41
43
  } else if (config.folderStructure === 'flat') {
42
44
  // 'flat' structure is the default.
@@ -46,6 +48,7 @@ export const loadConfig = async (): Promise<ConfigResolved | null> => {
46
48
  accounts: 'site/accounts',
47
49
  sessions: 'site/sessions',
48
50
  cache: 'site/cache',
51
+ site: 'site',
49
52
  }
50
53
  } else {
51
54
  folderStructure = config.folderStructure
package/src/types.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import {
2
- Output,
3
2
  any,
4
3
  array,
5
4
  boolean,
5
+ InferInput,
6
6
  literal,
7
7
  number,
8
8
  object,
@@ -18,9 +18,10 @@ export const FolderStructureSchema = object({
18
18
  accounts: string(),
19
19
  sessions: string(),
20
20
  cache: string(),
21
+ site: string(),
21
22
  })
22
23
 
23
- export type FolderStructure = Output<typeof FolderStructureSchema>
24
+ export type FolderStructure = InferInput<typeof FolderStructureSchema>
24
25
 
25
26
  export const ConfigSchema = object({
26
27
  host: string(),
@@ -45,7 +46,7 @@ export const ConfigSchema = object({
45
46
  lftpFlags: optional(array(string())),
46
47
  })
47
48
 
48
- export type Config = Output<typeof ConfigSchema>
49
+ export type Config = InferInput<typeof ConfigSchema>
49
50
 
50
51
  type ConfigWithDefaults = Pick<Config, 'url' | 'token'> &
51
52
  Required<Omit<Config, 'url' | 'token'>>