aspera-cli 4.26.1 → 4.27.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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +300 -22
- data/CONTRIBUTING.md +100 -12
- data/bin/ascli +5 -5
- data/docs/README.md +10757 -0
- data/docs/test-mcp-with-ai.md +202 -0
- data/lib/aspera/agent/base.rb +20 -6
- data/lib/aspera/agent/connect.rb +53 -16
- data/lib/aspera/agent/desktop.rb +52 -17
- data/lib/aspera/agent/direct.rb +27 -25
- data/lib/aspera/agent/factory.rb +4 -0
- data/lib/aspera/agent/httpgw.rb +2 -2
- data/lib/aspera/agent/node.rb +34 -2
- data/lib/aspera/agent/transferd.rb +39 -3
- data/lib/aspera/api/alee.rb +1 -1
- data/lib/aspera/api/aoc.rb +56 -51
- data/lib/aspera/api/cos_node.rb +2 -2
- data/lib/aspera/api/faspex.rb +22 -20
- data/lib/aspera/api/httpgw.rb +4 -4
- data/lib/aspera/api/node.rb +33 -30
- data/lib/aspera/api/queries/bss_subscription_account.graphql +18 -0
- data/lib/aspera/api/queries/bss_subscription_usage.graphql +18 -0
- data/lib/aspera/ascmd.rb +25 -23
- data/lib/aspera/ascp/installation.rb +43 -40
- data/lib/aspera/ascp/management.rb +2 -3
- data/lib/aspera/cli/ascp_actions.rb +155 -0
- data/lib/aspera/cli/async_transfer_store.rb +81 -0
- data/lib/aspera/cli/bootstrapper.rb +197 -0
- data/lib/aspera/cli/command_registry.rb +145 -0
- data/lib/aspera/cli/command_spec.rb +138 -0
- data/lib/aspera/cli/context.rb +71 -0
- data/lib/aspera/cli/error.rb +16 -0
- data/lib/aspera/cli/extended_value.rb +5 -3
- data/lib/aspera/cli/formatter.rb +122 -209
- data/lib/aspera/cli/gem_checker.rb +65 -0
- data/lib/aspera/cli/hints.rb +2 -2
- data/lib/aspera/cli/http.rb +218 -0
- data/lib/aspera/cli/info.rb +2 -0
- data/lib/aspera/cli/mailer.rb +97 -0
- data/lib/aspera/cli/mcp_tool.rb +198 -0
- data/lib/aspera/cli/options.schema.yaml +364 -7
- data/lib/aspera/cli/{manager.rb → parser.rb} +337 -144
- data/lib/aspera/cli/plugins/alee.rb +20 -22
- data/lib/aspera/cli/plugins/aoc.rb +1173 -849
- data/lib/aspera/cli/plugins/ats.rb +200 -161
- data/lib/aspera/cli/plugins/base.rb +470 -107
- data/lib/aspera/cli/plugins/basic_auth.rb +14 -4
- data/lib/aspera/cli/plugins/config.rb +434 -1032
- data/lib/aspera/cli/plugins/console.rb +106 -64
- data/lib/aspera/cli/plugins/cos.rb +44 -32
- data/lib/aspera/cli/plugins/factory.rb +7 -4
- data/lib/aspera/cli/plugins/faspex.rb +296 -259
- data/lib/aspera/cli/plugins/faspex5.rb +592 -344
- data/lib/aspera/cli/plugins/faspio.rb +49 -51
- data/lib/aspera/cli/plugins/httpgw.rb +18 -25
- data/lib/aspera/cli/plugins/mcp.rb +279 -0
- data/lib/aspera/cli/plugins/node.rb +1001 -797
- data/lib/aspera/cli/plugins/oauth.rb +7 -10
- data/lib/aspera/cli/plugins/orchestrator.rb +111 -139
- data/lib/aspera/cli/plugins/preview.rb +183 -142
- data/lib/aspera/cli/plugins/server.rb +125 -80
- data/lib/aspera/cli/plugins/shares.rb +301 -107
- data/lib/aspera/cli/preset_actions.rb +139 -0
- data/lib/aspera/cli/preset_manager.rb +236 -0
- data/lib/aspera/cli/result.rb +360 -0
- data/lib/aspera/cli/runner.rb +473 -0
- data/lib/aspera/cli/secret_finder.rb +40 -0
- data/lib/aspera/cli/special_values.rb +1 -0
- data/lib/aspera/cli/sync_actions.rb +84 -56
- data/lib/aspera/cli/terminal_formatter.rb +65 -0
- data/lib/aspera/cli/transfer_actions.rb +83 -0
- data/lib/aspera/cli/transfer_agent.rb +116 -51
- data/lib/aspera/cli/transfer_progress.rb +9 -9
- data/lib/aspera/cli/vault_manager.rb +57 -0
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/cli/wizard.rb +26 -26
- data/lib/aspera/command_line_builder.rb +23 -23
- data/lib/aspera/data_repository.rb +6 -1
- data/lib/aspera/dot_container.rb +5 -5
- data/lib/aspera/environment.rb +39 -13
- data/lib/aspera/exec_spec.rb +13 -0
- data/lib/aspera/faspex_gw.rb +2 -2
- data/lib/aspera/faspex_postproc.rb +4 -3
- data/lib/aspera/graphql.rb +35 -0
- data/lib/aspera/hash_ext.rb +6 -0
- data/lib/aspera/json_rpc/client.rb +62 -0
- data/lib/aspera/json_rpc/version.rb +7 -0
- data/lib/aspera/keychain/base.rb +1 -1
- data/lib/aspera/keychain/encrypted_hash.rb +2 -2
- data/lib/aspera/keychain/factory.rb +4 -4
- data/lib/aspera/keychain/macos_security.rb +4 -4
- data/lib/aspera/link_header.rb +82 -0
- data/lib/aspera/log.rb +23 -5
- data/lib/aspera/markdown.rb +85 -2
- data/lib/aspera/nagios.rb +2 -2
- data/lib/aspera/node_simulator.rb +3 -1
- data/lib/aspera/oauth/base.rb +10 -10
- data/lib/aspera/oauth/boot.rb +43 -0
- data/lib/aspera/oauth/factory.rb +41 -15
- data/lib/aspera/oauth/jwt.rb +4 -4
- data/lib/aspera/oauth/web.rb +4 -4
- data/lib/aspera/oauth.rb +1 -0
- data/lib/aspera/persistency_action_once.rb +10 -10
- data/lib/aspera/persistency_folder.rb +10 -3
- data/lib/aspera/preview/file_types.rb +7 -3
- data/lib/aspera/preview/generator.rb +3 -3
- data/lib/aspera/preview/utils.rb +1 -1
- data/lib/aspera/products/connect.rb +4 -1
- data/lib/aspera/products/other.rb +1 -1
- data/lib/aspera/products/transferd.rb +3 -3
- data/lib/aspera/proxy_auto_config.rb +10 -9
- data/lib/aspera/rest.rb +18 -40
- data/lib/aspera/rest_error_analyzer.rb +7 -3
- data/lib/aspera/rest_errors_aspera.rb +0 -10
- data/lib/aspera/rest_list.rb +13 -6
- data/lib/aspera/schema/IBM Aspera Faspex API-5.0-enhanced.yaml +14 -4
- data/lib/aspera/schema/IBM Aspera on Cloud API-0.2.6-enhanced.yaml +2730 -648
- data/lib/aspera/schema/async_tables.yaml +361 -0
- data/lib/aspera/schema/documentation.rb +57 -26
- data/lib/aspera/schema/reader.rb +60 -11
- data/lib/aspera/schema/registry.rb +50 -10
- data/lib/aspera/secret_hider.rb +11 -2
- data/lib/aspera/ssl.rb +4 -4
- data/lib/aspera/sync/conf.schema.yaml +2 -2
- data/lib/aspera/sync/database.rb +14 -10
- data/lib/aspera/sync/operations.rb +15 -18
- data/lib/aspera/temp_file_manager.rb +5 -1
- data/lib/aspera/timer_limiter.rb +1 -1
- data/lib/aspera/transfer/faux_file.rb +24 -11
- data/lib/aspera/transfer/parameters.rb +27 -25
- data/lib/aspera/transfer/result.rb +74 -0
- data/lib/aspera/transfer/resumer.rb +7 -7
- data/lib/aspera/transfer/spec.rb +18 -1
- data/lib/aspera/transfer/spec.schema.yaml +26 -8
- data/lib/aspera/transfer/uri.rb +1 -1
- data/lib/aspera/uri_reader.rb +2 -2
- data/lib/aspera/web_auth.rb +2 -2
- data/lib/aspera/web_server_simple.rb +8 -5
- data/lib/aspera/yaml.rb +2 -1
- data.tar.gz.sig +0 -0
- metadata +45 -16
- metadata.gz.sig +0 -0
- data/lib/aspera/cli/main.rb +0 -480
- data/lib/aspera/json_rpc.rb +0 -51
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
# Schema for the SQLite tables inside the Async snap database (snap.db).
|
|
2
|
+
# Sources:
|
|
3
|
+
# include/async/session/Sqlite3_SSDB.h (SYNC_SQLITE3_META_SCHEMA, SYNC_SQLITE3_COUNTERS_SCHEMA, SYNC_SQLITE3_SCHEMA_1_0)
|
|
4
|
+
# include/async/common/Sync_types.h (SSSTATE values)
|
|
5
|
+
# Verified against a live snap.db using: ascli config sync admin overview <path>
|
|
6
|
+
$schema: https://json-schema.org/draft/2020-12/schema
|
|
7
|
+
$id: https://github.com/IBM/aspera-cli/tree/main/lib/aspera/schema/async_tables.yaml
|
|
8
|
+
title: Async snap database tables
|
|
9
|
+
description: Schemas for the SQLite tables stored inside the Async snap database (`snap.db`).
|
|
10
|
+
type: object
|
|
11
|
+
properties:
|
|
12
|
+
meta:
|
|
13
|
+
title: sync_snapmeta_table
|
|
14
|
+
description: One row per session, written at start and updated at stop.
|
|
15
|
+
type: object
|
|
16
|
+
properties:
|
|
17
|
+
dbversion:
|
|
18
|
+
description: Database schema version.
|
|
19
|
+
type: string
|
|
20
|
+
pairname:
|
|
21
|
+
description: Sync session name.
|
|
22
|
+
type: string
|
|
23
|
+
ldir:
|
|
24
|
+
description: Local directory path.
|
|
25
|
+
type: string
|
|
26
|
+
rhost:
|
|
27
|
+
description: Remote host.
|
|
28
|
+
type: string
|
|
29
|
+
rdir:
|
|
30
|
+
description: Remote directory path.
|
|
31
|
+
type: string
|
|
32
|
+
direction:
|
|
33
|
+
description: Sync direction.
|
|
34
|
+
type: string
|
|
35
|
+
enum:
|
|
36
|
+
- push
|
|
37
|
+
- pull
|
|
38
|
+
- bidi
|
|
39
|
+
inode_format:
|
|
40
|
+
description: Inode format used by the session.
|
|
41
|
+
type: string
|
|
42
|
+
checksum:
|
|
43
|
+
description: Checksum algorithm.
|
|
44
|
+
type: string
|
|
45
|
+
enum:
|
|
46
|
+
- sha1
|
|
47
|
+
- md5
|
|
48
|
+
- sha1_sparse
|
|
49
|
+
- md5_sparse
|
|
50
|
+
- none
|
|
51
|
+
start_time:
|
|
52
|
+
description: Session start timestamp.
|
|
53
|
+
type: string
|
|
54
|
+
format: date-time
|
|
55
|
+
stop_time:
|
|
56
|
+
description: Session stop timestamp (written when session ends).
|
|
57
|
+
type: string
|
|
58
|
+
format: date-time
|
|
59
|
+
condition:
|
|
60
|
+
description: Last known session condition.
|
|
61
|
+
type: string
|
|
62
|
+
enum:
|
|
63
|
+
- running
|
|
64
|
+
- stopped
|
|
65
|
+
scn_true_val:
|
|
66
|
+
description: Scan counter true value (internal).
|
|
67
|
+
type: integer
|
|
68
|
+
sync_point:
|
|
69
|
+
description: Synchronization point sequence number.
|
|
70
|
+
type: integer
|
|
71
|
+
max_recid:
|
|
72
|
+
description: Highest record ID allocated in the snapshot table.
|
|
73
|
+
type: integer
|
|
74
|
+
sync_uuid:
|
|
75
|
+
description: UUID identifying this sync pair.
|
|
76
|
+
type: string
|
|
77
|
+
cip_true_val:
|
|
78
|
+
description: Candidate-in-progress counter true value (internal).
|
|
79
|
+
type: integer
|
|
80
|
+
exclude_dirs_older_than:
|
|
81
|
+
description: Exclude directories with modification time older than this epoch value (0 = disabled).
|
|
82
|
+
type: integer
|
|
83
|
+
path_synced:
|
|
84
|
+
description: Number of paths successfully synchronized.
|
|
85
|
+
type: integer
|
|
86
|
+
byte_synced:
|
|
87
|
+
description: Number of bytes successfully synchronized.
|
|
88
|
+
type: integer
|
|
89
|
+
filters:
|
|
90
|
+
description: Active include/exclude filter patterns.
|
|
91
|
+
type: string
|
|
92
|
+
path_peerxfer:
|
|
93
|
+
description: Number of paths transferred by the peer.
|
|
94
|
+
type: integer
|
|
95
|
+
byte_peerxfer:
|
|
96
|
+
description: Number of bytes transferred by the peer.
|
|
97
|
+
type: integer
|
|
98
|
+
path_xferres:
|
|
99
|
+
description: Number of paths for which transfer was resumed.
|
|
100
|
+
type: integer
|
|
101
|
+
byte_xferres:
|
|
102
|
+
description: Number of bytes for which transfer was resumed.
|
|
103
|
+
type: integer
|
|
104
|
+
file_synced:
|
|
105
|
+
description: Number of files successfully synchronized.
|
|
106
|
+
type: integer
|
|
107
|
+
file_peerxfer:
|
|
108
|
+
description: Number of files transferred by the peer.
|
|
109
|
+
type: integer
|
|
110
|
+
file_xferres:
|
|
111
|
+
description: Number of files for which transfer was resumed.
|
|
112
|
+
type: integer
|
|
113
|
+
ascp_sids:
|
|
114
|
+
description: Last known FASP (ascp) session IDs.
|
|
115
|
+
type: string
|
|
116
|
+
counters:
|
|
117
|
+
title: sync_snap_counters_table
|
|
118
|
+
description: One row, updated live during the session with path and file counts per state.
|
|
119
|
+
type: object
|
|
120
|
+
properties:
|
|
121
|
+
syncd:
|
|
122
|
+
description: Number of paths in the `Syncd` state.
|
|
123
|
+
type: integer
|
|
124
|
+
conflict:
|
|
125
|
+
description: Number of paths in the `Conflict` state.
|
|
126
|
+
type: integer
|
|
127
|
+
potential_conflict:
|
|
128
|
+
description: Number of paths in the `Potential conflict` state.
|
|
129
|
+
type: integer
|
|
130
|
+
error:
|
|
131
|
+
description: Number of paths in the `Error` state.
|
|
132
|
+
type: integer
|
|
133
|
+
pending:
|
|
134
|
+
description: Number of paths still pending synchronization.
|
|
135
|
+
type: integer
|
|
136
|
+
unused:
|
|
137
|
+
description: Reserved (unused counter slot).
|
|
138
|
+
type: integer
|
|
139
|
+
files_syncd:
|
|
140
|
+
description: Number of files in the `Syncd` state.
|
|
141
|
+
type: integer
|
|
142
|
+
files_conflict:
|
|
143
|
+
description: Number of files in the `Conflict` state.
|
|
144
|
+
type: integer
|
|
145
|
+
files_potential_conflict:
|
|
146
|
+
description: Number of files in the `Potential conflict` state.
|
|
147
|
+
type: integer
|
|
148
|
+
files_error:
|
|
149
|
+
description: Number of files in the `Error` state.
|
|
150
|
+
type: integer
|
|
151
|
+
files_pending:
|
|
152
|
+
description: Number of files still pending synchronization.
|
|
153
|
+
type: integer
|
|
154
|
+
file_info:
|
|
155
|
+
title: sync_snapdb_table
|
|
156
|
+
description: One row per tracked file or directory. Primary source for the `file_info` command.
|
|
157
|
+
type: object
|
|
158
|
+
properties:
|
|
159
|
+
record_id:
|
|
160
|
+
description: Primary key (auto-increment).
|
|
161
|
+
type: integer
|
|
162
|
+
nodeid:
|
|
163
|
+
description: Local filesystem node ID.
|
|
164
|
+
type: integer
|
|
165
|
+
peer_rid:
|
|
166
|
+
description: Peer record ID for this entry.
|
|
167
|
+
type: integer
|
|
168
|
+
state:
|
|
169
|
+
description: |
|
|
170
|
+
Sync state of the entry.
|
|
171
|
+
|
|
172
|
+
| Value | Name |
|
|
173
|
+
|-------|-------------------|
|
|
174
|
+
| 0 | Nil |
|
|
175
|
+
| 1–18 | Pending (variant) |
|
|
176
|
+
| 19 | Syncd |
|
|
177
|
+
| 20 | Error |
|
|
178
|
+
| 21 | Conflict |
|
|
179
|
+
| 22 | PotentialConflict |
|
|
180
|
+
| 23–24 | Pending (variant) |
|
|
181
|
+
type: integer
|
|
182
|
+
version:
|
|
183
|
+
description: Schema version field (not used).
|
|
184
|
+
type: integer
|
|
185
|
+
c_meta_type:
|
|
186
|
+
description: Current metadata — file type (file, directory, …).
|
|
187
|
+
type: integer
|
|
188
|
+
c_meta_parentrid:
|
|
189
|
+
description: Current metadata — parent record ID.
|
|
190
|
+
type: integer
|
|
191
|
+
c_meta_path:
|
|
192
|
+
description: Current metadata — file path as known to the snapshot.
|
|
193
|
+
type: string
|
|
194
|
+
c_meta_attrs:
|
|
195
|
+
description: Current metadata — file attributes.
|
|
196
|
+
type: string
|
|
197
|
+
c_meta_uid:
|
|
198
|
+
description: Current metadata — user ID (Unix).
|
|
199
|
+
type: integer
|
|
200
|
+
c_meta_gid:
|
|
201
|
+
description: Current metadata — group ID (Unix).
|
|
202
|
+
type: integer
|
|
203
|
+
c_meta_mtime:
|
|
204
|
+
description: Current metadata — modification time (epoch).
|
|
205
|
+
type: integer
|
|
206
|
+
c_meta_atime:
|
|
207
|
+
description: Current metadata — access time (epoch).
|
|
208
|
+
type: integer
|
|
209
|
+
c_meta_ctime:
|
|
210
|
+
description: Current metadata — change time (epoch).
|
|
211
|
+
type: integer
|
|
212
|
+
c_meta_xattrs:
|
|
213
|
+
description: Current metadata — extended attributes (not used).
|
|
214
|
+
type: integer
|
|
215
|
+
c_meta_xattrs_cksum:
|
|
216
|
+
description: Current metadata — checksum of extended attributes.
|
|
217
|
+
type: string
|
|
218
|
+
c_meta_ol_legal_hold:
|
|
219
|
+
description: Current metadata — object lock legal hold flag.
|
|
220
|
+
type: integer
|
|
221
|
+
c_meta_ol_mode:
|
|
222
|
+
description: Current metadata — object lock mode.
|
|
223
|
+
type: integer
|
|
224
|
+
c_meta_ol_retain_until:
|
|
225
|
+
description: Current metadata — object lock retain-until date (epoch).
|
|
226
|
+
type: integer
|
|
227
|
+
c_meta_object_metadata:
|
|
228
|
+
description: Current metadata — object metadata (JSON).
|
|
229
|
+
type: string
|
|
230
|
+
c_cont_size:
|
|
231
|
+
description: Current content — file size in bytes.
|
|
232
|
+
type: integer
|
|
233
|
+
c_cont_csum:
|
|
234
|
+
description: Current content — checksum.
|
|
235
|
+
type: string
|
|
236
|
+
c_cont_mtime:
|
|
237
|
+
description: Current content — modification time (epoch).
|
|
238
|
+
type: integer
|
|
239
|
+
c_cont_timestamp:
|
|
240
|
+
description: Current content — internal timestamp.
|
|
241
|
+
type: integer
|
|
242
|
+
p_cont_size:
|
|
243
|
+
description: Pending content — file size in bytes.
|
|
244
|
+
type: integer
|
|
245
|
+
p_cont_csum:
|
|
246
|
+
description: Pending content — checksum.
|
|
247
|
+
type: string
|
|
248
|
+
p_cont_mtime:
|
|
249
|
+
description: Pending content — modification time (epoch).
|
|
250
|
+
type: integer
|
|
251
|
+
p_cont_timestamp:
|
|
252
|
+
description: Pending content — internal timestamp.
|
|
253
|
+
type: integer
|
|
254
|
+
f_meta_type:
|
|
255
|
+
description: Filesystem metadata — file type.
|
|
256
|
+
type: integer
|
|
257
|
+
f_meta_parentrid:
|
|
258
|
+
description: Filesystem metadata — parent record ID.
|
|
259
|
+
type: integer
|
|
260
|
+
f_meta_path:
|
|
261
|
+
description: Filesystem metadata — file path as seen on disk (displayed by `file_info`).
|
|
262
|
+
type: string
|
|
263
|
+
f_meta_attrs:
|
|
264
|
+
description: Filesystem metadata — file attributes.
|
|
265
|
+
type: string
|
|
266
|
+
f_meta_uid:
|
|
267
|
+
description: Filesystem metadata — user ID (Unix).
|
|
268
|
+
type: integer
|
|
269
|
+
f_meta_gid:
|
|
270
|
+
description: Filesystem metadata — group ID (Unix).
|
|
271
|
+
type: integer
|
|
272
|
+
f_meta_mtime:
|
|
273
|
+
description: Filesystem metadata — modification time (epoch).
|
|
274
|
+
type: integer
|
|
275
|
+
f_meta_atime:
|
|
276
|
+
description: Filesystem metadata — access time (epoch).
|
|
277
|
+
type: integer
|
|
278
|
+
f_meta_ctime:
|
|
279
|
+
description: Filesystem metadata — change time (epoch).
|
|
280
|
+
type: integer
|
|
281
|
+
f_meta_xattrs:
|
|
282
|
+
description: Filesystem metadata — extended attributes (not used).
|
|
283
|
+
type: integer
|
|
284
|
+
f_meta_xattrs_cksum:
|
|
285
|
+
description: Filesystem metadata — checksum of extended attributes.
|
|
286
|
+
type: string
|
|
287
|
+
f_meta_ol_legal_hold:
|
|
288
|
+
description: Filesystem metadata — object lock legal hold flag.
|
|
289
|
+
type: integer
|
|
290
|
+
f_meta_ol_mode:
|
|
291
|
+
description: Filesystem metadata — object lock mode.
|
|
292
|
+
type: integer
|
|
293
|
+
f_meta_ol_retain_until:
|
|
294
|
+
description: Filesystem metadata — object lock retain-until date (epoch).
|
|
295
|
+
type: integer
|
|
296
|
+
f_meta_object_metadata:
|
|
297
|
+
description: Filesystem metadata — object metadata (JSON).
|
|
298
|
+
type: string
|
|
299
|
+
f_cont_size:
|
|
300
|
+
description: Filesystem content — file size in bytes.
|
|
301
|
+
type: integer
|
|
302
|
+
f_cont_csum:
|
|
303
|
+
description: Filesystem content — checksum.
|
|
304
|
+
type: string
|
|
305
|
+
f_cont_mtime:
|
|
306
|
+
description: Filesystem content — modification time (epoch).
|
|
307
|
+
type: integer
|
|
308
|
+
f_cont_timestamp:
|
|
309
|
+
description: Filesystem content — internal timestamp.
|
|
310
|
+
type: integer
|
|
311
|
+
pcr_reqno:
|
|
312
|
+
description: Peer content request sequence number.
|
|
313
|
+
type: integer
|
|
314
|
+
pp_cont_size:
|
|
315
|
+
description: Peer pending content — file size in bytes.
|
|
316
|
+
type: integer
|
|
317
|
+
pp_cont_csum:
|
|
318
|
+
description: Peer pending content — checksum.
|
|
319
|
+
type: string
|
|
320
|
+
pp_cont_mtime:
|
|
321
|
+
description: Peer pending content — modification time (epoch).
|
|
322
|
+
type: integer
|
|
323
|
+
pp_cont_timestamp:
|
|
324
|
+
description: Peer pending content — internal timestamp.
|
|
325
|
+
type: integer
|
|
326
|
+
tobe_deleted:
|
|
327
|
+
description: Set to 1 when the record is flagged for deletion (garbage collection pending).
|
|
328
|
+
type: integer
|
|
329
|
+
scn_not_visited:
|
|
330
|
+
description: Set to 1 when the scanner has not yet visited this entry in the current scan pass.
|
|
331
|
+
type: integer
|
|
332
|
+
scn_required:
|
|
333
|
+
description: Set to 1 when a rescan of this entry is required.
|
|
334
|
+
type: integer
|
|
335
|
+
scn_completed:
|
|
336
|
+
description: Set to 1 when the scan of this directory entry has completed.
|
|
337
|
+
type: integer
|
|
338
|
+
candidate_in_prog:
|
|
339
|
+
description: Set to 1 when this record is currently in the candidate transfer list.
|
|
340
|
+
type: integer
|
|
341
|
+
meta_lastreq_no:
|
|
342
|
+
description: Sequence number of the last metadata request sent.
|
|
343
|
+
type: integer
|
|
344
|
+
meta_lastresp_no:
|
|
345
|
+
description: Sequence number of the last metadata response received.
|
|
346
|
+
type: integer
|
|
347
|
+
commit_version:
|
|
348
|
+
description: Local commit version for this entry.
|
|
349
|
+
type: integer
|
|
350
|
+
peer_commit_version:
|
|
351
|
+
description: Peer commit version for this entry.
|
|
352
|
+
type: integer
|
|
353
|
+
peer_nodeid:
|
|
354
|
+
description: Peer filesystem node ID.
|
|
355
|
+
type: integer
|
|
356
|
+
recursive_mtime:
|
|
357
|
+
description: Most recent modification time across all descendants (directories only).
|
|
358
|
+
type: integer
|
|
359
|
+
message:
|
|
360
|
+
description: Error or status message associated with this entry.
|
|
361
|
+
type: string
|
|
@@ -7,6 +7,15 @@ module Aspera
|
|
|
7
7
|
module Schema
|
|
8
8
|
# Generate documentation from Schema, for Transfer Spec, or async Conf spec
|
|
9
9
|
class Documentation
|
|
10
|
+
# Map JSON Schema type names to user-friendly display names
|
|
11
|
+
JSON_TYPE_TO_DOC = {
|
|
12
|
+
'string' => 'String',
|
|
13
|
+
'integer' => 'Integer',
|
|
14
|
+
'number' => 'Number',
|
|
15
|
+
'boolean' => 'Bool',
|
|
16
|
+
'array' => 'Array',
|
|
17
|
+
'object' => 'Hash'
|
|
18
|
+
}.freeze
|
|
10
19
|
# @param formatter [Cli::Formatter] Formatter instance with methods: markdown_text, tick, check_row
|
|
11
20
|
# @param schema [Reader]
|
|
12
21
|
# @param include_option [Boolean] `true`: include CLI options (switches, env vars) in descriptions
|
|
@@ -18,25 +27,27 @@ module Aspera
|
|
|
18
27
|
@include_option = include_option
|
|
19
28
|
@agent_columns = agent_columns
|
|
20
29
|
@code_highlight = code_highlight
|
|
21
|
-
@columns = %
|
|
22
|
-
@columns.insert(-2, *Agent::Factory::ALL.values.map{ |i| i[:short]}.sort) if @agent_columns
|
|
23
|
-
#
|
|
24
|
-
|
|
30
|
+
@columns = %w[name type description]
|
|
31
|
+
@columns.insert(-2, *Agent::Factory::ALL.values.map{ |i| i[:short].to_s}.sort) if @agent_columns
|
|
32
|
+
# Sections: each entry is {header: row_or_nil, rows: []}
|
|
33
|
+
# A flat schema produces a single section with no header.
|
|
34
|
+
@sections = [{header: nil, rows: []}]
|
|
25
35
|
end
|
|
26
36
|
|
|
27
37
|
def rows
|
|
28
|
-
@
|
|
38
|
+
@sections.flat_map do |section|
|
|
39
|
+
sorted = section[:rows].sort_by{ |i| i['name']}
|
|
40
|
+
section[:header] ? [section[:header]] + sorted : sorted
|
|
41
|
+
end
|
|
29
42
|
end
|
|
30
43
|
|
|
31
44
|
# @return [Array<String>]
|
|
32
|
-
|
|
33
|
-
@columns.map(&:to_s)
|
|
34
|
-
end
|
|
45
|
+
attr_reader :columns
|
|
35
46
|
|
|
36
|
-
# First row is the titles
|
|
47
|
+
# First row is the titles (for Markdown table generation)
|
|
37
48
|
# @return [Array<Array<String>>]
|
|
38
49
|
def table
|
|
39
|
-
[@columns
|
|
50
|
+
[@columns] + rows.map{ |row| @columns.map{ |field| row[field]}}
|
|
40
51
|
end
|
|
41
52
|
|
|
42
53
|
# Generate a documentation table from a JSON schema for transfer specifications
|
|
@@ -49,37 +60,57 @@ module Aspera
|
|
|
49
60
|
def build(schema = nil)
|
|
50
61
|
code = @code_highlight ? ->(c){"`#{c}`"} : ->(c){c}
|
|
51
62
|
schema ||= @schema
|
|
52
|
-
|
|
63
|
+
render_title = ->(title){title.gsub(Markdown::FORMATS){@formatter.markdown_text(Regexp.last_match)}}
|
|
64
|
+
on_variant = ->(variant_reader, discriminant_property, discriminant_value) do
|
|
65
|
+
title = variant_reader.current['title'] || variant_reader.current['description']
|
|
66
|
+
header =
|
|
67
|
+
if discriminant_property && discriminant_value
|
|
68
|
+
desc = render_title.call("`#{discriminant_value}`")
|
|
69
|
+
desc += ": #{render_title.call(title)}" if title
|
|
70
|
+
@formatter.check_row({
|
|
71
|
+
'name' => render_title.call("**#{discriminant_property}**"),
|
|
72
|
+
'type' => code.call(JSON_TYPE_TO_DOC['string']),
|
|
73
|
+
'description' => desc
|
|
74
|
+
})
|
|
75
|
+
elsif title
|
|
76
|
+
@formatter.check_row({'name' => "**#{render_title.call(title)}**", 'type' => ' ', 'description' => ' '})
|
|
77
|
+
end
|
|
78
|
+
@sections.push({header: header, rows: []})
|
|
79
|
+
end
|
|
80
|
+
schema.each_property(on_variant: on_variant) do |property_schema, _name, property_full_name|
|
|
53
81
|
node = property_schema.current
|
|
54
82
|
# Manual table
|
|
83
|
+
item_type = JSON_TYPE_TO_DOC.fetch(node['type'], node['type'])
|
|
84
|
+
item_type = "#{item_type}[#{JSON_TYPE_TO_DOC.fetch(node.dig('items', 'type'), node.dig('items', 'type'))}]" if node['type'].eql?('array') && node.dig('items', 'type').is_a?(String)
|
|
55
85
|
item = {
|
|
56
|
-
name
|
|
57
|
-
type
|
|
58
|
-
description
|
|
86
|
+
'name' => code.call(property_full_name),
|
|
87
|
+
'type' => code.call(item_type),
|
|
88
|
+
'description' => []
|
|
59
89
|
}
|
|
60
90
|
# Render Markdown formatting and split lines
|
|
61
|
-
item[
|
|
91
|
+
item['description'] =
|
|
62
92
|
node['description']
|
|
63
93
|
.gsub(Markdown::FORMATS){@formatter.markdown_text(Regexp.last_match)}
|
|
64
94
|
.split("\n") if node.key?('description')
|
|
65
|
-
item[
|
|
95
|
+
item['description'].unshift("DEPRECATED: #{node['x-deprecation']}") if node.key?('x-deprecation')
|
|
66
96
|
# Add flags for supported agents in doc
|
|
67
97
|
agents = []
|
|
68
98
|
Agent::Factory::ALL.each_key do |sym|
|
|
69
99
|
agents.push(sym) if node['x-agents'].nil? || node['x-agents'].include?(sym.to_s)
|
|
70
100
|
end
|
|
71
|
-
Aspera.assert(agents.include?(:direct)){"#{
|
|
101
|
+
Aspera.assert(agents.include?(:direct)){"#{property_full_name}: x-cli-option requires agent direct (or nil)"} if node['x-cli-option']
|
|
72
102
|
if @agent_columns
|
|
73
103
|
Agent::Factory::ALL.each do |sym, names|
|
|
74
|
-
item[names[:short]] = @formatter.tick(agents.include?(sym))
|
|
104
|
+
item[names[:short].to_s] = @formatter.tick(agents.include?(sym))
|
|
75
105
|
end
|
|
76
106
|
else
|
|
77
|
-
item[
|
|
107
|
+
item['description'].push("(#{agents.map{ |i| Agent::Factory::ALL[i][:short].to_s.upcase}.sort.join(', ')})") unless agents.length.eql?(Agent::Factory::ALL.length)
|
|
78
108
|
end
|
|
79
109
|
# Only keep lines that are usable in supported agents
|
|
80
|
-
next
|
|
81
|
-
item[
|
|
82
|
-
item[
|
|
110
|
+
next if agents.empty?
|
|
111
|
+
item['description'].push("Allowed values: #{node['enum'].map{ |v| @formatter.markdown_text("`#{v}`")}.join(', ')}.") if node.key?('enum')
|
|
112
|
+
item['description'].push("Default: #{@formatter.markdown_text("`#{node['default']}`")}.") if node.key?('default')
|
|
113
|
+
item['description'].push("Example: #{@formatter.markdown_text("`#{node['example']}`")}.") if node.key?('example')
|
|
83
114
|
if @include_option
|
|
84
115
|
envvar_prefix = ''
|
|
85
116
|
cli_option =
|
|
@@ -87,18 +118,18 @@ module Aspera
|
|
|
87
118
|
envvar_prefix = 'env:'
|
|
88
119
|
node['x-cli-envvar']
|
|
89
120
|
elsif node['x-cli-switch']
|
|
90
|
-
node['x-cli-
|
|
121
|
+
false_part = node.key?('x-cli-false') ? " / #{node['x-cli-false']}" : ''
|
|
122
|
+
"#{node['x-cli-option']}#{false_part}"
|
|
91
123
|
elsif node['x-cli-option']
|
|
92
124
|
arg_type = node.key?('enum') ? '{enum}' : "{#{[node['type']].flatten.join('|')}}"
|
|
93
|
-
# conversion_tag = node['x-cli-convert']
|
|
94
125
|
conversion_tag = node.key?('x-cli-convert') ? 'conversion' : nil
|
|
95
126
|
sep = node['x-cli-option'].start_with?('--') ? '=' : ' '
|
|
96
127
|
"#{node['x-cli-option']}#{sep}#{"(#{conversion_tag})" if conversion_tag}#{arg_type}"
|
|
97
128
|
end
|
|
98
129
|
short = node.key?('x-cli-short') ? "(#{node['x-cli-short']})" : nil
|
|
99
|
-
item[
|
|
130
|
+
item['description'].push("(#{'special:' if node['x-cli-special']}#{envvar_prefix}#{@formatter.markdown_text("`#{cli_option}`")})#{short}") if cli_option
|
|
100
131
|
end
|
|
101
|
-
@rows.push(@formatter.check_row(item))
|
|
132
|
+
@sections.last[:rows].push(@formatter.check_row(item))
|
|
102
133
|
end
|
|
103
134
|
self
|
|
104
135
|
end
|
data/lib/aspera/schema/reader.rb
CHANGED
|
@@ -7,11 +7,34 @@ module Aspera
|
|
|
7
7
|
class Reader
|
|
8
8
|
attr_reader :current
|
|
9
9
|
|
|
10
|
+
class << self
|
|
11
|
+
# Build a synthetic Reader from an OAS `parameters` array (entries with `in: query`).
|
|
12
|
+
# Produces a JSON Schema object whose `properties` map each query param name to its schema,
|
|
13
|
+
# with the OAS-level `description` and `required` merged in.
|
|
14
|
+
# @param params [Array<Hash>] raw OAS parameter objects (may contain path/header params too)
|
|
15
|
+
# @return [Reader]
|
|
16
|
+
def from_query_params(params)
|
|
17
|
+
properties = {}
|
|
18
|
+
required_names = []
|
|
19
|
+
params.each do |param|
|
|
20
|
+
next unless param['in'] == 'query'
|
|
21
|
+
name = param['name']
|
|
22
|
+
prop = (param['schema'] || {}).dup
|
|
23
|
+
prop['description'] = param['description'] if param['description'] && !prop.key?('description')
|
|
24
|
+
properties[name] = prop
|
|
25
|
+
required_names << name if param['required']
|
|
26
|
+
end
|
|
27
|
+
synthetic = {'type' => 'object', 'properties' => properties}
|
|
28
|
+
synthetic['required'] = required_names unless required_names.empty?
|
|
29
|
+
new(synthetic)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
10
33
|
# Shortcut to access current value at path
|
|
11
|
-
# @param
|
|
34
|
+
# @param key [String] path element
|
|
12
35
|
# @return [Hash, Array, String, Integer] current value at path
|
|
13
|
-
def [](
|
|
14
|
-
@current[
|
|
36
|
+
def [](key)
|
|
37
|
+
@current[key]
|
|
15
38
|
end
|
|
16
39
|
|
|
17
40
|
# Find sub path relative to current
|
|
@@ -24,13 +47,19 @@ module Aspera
|
|
|
24
47
|
Aspera.assert_type(current, Hash){'schema'}
|
|
25
48
|
if current.key?('$ref')
|
|
26
49
|
ref = current['$ref']
|
|
27
|
-
Aspera.assert(ref.start_with?('#/'))
|
|
50
|
+
Aspera.assert(ref.start_with?('#/')){"schema $ref must start with '#/': #{ref}"}
|
|
28
51
|
current = @root.dig(*ref[2..].split('/'))
|
|
29
52
|
end
|
|
30
53
|
end
|
|
31
54
|
Reader.new(@root, current)
|
|
32
55
|
end
|
|
33
56
|
|
|
57
|
+
# Resolve a $ref string to a Reader
|
|
58
|
+
def resolve_ref(ref)
|
|
59
|
+
Aspera.assert(ref.start_with?('#/')){"schema $ref must start with '#/': #{ref}"}
|
|
60
|
+
Reader.new(@root, @root.dig(*ref[2..].split('/')))
|
|
61
|
+
end
|
|
62
|
+
|
|
34
63
|
# Read schema from file or from cache
|
|
35
64
|
# @param root [Hash] root schema
|
|
36
65
|
# @param current [Hash, nil] current position in
|
|
@@ -40,15 +69,35 @@ module Aspera
|
|
|
40
69
|
@current = current || root
|
|
41
70
|
end
|
|
42
71
|
|
|
43
|
-
# Recursively traverse schema properties with a block
|
|
44
|
-
#
|
|
45
|
-
#
|
|
72
|
+
# Recursively traverse schema properties with a block.
|
|
73
|
+
# If the current node has `oneOf`, each variant is traversed in turn and
|
|
74
|
+
# `on_variant` is called (if given) before each variant's properties.
|
|
75
|
+
# @param prefix [String] Prefix for property names (e.g., 'parent.child.')
|
|
76
|
+
# @param on_variant [Proc, nil] Called with the variant Reader before its properties
|
|
46
77
|
# @yield [property_schema, name, full_name] Yields property info to block
|
|
47
|
-
# @yieldparam property_schema [Reader] Schema reader for this property
|
|
78
|
+
# @yieldparam property_schema [Reader] Schema reader for this property
|
|
48
79
|
# @yieldparam name [String] Property name
|
|
49
80
|
# @yieldparam full_name [String] Full property name with prefix
|
|
50
81
|
# @return [nil]
|
|
51
|
-
def each_property(prefix = '', &block)
|
|
82
|
+
def each_property(prefix = '', on_variant: nil, &block)
|
|
83
|
+
if @current.key?('oneOf')
|
|
84
|
+
# Build reverse map: $ref -> discriminant value, from discriminator.mapping if present
|
|
85
|
+
discriminant_by_ref = {}
|
|
86
|
+
if @current.dig('discriminator', 'mapping').is_a?(Hash)
|
|
87
|
+
@current['discriminator']['mapping'].each do |value, ref|
|
|
88
|
+
discriminant_by_ref[ref] = value
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
discriminant_property = @current.dig('discriminator', 'propertyName')
|
|
92
|
+
@current['oneOf'].each do |variant_node|
|
|
93
|
+
ref = variant_node['$ref']
|
|
94
|
+
variant_reader = ref ? resolve_ref(ref) : Reader.new(@root, variant_node)
|
|
95
|
+
discriminant_value = ref ? discriminant_by_ref[ref] : nil
|
|
96
|
+
on_variant&.call(variant_reader, discriminant_property, discriminant_value)
|
|
97
|
+
variant_reader.each_property(prefix, on_variant: on_variant, &block)
|
|
98
|
+
end
|
|
99
|
+
return
|
|
100
|
+
end
|
|
52
101
|
properties = dig('properties')
|
|
53
102
|
properties.current.each_key do |name|
|
|
54
103
|
property_full_name = "#{prefix}#{name}"
|
|
@@ -61,11 +110,11 @@ module Aspera
|
|
|
61
110
|
# Recursively process nested structures
|
|
62
111
|
case node['type']
|
|
63
112
|
when 'object'
|
|
64
|
-
property_schema.each_property("#{property_full_name}.", &block) if node['properties']
|
|
113
|
+
property_schema.each_property("#{property_full_name}.", on_variant: on_variant, &block) if node['properties']
|
|
65
114
|
when 'array'
|
|
66
115
|
if node['items']
|
|
67
116
|
array_item_schema = property_schema.dig('items')
|
|
68
|
-
array_item_schema.each_property("#{property_full_name}[].", &block) if array_item_schema.current['properties']
|
|
117
|
+
array_item_schema.each_property("#{property_full_name}[].", on_variant: on_variant, &block) if array_item_schema.current['properties']
|
|
69
118
|
end
|
|
70
119
|
end
|
|
71
120
|
end
|