syncast-cli 0.1.1 → 0.1.2

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.
Files changed (3) hide show
  1. package/dist/cli.js +133 -7
  2. package/dist/index.js +135 -8
  3. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -1,12 +1,138 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from "commander";
3
- import { CHUNK_SIZE, DEFAULT_HOST, DEFAULT_PORT, ErrorCodes, FILE_CHANGE_DEBOUNCE_MS, FILE_STABLE_CHECK_INTERVAL_MS, createConnectedMessage, createErrorMessage, createFileConfig, createFolderConfig, getFileConfigPath, getFilename, getFolderConfigPath, isConfigFile, isSupportedFile, parseFileConfig, parseFolderConfig, toRelativePath } from "local-sync-protocol";
4
3
  import { WebSocketServer } from "ws";
5
4
  import { mkdir, readFile, readdir, stat as promises_stat, writeFile } from "node:fs/promises";
6
5
  import { dirname as external_node_path_dirname, join } from "node:path";
7
6
  import { exec } from "node:child_process";
8
7
  import { promisify } from "node:util";
9
8
  import { watch } from "chokidar";
9
+ const DEFAULT_HOST = "localhost";
10
+ const CHUNK_SIZE = 1048576;
11
+ const FILE_CONFIG_SUFFIX = ".config.json";
12
+ const FOLDER_CONFIG_SUFFIX = ".folder.config.json";
13
+ const SUPPORTED_EXTENSIONS = [
14
+ "jpg",
15
+ "jpeg",
16
+ "png",
17
+ "webp",
18
+ "gif",
19
+ "mp4",
20
+ "mov",
21
+ "m4v",
22
+ "webm",
23
+ "mp3",
24
+ "wav",
25
+ "ogg",
26
+ "m4a"
27
+ ];
28
+ function createFileConfig(assetId, originalFilename, md5) {
29
+ return {
30
+ assetId,
31
+ syncedAt: new Date().toISOString(),
32
+ originalFilename,
33
+ md5
34
+ };
35
+ }
36
+ function createFolderConfig(folderId) {
37
+ return {
38
+ folderId,
39
+ syncedAt: new Date().toISOString()
40
+ };
41
+ }
42
+ function parseFileConfig(content) {
43
+ try {
44
+ const config = JSON.parse(content);
45
+ if (!config.assetId || "string" != typeof config.assetId) {
46
+ console.warn("Invalid config.json: missing or invalid assetId");
47
+ return null;
48
+ }
49
+ if (!config.originalFilename || "string" != typeof config.originalFilename) {
50
+ console.warn("Invalid config.json: missing or invalid originalFilename");
51
+ return null;
52
+ }
53
+ return config;
54
+ } catch (e) {
55
+ console.warn("Failed to parse config.json:", e);
56
+ return null;
57
+ }
58
+ }
59
+ function parseFolderConfig(content) {
60
+ try {
61
+ const config = JSON.parse(content);
62
+ if (!config.folderId || "string" != typeof config.folderId) {
63
+ console.warn("Invalid folder config.json: missing or invalid folderId");
64
+ return null;
65
+ }
66
+ return config;
67
+ } catch (e) {
68
+ console.warn("Failed to parse folder config.json:", e);
69
+ return null;
70
+ }
71
+ }
72
+ function getFileConfigPath(filePath) {
73
+ return `${filePath}${FILE_CONFIG_SUFFIX}`;
74
+ }
75
+ function getFolderConfigPath(folderPath) {
76
+ const normalizedPath = folderPath.replace(/\/+$/, "");
77
+ return `${normalizedPath}${FOLDER_CONFIG_SUFFIX}`;
78
+ }
79
+ function isConfigFile(path) {
80
+ return path.endsWith(FOLDER_CONFIG_SUFFIX) || path.endsWith(FILE_CONFIG_SUFFIX);
81
+ }
82
+ function getFileExtension(filename) {
83
+ const lastDot = filename.lastIndexOf(".");
84
+ if (-1 === lastDot || lastDot === filename.length - 1) return "";
85
+ return filename.slice(lastDot + 1).toLowerCase();
86
+ }
87
+ function isSupportedFile(filename) {
88
+ const ext = getFileExtension(filename);
89
+ return ext ? SUPPORTED_EXTENSIONS.includes(ext) : false;
90
+ }
91
+ function getFilename(path) {
92
+ const normalized = path.replace(/\\/g, "/");
93
+ const parts = normalized.split("/");
94
+ return parts[parts.length - 1] || "";
95
+ }
96
+ function normalizePath(path) {
97
+ return path.replace(/\\/g, "/").replace(/\/+$/, "");
98
+ }
99
+ function toRelativePath(absolutePath, basePath) {
100
+ const normalizedAbs = normalizePath(absolutePath);
101
+ const normalizedBase = normalizePath(basePath);
102
+ if (!normalizedAbs.startsWith(normalizedBase)) return normalizedAbs;
103
+ let relative = normalizedAbs.slice(normalizedBase.length);
104
+ if (relative.startsWith("/")) relative = relative.slice(1);
105
+ return relative;
106
+ }
107
+ function createConnectedMessage(cwd) {
108
+ return {
109
+ type: "connected",
110
+ cwd,
111
+ version: "1.0.0"
112
+ };
113
+ }
114
+ function createErrorMessage(code, message, requestId) {
115
+ return {
116
+ type: "error",
117
+ code,
118
+ message,
119
+ requestId
120
+ };
121
+ }
122
+ const ErrorCodes = {
123
+ FILE_NOT_FOUND: "FILE_NOT_FOUND",
124
+ FOLDER_NOT_FOUND: "FOLDER_NOT_FOUND",
125
+ PERMISSION_DENIED: "PERMISSION_DENIED",
126
+ FILE_IN_USE: "FILE_IN_USE",
127
+ TRANSFER_CANCELLED: "TRANSFER_CANCELLED",
128
+ INVALID_REQUEST_ID: "INVALID_REQUEST_ID",
129
+ VERSION_MISMATCH: "VERSION_MISMATCH",
130
+ PROJECT_ALREADY_CONNECTED: "PROJECT_ALREADY_CONNECTED",
131
+ UNKNOWN_ERROR: "UNKNOWN_ERROR"
132
+ };
133
+ var __webpack_exports__DEFAULT_PORT = 23456;
134
+ var __webpack_exports__FILE_CHANGE_DEBOUNCE_MS = 300;
135
+ var __webpack_exports__FILE_STABLE_CHECK_INTERVAL_MS = 500;
10
136
  class FileTransferManager {
11
137
  rootPath;
12
138
  events;
@@ -136,7 +262,7 @@ class FileChangeCollector {
136
262
  this.timer = setTimeout(()=>{
137
263
  this.flush();
138
264
  this.timer = null;
139
- }, FILE_CHANGE_DEBOUNCE_MS);
265
+ }, __webpack_exports__FILE_CHANGE_DEBOUNCE_MS);
140
266
  }
141
267
  flush() {
142
268
  if (0 === this.pending.size) return;
@@ -252,7 +378,7 @@ class FileWatcher {
252
378
  persistent: true,
253
379
  ignoreInitial: true,
254
380
  awaitWriteFinish: {
255
- stabilityThreshold: FILE_STABLE_CHECK_INTERVAL_MS,
381
+ stabilityThreshold: __webpack_exports__FILE_STABLE_CHECK_INTERVAL_MS,
256
382
  pollInterval: 100
257
383
  }
258
384
  });
@@ -359,7 +485,7 @@ class SyncServer {
359
485
  isProcessingQueue = false;
360
486
  currentProjectId = null;
361
487
  constructor(options = {}, events = {}){
362
- this.port = options.port ?? DEFAULT_PORT;
488
+ this.port = options.port ?? __webpack_exports__DEFAULT_PORT;
363
489
  this.host = options.host ?? DEFAULT_HOST;
364
490
  this.cwd = process.cwd();
365
491
  this.events = events;
@@ -677,7 +803,7 @@ class SyncServer {
677
803
  }
678
804
  const program = new Command();
679
805
  program.name("syncast-cli").description("Syncast CLI tool for local file sync").version("0.1.0");
680
- program.command("sync").description("Start the local sync server").option("-p, --port <port>", "Port to listen on", String(DEFAULT_PORT)).option("-H, --host <host>", "Host to bind to", DEFAULT_HOST).action(startSyncServer);
806
+ program.command("sync").description("Start the local sync server").option("-p, --port <port>", "Port to listen on", String(__webpack_exports__DEFAULT_PORT)).option("-H, --host <host>", "Host to bind to", DEFAULT_HOST).action(startSyncServer);
681
807
  async function startSyncServer(options) {
682
808
  const port = Number.parseInt(options.port, 10);
683
809
  const host = options.host;
@@ -724,8 +850,8 @@ async function startSyncServer(options) {
724
850
  process.on("SIGTERM", shutdown);
725
851
  await new Promise(()=>{});
726
852
  }
727
- program.command("start").description("Alias for 'sync' command - Start the local sync server").option("-p, --port <port>", "Port to listen on", String(DEFAULT_PORT)).option("-H, --host <host>", "Host to bind to", DEFAULT_HOST).action(startSyncServer);
728
- program.command("status").description("Check if a sync server is running").option("-p, --port <port>", "Port to check", String(DEFAULT_PORT)).option("-H, --host <host>", "Host to check", DEFAULT_HOST).action(async (options)=>{
853
+ program.command("start").description("Alias for 'sync' command - Start the local sync server").option("-p, --port <port>", "Port to listen on", String(__webpack_exports__DEFAULT_PORT)).option("-H, --host <host>", "Host to bind to", DEFAULT_HOST).action(startSyncServer);
854
+ program.command("status").description("Check if a sync server is running").option("-p, --port <port>", "Port to check", String(__webpack_exports__DEFAULT_PORT)).option("-H, --host <host>", "Host to check", DEFAULT_HOST).action(async (options)=>{
729
855
  const port = Number.parseInt(options.port, 10);
730
856
  const host = options.host;
731
857
  const address = `ws://${host}:${port}`;
package/dist/index.js CHANGED
@@ -1,4 +1,3 @@
1
- import { CHUNK_SIZE, DEFAULT_HOST, DEFAULT_PORT, ErrorCodes, FILE_CHANGE_DEBOUNCE_MS, FILE_STABLE_CHECK_INTERVAL_MS, PROTOCOL_VERSION, createConnectedMessage, createErrorMessage, createFileConfig, createFolderConfig, getFileConfigPath, getFilename, getFolderConfigPath, isConfigFile, isSupportedFile, parseFileConfig, parseFolderConfig, toRelativePath } from "local-sync-protocol";
2
1
  import { WebSocketServer } from "ws";
3
2
  import { mkdir, readFile, readdir, stat as promises_stat, writeFile } from "node:fs/promises";
4
3
  import { dirname as external_node_path_dirname, join } from "node:path";
@@ -6,6 +5,134 @@ import { exec } from "node:child_process";
6
5
  import { promisify } from "node:util";
7
6
  import { watch } from "chokidar";
8
7
  import { Command } from "commander";
8
+ const DEFAULT_HOST = "localhost";
9
+ const CHUNK_SIZE = 1048576;
10
+ const FILE_CONFIG_SUFFIX = ".config.json";
11
+ const FOLDER_CONFIG_SUFFIX = ".folder.config.json";
12
+ const SUPPORTED_EXTENSIONS = [
13
+ "jpg",
14
+ "jpeg",
15
+ "png",
16
+ "webp",
17
+ "gif",
18
+ "mp4",
19
+ "mov",
20
+ "m4v",
21
+ "webm",
22
+ "mp3",
23
+ "wav",
24
+ "ogg",
25
+ "m4a"
26
+ ];
27
+ function createFileConfig(assetId, originalFilename, md5) {
28
+ return {
29
+ assetId,
30
+ syncedAt: new Date().toISOString(),
31
+ originalFilename,
32
+ md5
33
+ };
34
+ }
35
+ function createFolderConfig(folderId) {
36
+ return {
37
+ folderId,
38
+ syncedAt: new Date().toISOString()
39
+ };
40
+ }
41
+ function parseFileConfig(content) {
42
+ try {
43
+ const config = JSON.parse(content);
44
+ if (!config.assetId || "string" != typeof config.assetId) {
45
+ console.warn("Invalid config.json: missing or invalid assetId");
46
+ return null;
47
+ }
48
+ if (!config.originalFilename || "string" != typeof config.originalFilename) {
49
+ console.warn("Invalid config.json: missing or invalid originalFilename");
50
+ return null;
51
+ }
52
+ return config;
53
+ } catch (e) {
54
+ console.warn("Failed to parse config.json:", e);
55
+ return null;
56
+ }
57
+ }
58
+ function parseFolderConfig(content) {
59
+ try {
60
+ const config = JSON.parse(content);
61
+ if (!config.folderId || "string" != typeof config.folderId) {
62
+ console.warn("Invalid folder config.json: missing or invalid folderId");
63
+ return null;
64
+ }
65
+ return config;
66
+ } catch (e) {
67
+ console.warn("Failed to parse folder config.json:", e);
68
+ return null;
69
+ }
70
+ }
71
+ function getFileConfigPath(filePath) {
72
+ return `${filePath}${FILE_CONFIG_SUFFIX}`;
73
+ }
74
+ function getFolderConfigPath(folderPath) {
75
+ const normalizedPath = folderPath.replace(/\/+$/, "");
76
+ return `${normalizedPath}${FOLDER_CONFIG_SUFFIX}`;
77
+ }
78
+ function isConfigFile(path) {
79
+ return path.endsWith(FOLDER_CONFIG_SUFFIX) || path.endsWith(FILE_CONFIG_SUFFIX);
80
+ }
81
+ function getFileExtension(filename) {
82
+ const lastDot = filename.lastIndexOf(".");
83
+ if (-1 === lastDot || lastDot === filename.length - 1) return "";
84
+ return filename.slice(lastDot + 1).toLowerCase();
85
+ }
86
+ function isSupportedFile(filename) {
87
+ const ext = getFileExtension(filename);
88
+ return ext ? SUPPORTED_EXTENSIONS.includes(ext) : false;
89
+ }
90
+ function getFilename(path) {
91
+ const normalized = path.replace(/\\/g, "/");
92
+ const parts = normalized.split("/");
93
+ return parts[parts.length - 1] || "";
94
+ }
95
+ function normalizePath(path) {
96
+ return path.replace(/\\/g, "/").replace(/\/+$/, "");
97
+ }
98
+ function toRelativePath(absolutePath, basePath) {
99
+ const normalizedAbs = normalizePath(absolutePath);
100
+ const normalizedBase = normalizePath(basePath);
101
+ if (!normalizedAbs.startsWith(normalizedBase)) return normalizedAbs;
102
+ let relative = normalizedAbs.slice(normalizedBase.length);
103
+ if (relative.startsWith("/")) relative = relative.slice(1);
104
+ return relative;
105
+ }
106
+ function createConnectedMessage(cwd) {
107
+ return {
108
+ type: "connected",
109
+ cwd,
110
+ version: "1.0.0"
111
+ };
112
+ }
113
+ function createErrorMessage(code, message, requestId) {
114
+ return {
115
+ type: "error",
116
+ code,
117
+ message,
118
+ requestId
119
+ };
120
+ }
121
+ const ErrorCodes = {
122
+ FILE_NOT_FOUND: "FILE_NOT_FOUND",
123
+ FOLDER_NOT_FOUND: "FOLDER_NOT_FOUND",
124
+ PERMISSION_DENIED: "PERMISSION_DENIED",
125
+ FILE_IN_USE: "FILE_IN_USE",
126
+ TRANSFER_CANCELLED: "TRANSFER_CANCELLED",
127
+ INVALID_REQUEST_ID: "INVALID_REQUEST_ID",
128
+ VERSION_MISMATCH: "VERSION_MISMATCH",
129
+ PROJECT_ALREADY_CONNECTED: "PROJECT_ALREADY_CONNECTED",
130
+ UNKNOWN_ERROR: "UNKNOWN_ERROR"
131
+ };
132
+ var __webpack_exports__DEFAULT_PORT = 23456;
133
+ var __webpack_exports__FILE_CHANGE_DEBOUNCE_MS = 300;
134
+ var __webpack_exports__FILE_STABLE_CHECK_INTERVAL_MS = 500;
135
+ var __webpack_exports__PROTOCOL_VERSION = "1.0.0";
9
136
  class FileTransferManager {
10
137
  rootPath;
11
138
  events;
@@ -135,7 +262,7 @@ class FileChangeCollector {
135
262
  this.timer = setTimeout(()=>{
136
263
  this.flush();
137
264
  this.timer = null;
138
- }, FILE_CHANGE_DEBOUNCE_MS);
265
+ }, __webpack_exports__FILE_CHANGE_DEBOUNCE_MS);
139
266
  }
140
267
  flush() {
141
268
  if (0 === this.pending.size) return;
@@ -251,7 +378,7 @@ class FileWatcher {
251
378
  persistent: true,
252
379
  ignoreInitial: true,
253
380
  awaitWriteFinish: {
254
- stabilityThreshold: FILE_STABLE_CHECK_INTERVAL_MS,
381
+ stabilityThreshold: __webpack_exports__FILE_STABLE_CHECK_INTERVAL_MS,
255
382
  pollInterval: 100
256
383
  }
257
384
  });
@@ -358,7 +485,7 @@ class SyncServer {
358
485
  isProcessingQueue = false;
359
486
  currentProjectId = null;
360
487
  constructor(options = {}, events = {}){
361
- this.port = options.port ?? DEFAULT_PORT;
488
+ this.port = options.port ?? __webpack_exports__DEFAULT_PORT;
362
489
  this.host = options.host ?? DEFAULT_HOST;
363
490
  this.cwd = process.cwd();
364
491
  this.events = events;
@@ -676,7 +803,7 @@ class SyncServer {
676
803
  }
677
804
  const program = new Command();
678
805
  program.name("syncast-cli").description("Syncast CLI tool for local file sync").version("0.1.0");
679
- program.command("sync").description("Start the local sync server").option("-p, --port <port>", "Port to listen on", String(DEFAULT_PORT)).option("-H, --host <host>", "Host to bind to", DEFAULT_HOST).action(startSyncServer);
806
+ program.command("sync").description("Start the local sync server").option("-p, --port <port>", "Port to listen on", String(__webpack_exports__DEFAULT_PORT)).option("-H, --host <host>", "Host to bind to", DEFAULT_HOST).action(startSyncServer);
680
807
  async function startSyncServer(options) {
681
808
  const port = Number.parseInt(options.port, 10);
682
809
  const host = options.host;
@@ -723,8 +850,8 @@ async function startSyncServer(options) {
723
850
  process.on("SIGTERM", shutdown);
724
851
  await new Promise(()=>{});
725
852
  }
726
- program.command("start").description("Alias for 'sync' command - Start the local sync server").option("-p, --port <port>", "Port to listen on", String(DEFAULT_PORT)).option("-H, --host <host>", "Host to bind to", DEFAULT_HOST).action(startSyncServer);
727
- program.command("status").description("Check if a sync server is running").option("-p, --port <port>", "Port to check", String(DEFAULT_PORT)).option("-H, --host <host>", "Host to check", DEFAULT_HOST).action(async (options)=>{
853
+ program.command("start").description("Alias for 'sync' command - Start the local sync server").option("-p, --port <port>", "Port to listen on", String(__webpack_exports__DEFAULT_PORT)).option("-H, --host <host>", "Host to bind to", DEFAULT_HOST).action(startSyncServer);
854
+ program.command("status").description("Check if a sync server is running").option("-p, --port <port>", "Port to check", String(__webpack_exports__DEFAULT_PORT)).option("-H, --host <host>", "Host to check", DEFAULT_HOST).action(async (options)=>{
728
855
  const port = Number.parseInt(options.port, 10);
729
856
  const host = options.host;
730
857
  const address = `ws://${host}:${port}`;
@@ -757,4 +884,4 @@ async function runCli(args = process.argv) {
757
884
  await program.parseAsync(args);
758
885
  }
759
886
  runCli();
760
- export { DEFAULT_HOST, DEFAULT_PORT, FileTransferManager, FileWatcher, PROTOCOL_VERSION, SyncServer, runCli };
887
+ export { DEFAULT_HOST, __webpack_exports__DEFAULT_PORT as DEFAULT_PORT, FileTransferManager, FileWatcher, __webpack_exports__PROTOCOL_VERSION as PROTOCOL_VERSION, SyncServer, runCli };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "syncast-cli",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Syncast CLI tool",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -34,7 +34,6 @@
34
34
  "dependencies": {
35
35
  "chokidar": "^4.0.3",
36
36
  "commander": "^13.1.0",
37
- "local-sync-protocol": "workspace:*",
38
37
  "mime-types": "^2.1.35",
39
38
  "ws": "^8.18.0"
40
39
  },
@@ -44,6 +43,7 @@
44
43
  "@types/mime-types": "^2.1.4",
45
44
  "@types/node": "^22.18.6",
46
45
  "@types/ws": "^8.5.13",
46
+ "local-sync-protocol": "workspace:^",
47
47
  "typescript": "^5.9.2"
48
48
  }
49
49
  }