@cetapod/react-native-smb 1.0.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.
Files changed (137) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +72 -0
  3. package/ReactNativeSmb.podspec +59 -0
  4. package/cpp/ios/OnLoad.mm +24 -0
  5. package/cpp/shared/HybridSMB.cpp +324 -0
  6. package/cpp/shared/HybridSMB.hpp +102 -0
  7. package/cpp/shared/ReactNativeSmb.hpp +428 -0
  8. package/cpp/shared/connection/ContextRequest.hpp +27 -0
  9. package/cpp/shared/connection/ContextRequestQueue.cpp +85 -0
  10. package/cpp/shared/connection/ContextRequestQueue.hpp +28 -0
  11. package/cpp/shared/connection/MetadataContextLease.hpp +33 -0
  12. package/cpp/shared/connection/PoolContextHandle.cpp +35 -0
  13. package/cpp/shared/connection/PoolContextHandle.hpp +44 -0
  14. package/cpp/shared/connection/PoolSlot.cpp +73 -0
  15. package/cpp/shared/connection/PoolSlot.hpp +46 -0
  16. package/cpp/shared/connection/PoolTypes.hpp +41 -0
  17. package/cpp/shared/connection/SmbConnection.cpp +385 -0
  18. package/cpp/shared/connection/SmbConnection.hpp +93 -0
  19. package/cpp/shared/connection/SmbConnectionPool.cpp +316 -0
  20. package/cpp/shared/connection/SmbConnectionPool.hpp +84 -0
  21. package/cpp/shared/core/CancellationToken.hpp +22 -0
  22. package/cpp/shared/core/OperatorContext.hpp +24 -0
  23. package/cpp/shared/core/SmbEnums.hpp +126 -0
  24. package/cpp/shared/core/SmbTask.cpp +131 -0
  25. package/cpp/shared/core/SmbTask.hpp +52 -0
  26. package/cpp/shared/core/SmbTaskCore.cpp +222 -0
  27. package/cpp/shared/core/SmbTaskCore.hpp +107 -0
  28. package/cpp/shared/core/SmbTypes.hpp +35 -0
  29. package/cpp/shared/core/TaskObserverHub.cpp +166 -0
  30. package/cpp/shared/core/TaskObserverHub.hpp +66 -0
  31. package/cpp/shared/core/TaskSnapshotCodec.cpp +32 -0
  32. package/cpp/shared/core/TaskSnapshotCodec.hpp +41 -0
  33. package/cpp/shared/io/SmbCopyTree.hpp +114 -0
  34. package/cpp/shared/io/SmbDirScan.hpp +80 -0
  35. package/cpp/shared/io/SmbFileIO.cpp +1355 -0
  36. package/cpp/shared/io/SmbFileIO.hpp +45 -0
  37. package/cpp/shared/io/SmbPathUtil.hpp +75 -0
  38. package/cpp/shared/io/SmbSecurity.cpp +308 -0
  39. package/cpp/shared/io/SmbSecurity.hpp +32 -0
  40. package/cpp/shared/io/SmbTreeOps.hpp +112 -0
  41. package/cpp/shared/operators/Operator.hpp +35 -0
  42. package/cpp/shared/operators/OperatorBase.cpp +57 -0
  43. package/cpp/shared/operators/OperatorBase.hpp +57 -0
  44. package/cpp/shared/operators/connection/ConnectOperator.cpp +19 -0
  45. package/cpp/shared/operators/connection/ConnectOperator.hpp +22 -0
  46. package/cpp/shared/operators/connection/ConnectShareOperator.cpp +19 -0
  47. package/cpp/shared/operators/connection/ConnectShareOperator.hpp +21 -0
  48. package/cpp/shared/operators/connection/DisconnectOperator.cpp +12 -0
  49. package/cpp/shared/operators/connection/DisconnectOperator.hpp +15 -0
  50. package/cpp/shared/operators/connection/InitializeOperator.cpp +12 -0
  51. package/cpp/shared/operators/connection/InitializeOperator.hpp +22 -0
  52. package/cpp/shared/operators/connection/ListSharesOperator.cpp +13 -0
  53. package/cpp/shared/operators/connection/ListSharesOperator.hpp +18 -0
  54. package/cpp/shared/operators/listing/GetPathInfoOperator.cpp +43 -0
  55. package/cpp/shared/operators/listing/GetPathInfoOperator.hpp +21 -0
  56. package/cpp/shared/operators/listing/GetSecurityDescriptorOperator.cpp +202 -0
  57. package/cpp/shared/operators/listing/GetSecurityDescriptorOperator.hpp +22 -0
  58. package/cpp/shared/operators/listing/ListDirectoryOperator.cpp +20 -0
  59. package/cpp/shared/operators/listing/ListDirectoryOperator.hpp +24 -0
  60. package/cpp/shared/operators/mutate/CopyItemOperator.cpp +19 -0
  61. package/cpp/shared/operators/mutate/CopyItemOperator.hpp +25 -0
  62. package/cpp/shared/operators/mutate/CreateDirectoryOperator.cpp +28 -0
  63. package/cpp/shared/operators/mutate/CreateDirectoryOperator.hpp +20 -0
  64. package/cpp/shared/operators/mutate/DeleteItemOperator.cpp +96 -0
  65. package/cpp/shared/operators/mutate/DeleteItemOperator.hpp +23 -0
  66. package/cpp/shared/operators/mutate/DuplicateItemOperator.cpp +48 -0
  67. package/cpp/shared/operators/mutate/DuplicateItemOperator.hpp +23 -0
  68. package/cpp/shared/operators/mutate/MoveItemOperator.cpp +32 -0
  69. package/cpp/shared/operators/mutate/MoveItemOperator.hpp +21 -0
  70. package/cpp/shared/operators/mutate/RenameItemOperator.cpp +37 -0
  71. package/cpp/shared/operators/mutate/RenameItemOperator.hpp +21 -0
  72. package/cpp/shared/operators/transfer/DownloadFileOperator.cpp +31 -0
  73. package/cpp/shared/operators/transfer/DownloadFileOperator.hpp +21 -0
  74. package/cpp/shared/operators/transfer/UploadFileOperator.cpp +27 -0
  75. package/cpp/shared/operators/transfer/UploadFileOperator.hpp +21 -0
  76. package/cpp/shared/util/SmbErrorMapper.hpp +229 -0
  77. package/cpp/shared/util/SmbLog.hpp +20 -0
  78. package/docs/API.md +105 -0
  79. package/docs/ARCHITECTURE.md +70 -0
  80. package/docs/TASK_MODEL.md +149 -0
  81. package/ios/include/smb2/libsmb2-dcerpc-lsa.h +172 -0
  82. package/ios/include/smb2/libsmb2-dcerpc-srvsvc.h +180 -0
  83. package/ios/include/smb2/libsmb2-dcerpc.h +155 -0
  84. package/ios/include/smb2/libsmb2-raw.h +497 -0
  85. package/ios/include/smb2/libsmb2.h +1384 -0
  86. package/ios/include/smb2/smb2-errors.h +549 -0
  87. package/ios/include/smb2/smb2.h +1251 -0
  88. package/ios/libs/device/libsmb2-device.a +0 -0
  89. package/ios/libs/libsmb2.xcframework/Info.plist +48 -0
  90. package/ios/libs/libsmb2.xcframework/ios-arm64/Headers/smb2/libsmb2-dcerpc-lsa.h +172 -0
  91. package/ios/libs/libsmb2.xcframework/ios-arm64/Headers/smb2/libsmb2-dcerpc-srvsvc.h +180 -0
  92. package/ios/libs/libsmb2.xcframework/ios-arm64/Headers/smb2/libsmb2-dcerpc.h +155 -0
  93. package/ios/libs/libsmb2.xcframework/ios-arm64/Headers/smb2/libsmb2-raw.h +497 -0
  94. package/ios/libs/libsmb2.xcframework/ios-arm64/Headers/smb2/libsmb2.h +1384 -0
  95. package/ios/libs/libsmb2.xcframework/ios-arm64/Headers/smb2/smb2-errors.h +549 -0
  96. package/ios/libs/libsmb2.xcframework/ios-arm64/Headers/smb2/smb2.h +1251 -0
  97. package/ios/libs/libsmb2.xcframework/ios-arm64/libsmb2.a +0 -0
  98. package/ios/libs/libsmb2.xcframework/ios-arm64_x86_64-simulator/Headers/smb2/libsmb2-dcerpc-lsa.h +172 -0
  99. package/ios/libs/libsmb2.xcframework/ios-arm64_x86_64-simulator/Headers/smb2/libsmb2-dcerpc-srvsvc.h +180 -0
  100. package/ios/libs/libsmb2.xcframework/ios-arm64_x86_64-simulator/Headers/smb2/libsmb2-dcerpc.h +155 -0
  101. package/ios/libs/libsmb2.xcframework/ios-arm64_x86_64-simulator/Headers/smb2/libsmb2-raw.h +497 -0
  102. package/ios/libs/libsmb2.xcframework/ios-arm64_x86_64-simulator/Headers/smb2/libsmb2.h +1384 -0
  103. package/ios/libs/libsmb2.xcframework/ios-arm64_x86_64-simulator/Headers/smb2/smb2-errors.h +549 -0
  104. package/ios/libs/libsmb2.xcframework/ios-arm64_x86_64-simulator/Headers/smb2/smb2.h +1251 -0
  105. package/ios/libs/libsmb2.xcframework/ios-arm64_x86_64-simulator/libsmb2.a +0 -0
  106. package/ios/libs/simulator/libsmb2-simulator.a +0 -0
  107. package/lib/ReactNativeSmb.d.ts +200 -0
  108. package/lib/ReactNativeSmb.js +1 -0
  109. package/lib/bridge/decode.d.ts +4 -0
  110. package/lib/bridge/decode.js +92 -0
  111. package/lib/core/SMB.d.ts +3 -0
  112. package/lib/core/SMB.js +4 -0
  113. package/lib/core/SmbClient.d.ts +35 -0
  114. package/lib/core/SmbClient.js +99 -0
  115. package/lib/core/SmbTask.d.ts +41 -0
  116. package/lib/core/SmbTask.js +74 -0
  117. package/lib/core/TransferStore.d.ts +22 -0
  118. package/lib/core/TransferStore.js +88 -0
  119. package/lib/core/ids.d.ts +1 -0
  120. package/lib/core/ids.js +3 -0
  121. package/lib/core/taskResult.d.ts +3 -0
  122. package/lib/core/taskResult.js +52 -0
  123. package/lib/hooks/useSubscribe.d.ts +20 -0
  124. package/lib/hooks/useSubscribe.js +36 -0
  125. package/lib/hooks/useTransfers.d.ts +7 -0
  126. package/lib/hooks/useTransfers.js +29 -0
  127. package/lib/index.d.ts +7 -0
  128. package/lib/index.js +7 -0
  129. package/lib/labels.d.ts +6 -0
  130. package/lib/labels.js +71 -0
  131. package/lib/types.d.ts +141 -0
  132. package/lib/types.js +59 -0
  133. package/lib/utils.d.ts +79 -0
  134. package/lib/utils.js +153 -0
  135. package/package.json +63 -0
  136. package/scripts/build-libsmb2.sh +143 -0
  137. package/scripts/create-xcframework.sh +84 -0
@@ -0,0 +1,3 @@
1
+ import type { SmbTask } from './SmbTask';
2
+ /** Subscribe once, resolve or reject when the task reaches a terminal status. */
3
+ export declare function taskResult<T>(task: SmbTask<T>): Promise<T>;
@@ -0,0 +1,52 @@
1
+ import { terminalStatus } from '../bridge/decode';
2
+ import { SmbError, SmbTaskError, TaskStatus } from '../types';
3
+ function errorForStatus(status, raw, taskId) {
4
+ const code = parseInt(raw.errorCode ?? '0', 10);
5
+ const message = raw.errorMessage || (status === TaskStatus.Cancelled ? 'Task cancelled' : 'Task failed');
6
+ return new SmbTaskError(message, Number.isFinite(code) ? code : SmbError.Unknown, taskId);
7
+ }
8
+ /** Subscribe once, resolve or reject when the task reaches a terminal status. */
9
+ export function taskResult(task) {
10
+ return new Promise((resolve, reject) => {
11
+ let settled = false;
12
+ const finish = (status, raw) => {
13
+ if (settled)
14
+ return;
15
+ settled = true;
16
+ if (status === TaskStatus.Success) {
17
+ try {
18
+ resolve(task.getResultValue());
19
+ }
20
+ catch (e) {
21
+ reject(e);
22
+ }
23
+ }
24
+ else {
25
+ reject(errorForStatus(status, raw, task.id));
26
+ }
27
+ };
28
+ const unsub = task.subscribe((snap) => {
29
+ if (snap.status === TaskStatus.Success ||
30
+ snap.status === TaskStatus.Error ||
31
+ snap.status === TaskStatus.Cancelled) {
32
+ finish(snap.status, {
33
+ errorCode: String(snap.errorCode),
34
+ errorMessage: snap.errorMessage,
35
+ });
36
+ unsub();
37
+ }
38
+ });
39
+ try {
40
+ const raw = task.getRaw();
41
+ const status = terminalStatus(raw);
42
+ if (status !== null) {
43
+ finish(status, raw);
44
+ unsub();
45
+ }
46
+ }
47
+ catch (e) {
48
+ unsub();
49
+ reject(e);
50
+ }
51
+ });
52
+ }
@@ -0,0 +1,20 @@
1
+ import type { SmbTask } from '../core/SmbTask';
2
+ import { TaskStatus, type SmbTaskState } from '../types';
3
+ export interface SubscribeHandle<T = void> {
4
+ /** Start live updates. Returns unsubscribe. */
5
+ subscribe: (listener?: (snapshot: SmbTaskState) => void) => () => void;
6
+ cancel: () => void;
7
+ progress: number;
8
+ status: TaskStatus;
9
+ snapshot: SmbTaskState | null;
10
+ task: SmbTask<T> | null;
11
+ }
12
+ /**
13
+ * React binding for {@link SmbTask.subscribe}. Subscribes automatically on mount
14
+ * and whenever `task` changes; unsubscribes on unmount / task change.
15
+ *
16
+ * @example
17
+ * const task = smb.downloadFile(remote, local);
18
+ * const { progress, status, cancel } = useSubscribe(task);
19
+ */
20
+ export declare function useSubscribe<T>(task: SmbTask<T> | null | undefined): SubscribeHandle<T>;
@@ -0,0 +1,36 @@
1
+ import { useCallback, useEffect, useState } from 'react';
2
+ import { TaskStatus } from '../types';
3
+ /**
4
+ * React binding for {@link SmbTask.subscribe}. Subscribes automatically on mount
5
+ * and whenever `task` changes; unsubscribes on unmount / task change.
6
+ *
7
+ * @example
8
+ * const task = smb.downloadFile(remote, local);
9
+ * const { progress, status, cancel } = useSubscribe(task);
10
+ */
11
+ export function useSubscribe(task) {
12
+ const [snapshot, setSnapshot] = useState(() => task?.get() ?? null);
13
+ const subscribe = useCallback((listener) => {
14
+ if (!task)
15
+ return () => { };
16
+ return task.subscribe((snap) => {
17
+ setSnapshot(snap);
18
+ listener?.(snap);
19
+ });
20
+ }, [task]);
21
+ useEffect(() => {
22
+ setSnapshot(task?.get() ?? null);
23
+ return subscribe();
24
+ }, [task, subscribe]);
25
+ const cancel = useCallback(() => {
26
+ task?.cancel();
27
+ }, [task]);
28
+ return {
29
+ subscribe,
30
+ cancel,
31
+ progress: snapshot?.progress ?? task?.progress ?? 0,
32
+ status: snapshot?.status ?? task?.status ?? TaskStatus.Pending,
33
+ snapshot,
34
+ task: task ?? null,
35
+ };
36
+ }
@@ -0,0 +1,7 @@
1
+ import type { Smb } from '../core/SMB';
2
+ import type { SmbTaskState } from '../types';
3
+ export declare function useTransfers(smb: Smb | null): SmbTaskState[];
4
+ export declare function useTransferActions(smb: Smb | null): {
5
+ clearCompleted: () => void | undefined;
6
+ hide: (taskId: string) => void | undefined;
7
+ };
@@ -0,0 +1,29 @@
1
+ import { useEffect, useMemo, useState } from 'react';
2
+ const EMPTY_TASKS = [];
3
+ function store(smb) {
4
+ return smb.transferStore();
5
+ }
6
+ export function useTransfers(smb) {
7
+ const [tasks, setTasks] = useState(EMPTY_TASKS);
8
+ useEffect(() => {
9
+ if (!smb) {
10
+ setTasks(EMPTY_TASKS);
11
+ return undefined;
12
+ }
13
+ const transferStore = store(smb);
14
+ const onStoreChange = () => {
15
+ setTasks(transferStore.getSnapshot());
16
+ };
17
+ const unsubscribe = transferStore.subscribe(onStoreChange);
18
+ onStoreChange();
19
+ return unsubscribe;
20
+ }, [smb]);
21
+ return smb ? tasks : EMPTY_TASKS;
22
+ }
23
+ export function useTransferActions(smb) {
24
+ const s = smb ? store(smb) : null;
25
+ return useMemo(() => ({
26
+ clearCompleted: () => s?.clearCompleted(),
27
+ hide: (taskId) => s?.hide(taskId),
28
+ }), [s]);
29
+ }
package/lib/index.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ export * from './types';
2
+ export * from './utils';
3
+ export { SMB, type Smb } from './core/SMB';
4
+ export { SmbTask } from './core/SmbTask';
5
+ export { useSubscribe, type SubscribeHandle } from './hooks/useSubscribe';
6
+ export { useTransfers, useTransferActions } from './hooks/useTransfers';
7
+ export { statusLabel, operationLabel, isTransferKind, isDeterminateKind, isTerminalStatus, } from './labels';
package/lib/index.js ADDED
@@ -0,0 +1,7 @@
1
+ export * from './types';
2
+ export * from './utils';
3
+ export { SMB } from './core/SMB';
4
+ export { SmbTask } from './core/SmbTask';
5
+ export { useSubscribe } from './hooks/useSubscribe';
6
+ export { useTransfers, useTransferActions } from './hooks/useTransfers';
7
+ export { statusLabel, operationLabel, isTransferKind, isDeterminateKind, isTerminalStatus, } from './labels';
@@ -0,0 +1,6 @@
1
+ import { SmbOperatorKind, TaskStatus } from './types';
2
+ export declare function statusLabel(status: TaskStatus): string;
3
+ export declare function operationLabel(kind: SmbOperatorKind): string;
4
+ export declare function isTransferKind(kind: SmbOperatorKind): boolean;
5
+ export declare function isDeterminateKind(kind: SmbOperatorKind): boolean;
6
+ export declare function isTerminalStatus(status: TaskStatus): boolean;
package/lib/labels.js ADDED
@@ -0,0 +1,71 @@
1
+ import { SmbOperatorKind, TaskStatus } from './types';
2
+ export function statusLabel(status) {
3
+ switch (status) {
4
+ case TaskStatus.Idle:
5
+ return 'idle';
6
+ case TaskStatus.Pending:
7
+ return 'pending';
8
+ case TaskStatus.Running:
9
+ return 'running';
10
+ case TaskStatus.Success:
11
+ return 'success';
12
+ case TaskStatus.Error:
13
+ return 'error';
14
+ case TaskStatus.Cancelled:
15
+ return 'cancelled';
16
+ default:
17
+ return 'unknown';
18
+ }
19
+ }
20
+ export function operationLabel(kind) {
21
+ switch (kind) {
22
+ case SmbOperatorKind.Initialize:
23
+ return 'Initialize';
24
+ case SmbOperatorKind.Connect:
25
+ return 'Connect';
26
+ case SmbOperatorKind.ConnectShare:
27
+ return 'Connect share';
28
+ case SmbOperatorKind.Disconnect:
29
+ return 'Disconnect';
30
+ case SmbOperatorKind.ListShares:
31
+ return 'List shares';
32
+ case SmbOperatorKind.ListDirectory:
33
+ return 'List directory';
34
+ case SmbOperatorKind.GetPathInfo:
35
+ return 'Get info';
36
+ case SmbOperatorKind.GetSecurityDescriptor:
37
+ return 'Get ACL';
38
+ case SmbOperatorKind.DownloadFile:
39
+ return 'Download';
40
+ case SmbOperatorKind.UploadFile:
41
+ return 'Upload';
42
+ case SmbOperatorKind.CreateDirectory:
43
+ return 'Create folder';
44
+ case SmbOperatorKind.DeleteItem:
45
+ return 'Delete';
46
+ case SmbOperatorKind.MoveItem:
47
+ return 'Move';
48
+ case SmbOperatorKind.RenameItem:
49
+ return 'Rename';
50
+ case SmbOperatorKind.CopyItem:
51
+ return 'Copy';
52
+ case SmbOperatorKind.DuplicateItem:
53
+ return 'Duplicate';
54
+ default:
55
+ return 'Unknown';
56
+ }
57
+ }
58
+ export function isTransferKind(kind) {
59
+ return (kind === SmbOperatorKind.DownloadFile ||
60
+ kind === SmbOperatorKind.UploadFile ||
61
+ kind === SmbOperatorKind.CopyItem ||
62
+ kind === SmbOperatorKind.DuplicateItem);
63
+ }
64
+ export function isDeterminateKind(kind) {
65
+ return isTransferKind(kind);
66
+ }
67
+ export function isTerminalStatus(status) {
68
+ return (status === TaskStatus.Success ||
69
+ status === TaskStatus.Error ||
70
+ status === TaskStatus.Cancelled);
71
+ }
package/lib/types.d.ts ADDED
@@ -0,0 +1,141 @@
1
+ export interface SmbCredentials {
2
+ readonly username: string;
3
+ readonly password: string;
4
+ }
5
+ export interface SmbShareList {
6
+ readonly name: string;
7
+ readonly comment: string;
8
+ }
9
+ export interface SmbConnectionInfo {
10
+ readonly url: string;
11
+ readonly server: string;
12
+ readonly share: string;
13
+ readonly isConnected: boolean;
14
+ }
15
+ export declare enum SmbError {
16
+ Unknown = 0,
17
+ Cancelled = 1,
18
+ InvalidArgument = 100,
19
+ NotFound = 101,
20
+ AlreadyExists = 102,
21
+ AccessDenied = 103,
22
+ NotDirectory = 104,
23
+ IsDirectory = 105,
24
+ DirectoryNotEmpty = 106,
25
+ NotConnected = 200,
26
+ ConnectionRefused = 201,
27
+ TimedOut = 202,
28
+ Busy = 300,
29
+ NoSpace = 301,
30
+ Io = 302
31
+ }
32
+ export declare class SmbTaskError extends Error {
33
+ readonly code: SmbError;
34
+ readonly taskId?: string;
35
+ constructor(message: string, code?: SmbError, taskId?: string);
36
+ }
37
+ export interface SmbFileInfo {
38
+ readonly name: string;
39
+ readonly path: string;
40
+ readonly size: number;
41
+ readonly isDirectory: boolean;
42
+ readonly modifiedAt: number;
43
+ readonly accessedAt: number;
44
+ readonly createdAt: number;
45
+ readonly changedAt: number;
46
+ readonly childCount?: number;
47
+ readonly children?: SmbFileInfo[];
48
+ }
49
+ export interface SmbAce {
50
+ readonly aceType: string;
51
+ readonly aceFlags: string[];
52
+ readonly mask: string[];
53
+ readonly sid: string;
54
+ }
55
+ export interface SmbAcl {
56
+ readonly revision: number;
57
+ readonly aceCount: number;
58
+ readonly aces: SmbAce[];
59
+ }
60
+ export interface SmbSecurityDescriptor {
61
+ readonly revision: number;
62
+ readonly control: string[];
63
+ readonly ownerSid: string;
64
+ readonly groupSid: string;
65
+ readonly dacl: SmbAcl;
66
+ }
67
+ export interface PathComponents {
68
+ readonly parentDirectory: string;
69
+ readonly baseFileName: string;
70
+ readonly extension: string;
71
+ readonly fullFileName: string;
72
+ }
73
+ export declare enum TaskStatus {
74
+ Idle = 0,
75
+ Pending = 1,
76
+ Running = 2,
77
+ Success = 3,
78
+ Error = 4,
79
+ Cancelled = 5
80
+ }
81
+ export declare enum SmbOperatorKind {
82
+ Initialize = 0,
83
+ Connect = 1,
84
+ ConnectShare = 2,
85
+ Disconnect = 3,
86
+ ListShares = 4,
87
+ ListDirectory = 5,
88
+ GetPathInfo = 6,
89
+ GetSecurityDescriptor = 7,
90
+ DownloadFile = 8,
91
+ UploadFile = 9,
92
+ CreateDirectory = 10,
93
+ DeleteItem = 11,
94
+ MoveItem = 12,
95
+ RenameItem = 13,
96
+ CopyItem = 14,
97
+ DuplicateItem = 15
98
+ }
99
+ export declare enum SlotState {
100
+ Idle = 0,
101
+ Assigned = 1,
102
+ Activating = 2
103
+ }
104
+ export interface SmbTaskState {
105
+ readonly taskId: string;
106
+ readonly kind: SmbOperatorKind;
107
+ readonly status: TaskStatus;
108
+ readonly determinate: boolean;
109
+ readonly progress: number;
110
+ readonly bytesDone: number;
111
+ readonly totalBytes: number;
112
+ readonly bytesPerSecond: number;
113
+ readonly etaSeconds: number;
114
+ readonly sourcePath: string;
115
+ readonly destinationPath: string;
116
+ readonly errorCode: number;
117
+ readonly errorMessage: string;
118
+ readonly startedAt: number;
119
+ readonly updatedAt: number;
120
+ readonly endedAt: number;
121
+ }
122
+ export interface PoolSlotInfo {
123
+ readonly index: number;
124
+ readonly interactiveOnly: boolean;
125
+ readonly state: SlotState;
126
+ readonly isConnected: boolean;
127
+ readonly shareName: string;
128
+ readonly taskId: string;
129
+ readonly kind: SmbOperatorKind;
130
+ }
131
+ export interface PoolInfo {
132
+ readonly poolSize: number;
133
+ readonly slots: PoolSlotInfo[];
134
+ }
135
+ export interface NativeSmbTask {
136
+ cancel(): void;
137
+ get(): Record<string, string>;
138
+ subscribe(listener: (snapshot: Record<string, string>) => void): string;
139
+ unsubscribe(subscriptionId: string): void;
140
+ getResultValue(): unknown;
141
+ }
package/lib/types.js ADDED
@@ -0,0 +1,59 @@
1
+ export var SmbError;
2
+ (function (SmbError) {
3
+ SmbError[SmbError["Unknown"] = 0] = "Unknown";
4
+ SmbError[SmbError["Cancelled"] = 1] = "Cancelled";
5
+ SmbError[SmbError["InvalidArgument"] = 100] = "InvalidArgument";
6
+ SmbError[SmbError["NotFound"] = 101] = "NotFound";
7
+ SmbError[SmbError["AlreadyExists"] = 102] = "AlreadyExists";
8
+ SmbError[SmbError["AccessDenied"] = 103] = "AccessDenied";
9
+ SmbError[SmbError["NotDirectory"] = 104] = "NotDirectory";
10
+ SmbError[SmbError["IsDirectory"] = 105] = "IsDirectory";
11
+ SmbError[SmbError["DirectoryNotEmpty"] = 106] = "DirectoryNotEmpty";
12
+ SmbError[SmbError["NotConnected"] = 200] = "NotConnected";
13
+ SmbError[SmbError["ConnectionRefused"] = 201] = "ConnectionRefused";
14
+ SmbError[SmbError["TimedOut"] = 202] = "TimedOut";
15
+ SmbError[SmbError["Busy"] = 300] = "Busy";
16
+ SmbError[SmbError["NoSpace"] = 301] = "NoSpace";
17
+ SmbError[SmbError["Io"] = 302] = "Io";
18
+ })(SmbError || (SmbError = {}));
19
+ export class SmbTaskError extends Error {
20
+ constructor(message, code = SmbError.Unknown, taskId) {
21
+ super(message);
22
+ this.code = code;
23
+ this.taskId = taskId;
24
+ }
25
+ }
26
+ export var TaskStatus;
27
+ (function (TaskStatus) {
28
+ TaskStatus[TaskStatus["Idle"] = 0] = "Idle";
29
+ TaskStatus[TaskStatus["Pending"] = 1] = "Pending";
30
+ TaskStatus[TaskStatus["Running"] = 2] = "Running";
31
+ TaskStatus[TaskStatus["Success"] = 3] = "Success";
32
+ TaskStatus[TaskStatus["Error"] = 4] = "Error";
33
+ TaskStatus[TaskStatus["Cancelled"] = 5] = "Cancelled";
34
+ })(TaskStatus || (TaskStatus = {}));
35
+ export var SmbOperatorKind;
36
+ (function (SmbOperatorKind) {
37
+ SmbOperatorKind[SmbOperatorKind["Initialize"] = 0] = "Initialize";
38
+ SmbOperatorKind[SmbOperatorKind["Connect"] = 1] = "Connect";
39
+ SmbOperatorKind[SmbOperatorKind["ConnectShare"] = 2] = "ConnectShare";
40
+ SmbOperatorKind[SmbOperatorKind["Disconnect"] = 3] = "Disconnect";
41
+ SmbOperatorKind[SmbOperatorKind["ListShares"] = 4] = "ListShares";
42
+ SmbOperatorKind[SmbOperatorKind["ListDirectory"] = 5] = "ListDirectory";
43
+ SmbOperatorKind[SmbOperatorKind["GetPathInfo"] = 6] = "GetPathInfo";
44
+ SmbOperatorKind[SmbOperatorKind["GetSecurityDescriptor"] = 7] = "GetSecurityDescriptor";
45
+ SmbOperatorKind[SmbOperatorKind["DownloadFile"] = 8] = "DownloadFile";
46
+ SmbOperatorKind[SmbOperatorKind["UploadFile"] = 9] = "UploadFile";
47
+ SmbOperatorKind[SmbOperatorKind["CreateDirectory"] = 10] = "CreateDirectory";
48
+ SmbOperatorKind[SmbOperatorKind["DeleteItem"] = 11] = "DeleteItem";
49
+ SmbOperatorKind[SmbOperatorKind["MoveItem"] = 12] = "MoveItem";
50
+ SmbOperatorKind[SmbOperatorKind["RenameItem"] = 13] = "RenameItem";
51
+ SmbOperatorKind[SmbOperatorKind["CopyItem"] = 14] = "CopyItem";
52
+ SmbOperatorKind[SmbOperatorKind["DuplicateItem"] = 15] = "DuplicateItem";
53
+ })(SmbOperatorKind || (SmbOperatorKind = {}));
54
+ export var SlotState;
55
+ (function (SlotState) {
56
+ SlotState[SlotState["Idle"] = 0] = "Idle";
57
+ SlotState[SlotState["Assigned"] = 1] = "Assigned";
58
+ SlotState[SlotState["Activating"] = 2] = "Activating";
59
+ })(SlotState || (SlotState = {}));
package/lib/utils.d.ts ADDED
@@ -0,0 +1,79 @@
1
+ import type { PathComponents } from './types';
2
+ /**
3
+ * Normalize a path to use forward slashes and remove trailing slashes
4
+ * @param path - The path to normalize
5
+ * @returns The normalized path
6
+ */
7
+ export declare function normalizePath(path: string): string;
8
+ /**
9
+ * Split a file path into its components
10
+ * @param path - The full path to split
11
+ * @returns PathComponents containing parent directory, base filename, extension, and full filename
12
+ *
13
+ * @example
14
+ * splitPath('/folder/document.pdf')
15
+ * // Returns:
16
+ * // {
17
+ * // parentDirectory: '/folder',
18
+ * // baseFileName: 'document',
19
+ * // extension: '.pdf',
20
+ * // fullFileName: 'document.pdf'
21
+ * // }
22
+ */
23
+ export declare function splitPath(path: string): PathComponents;
24
+ /**
25
+ * Join path components into a full path
26
+ * @param directory - The directory path
27
+ * @param filename - The filename to append
28
+ * @returns The combined path
29
+ *
30
+ * @example
31
+ * joinPath('/folder', 'file.txt') // '/folder/file.txt'
32
+ * joinPath('/', 'file.txt') // '/file.txt'
33
+ */
34
+ export declare function joinPath(directory: string, filename: string): string;
35
+ /**
36
+ * Generate a unique copy name for duplicating files/folders
37
+ * Creates names in the format: "name copy.ext", "name copy 2.ext", etc.
38
+ *
39
+ * @param baseName - The base filename without extension
40
+ * @param extension - The file extension (including the dot)
41
+ * @param existingNames - Array of existing filenames to check against
42
+ * @returns The new unique name
43
+ *
44
+ * @example
45
+ * generateCopyName('document', '.pdf', ['document.pdf', 'document copy.pdf'])
46
+ * // Returns: 'document copy 2.pdf'
47
+ */
48
+ export declare function generateCopyName(baseName: string, extension: string, existingNames: string[]): string;
49
+ /**
50
+ * Get the parent directory of a path
51
+ * @param path - The path to get parent from
52
+ * @returns The parent directory path
53
+ *
54
+ * @example
55
+ * getParentPath('/folder/subfolder/file.txt') // '/folder/subfolder'
56
+ * getParentPath('/file.txt') // '/'
57
+ */
58
+ export declare function getParentPath(path: string): string;
59
+ /**
60
+ * Get just the filename from a full path
61
+ * @param path - The full path
62
+ * @returns The filename
63
+ *
64
+ * @example
65
+ * getFileName('/folder/document.pdf') // 'document.pdf'
66
+ */
67
+ export declare function getFileName(path: string): string;
68
+ /**
69
+ * Format file size in human-readable format
70
+ * @param bytes - Size in bytes
71
+ * @returns Formatted string (e.g., "1.5 MB")
72
+ */
73
+ export declare function formatFileSize(bytes: number): string;
74
+ /**
75
+ * Format a timestamp to a readable date string
76
+ * @param timestamp - Unix timestamp in seconds
77
+ * @returns Formatted date string
78
+ */
79
+ export declare function formatDate(timestamp: number): string;
package/lib/utils.js ADDED
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Normalize a path to use forward slashes and remove trailing slashes
3
+ * @param path - The path to normalize
4
+ * @returns The normalized path
5
+ */
6
+ export function normalizePath(path) {
7
+ const normalized = path.replace(/\\/g, '/');
8
+ return normalized === '/' ? normalized : normalized.replace(/\/+$/, '');
9
+ }
10
+ /**
11
+ * Split a file path into its components
12
+ * @param path - The full path to split
13
+ * @returns PathComponents containing parent directory, base filename, extension, and full filename
14
+ *
15
+ * @example
16
+ * splitPath('/folder/document.pdf')
17
+ * // Returns:
18
+ * // {
19
+ * // parentDirectory: '/folder',
20
+ * // baseFileName: 'document',
21
+ * // extension: '.pdf',
22
+ * // fullFileName: 'document.pdf'
23
+ * // }
24
+ */
25
+ export function splitPath(path) {
26
+ const normalizedPath = normalizePath(path);
27
+ const lastSlashIndex = normalizedPath.lastIndexOf('/');
28
+ const parentDirectory = lastSlashIndex >= 0
29
+ ? normalizedPath.substring(0, lastSlashIndex) || '/'
30
+ : '/';
31
+ const fullFileName = lastSlashIndex >= 0
32
+ ? normalizedPath.substring(lastSlashIndex + 1)
33
+ : normalizedPath;
34
+ const lastDotIndex = fullFileName.lastIndexOf('.');
35
+ const hasExtension = lastDotIndex > 0;
36
+ const baseFileName = hasExtension
37
+ ? fullFileName.substring(0, lastDotIndex)
38
+ : fullFileName;
39
+ const extension = hasExtension
40
+ ? fullFileName.substring(lastDotIndex)
41
+ : '';
42
+ return {
43
+ parentDirectory,
44
+ baseFileName,
45
+ extension,
46
+ fullFileName,
47
+ };
48
+ }
49
+ /**
50
+ * Join path components into a full path
51
+ * @param directory - The directory path
52
+ * @param filename - The filename to append
53
+ * @returns The combined path
54
+ *
55
+ * @example
56
+ * joinPath('/folder', 'file.txt') // '/folder/file.txt'
57
+ * joinPath('/', 'file.txt') // '/file.txt'
58
+ */
59
+ export function joinPath(directory, filename) {
60
+ if (directory === '/') {
61
+ return `/${filename}`;
62
+ }
63
+ return directory.endsWith('/')
64
+ ? `${directory}${filename}`
65
+ : `${directory}/${filename}`;
66
+ }
67
+ /**
68
+ * Generate a unique copy name for duplicating files/folders
69
+ * Creates names in the format: "name copy.ext", "name copy 2.ext", etc.
70
+ *
71
+ * @param baseName - The base filename without extension
72
+ * @param extension - The file extension (including the dot)
73
+ * @param existingNames - Array of existing filenames to check against
74
+ * @returns The new unique name
75
+ *
76
+ * @example
77
+ * generateCopyName('document', '.pdf', ['document.pdf', 'document copy.pdf'])
78
+ * // Returns: 'document copy 2.pdf'
79
+ */
80
+ export function generateCopyName(baseName, extension, existingNames) {
81
+ const copyPattern = /^(.+?)( copy)( \d+)?$/;
82
+ const match = baseName.match(copyPattern);
83
+ const rootName = baseName.replace(/ copy( \d+)?$/, '');
84
+ const copyNumbers = [];
85
+ existingNames.forEach((name) => {
86
+ const { baseFileName } = splitPath(name);
87
+ const _match = baseFileName.match(copyPattern);
88
+ if (!_match || rootName !== _match[1]) {
89
+ return;
90
+ }
91
+ if (!_match[3]) {
92
+ copyNumbers.push(1);
93
+ }
94
+ else {
95
+ copyNumbers.push(parseInt(_match[3].trim(), 10));
96
+ }
97
+ });
98
+ let nextNumber = match ? parseInt(match[3]?.trim() || '1', 10) + 1 : 1;
99
+ while (copyNumbers.includes(nextNumber)) {
100
+ nextNumber++;
101
+ }
102
+ const copySuffix = nextNumber === 1 ? 'copy' : `copy ${nextNumber}`;
103
+ return `${rootName} ${copySuffix}${extension}`;
104
+ }
105
+ /**
106
+ * Get the parent directory of a path
107
+ * @param path - The path to get parent from
108
+ * @returns The parent directory path
109
+ *
110
+ * @example
111
+ * getParentPath('/folder/subfolder/file.txt') // '/folder/subfolder'
112
+ * getParentPath('/file.txt') // '/'
113
+ */
114
+ export function getParentPath(path) {
115
+ const { parentDirectory } = splitPath(path);
116
+ return parentDirectory;
117
+ }
118
+ /**
119
+ * Get just the filename from a full path
120
+ * @param path - The full path
121
+ * @returns The filename
122
+ *
123
+ * @example
124
+ * getFileName('/folder/document.pdf') // 'document.pdf'
125
+ */
126
+ export function getFileName(path) {
127
+ const { fullFileName } = splitPath(path);
128
+ return fullFileName;
129
+ }
130
+ /**
131
+ * Format file size in human-readable format
132
+ * @param bytes - Size in bytes
133
+ * @returns Formatted string (e.g., "1.5 MB")
134
+ */
135
+ export function formatFileSize(bytes) {
136
+ if (bytes === 0)
137
+ return '0 Bytes';
138
+ const k = 1024;
139
+ const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
140
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
141
+ return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
142
+ }
143
+ /**
144
+ * Format a timestamp to a readable date string
145
+ * @param timestamp - Unix timestamp in seconds
146
+ * @returns Formatted date string
147
+ */
148
+ export function formatDate(timestamp) {
149
+ if (!timestamp)
150
+ return 'N/A';
151
+ const date = new Date(timestamp * 1000);
152
+ return `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`;
153
+ }