@data-fair/catalog-sftp 0.2.0 → 0.3.1
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/index.ts +2 -7
- package/lib/download.ts +29 -5
- package/lib/imports.ts +26 -30
- package/package.json +2 -5
- package/types/catalogConfig/.type/index.js +8 -2
- package/types/catalogConfig/.type/validate.js +2 -2
- package/types/catalogConfig/schema.json +14 -23
package/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CatalogPlugin } from '@data-fair/
|
|
1
|
+
import type { CatalogPlugin } from '@data-fair/types-catalogs'
|
|
2
2
|
import { type SFTPConfig, configSchema, assertConfigValid } from '#types'
|
|
3
3
|
import capabilities from './lib/capabilities.ts'
|
|
4
4
|
|
|
@@ -39,15 +39,10 @@ const plugin: CatalogPlugin<SFTPConfig, typeof capabilities> = {
|
|
|
39
39
|
},
|
|
40
40
|
|
|
41
41
|
async getResource (context) {
|
|
42
|
-
const { getResource } = await import('./lib/
|
|
42
|
+
const { getResource } = await import('./lib/download.ts')
|
|
43
43
|
return getResource(context)
|
|
44
44
|
},
|
|
45
45
|
|
|
46
|
-
async downloadResource (context) {
|
|
47
|
-
const { downloadResource } = await import('./lib/download.ts')
|
|
48
|
-
return downloadResource(context)
|
|
49
|
-
},
|
|
50
|
-
|
|
51
46
|
metadata: {
|
|
52
47
|
title: 'Catalog SFTP',
|
|
53
48
|
description: 'SFTP plugin for Data Fair Catalog',
|
package/lib/download.ts
CHANGED
|
@@ -1,7 +1,31 @@
|
|
|
1
|
-
import type { DownloadResourceContext } from '@data-fair/lib-common-types/catalog/index.js'
|
|
2
1
|
import type { SFTPConfig } from '#types'
|
|
2
|
+
import type { CatalogPlugin, GetResourceContext, Resource } from '@data-fair/types-catalogs'
|
|
3
3
|
import { type Config, NodeSSH } from 'node-ssh'
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Download localy a specific resource from a SFTP server, and retrieves the metadata with the filepath of the downloaded file.
|
|
7
|
+
*
|
|
8
|
+
* @param catalogConfig - The SFTP configuration object.
|
|
9
|
+
* @param resourceId - The identifier (path) of the resource.
|
|
10
|
+
* @returns A `Resource` object representing the file.
|
|
11
|
+
*/
|
|
12
|
+
export const getResource = async (context: GetResourceContext<SFTPConfig>): ReturnType<CatalogPlugin['getResource']> => {
|
|
13
|
+
const resource = await getMetaData(context)
|
|
14
|
+
resource.filePath = await downloadResource(context)
|
|
15
|
+
return resource
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const getMetaData = async ({ catalogConfig, resourceId }: GetResourceContext<SFTPConfig>): Promise<Resource> => {
|
|
19
|
+
const pointPos = resourceId.lastIndexOf('.')
|
|
20
|
+
return {
|
|
21
|
+
id: resourceId,
|
|
22
|
+
title: resourceId.substring(resourceId.lastIndexOf('/') + 1),
|
|
23
|
+
format: (pointPos === -1) ? '' : (resourceId.substring(pointPos + 1)),
|
|
24
|
+
origin: catalogConfig.url + ':' + catalogConfig.port,
|
|
25
|
+
filePath: ''
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
5
29
|
/**
|
|
6
30
|
* Downloads a resource (file) from the SFTP server to a temporary directory.
|
|
7
31
|
*
|
|
@@ -9,7 +33,7 @@ import { type Config, NodeSSH } from 'node-ssh'
|
|
|
9
33
|
* @returns The local path to the downloaded file, or `undefined` if the download fails.
|
|
10
34
|
* @throws Will throw an error if the connection configuration is invalid or not supported.
|
|
11
35
|
*/
|
|
12
|
-
|
|
36
|
+
const downloadResource = async ({ catalogConfig, resourceId, secrets, tmpDir }:GetResourceContext<SFTPConfig>) => {
|
|
13
37
|
const ssh = new NodeSSH()
|
|
14
38
|
|
|
15
39
|
const paramsConnection: Config = {
|
|
@@ -31,12 +55,12 @@ export const downloadResource = async ({ catalogConfig, resourceId, secrets, tmp
|
|
|
31
55
|
throw new Error('Configuration invalide')
|
|
32
56
|
}
|
|
33
57
|
|
|
34
|
-
const fs = await import('node:fs/promises')
|
|
58
|
+
// const fs = await import('node:fs/promises')
|
|
35
59
|
resourceId = resourceId.substring(resourceId.indexOf('./') + 2)
|
|
36
|
-
const destinationPath = tmpDir + '/' + resourceId
|
|
60
|
+
const destinationPath = tmpDir + '/' + resourceId.substring(resourceId.lastIndexOf('/') + 1)
|
|
37
61
|
|
|
38
62
|
// creation du dossier pour stocker le fichier distant
|
|
39
|
-
await fs.mkdir(destinationPath.substring(0, destinationPath.lastIndexOf('/')), { recursive: true })
|
|
63
|
+
// await fs.mkdir(destinationPath.substring(0, destinationPath.lastIndexOf('/')), { recursive: true })
|
|
40
64
|
|
|
41
65
|
try {
|
|
42
66
|
await ssh.getFile(destinationPath, resourceId)
|
package/lib/imports.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { SFTPConfig } from '#types'
|
|
2
2
|
import type { FileEntryWithStats, SFTPWrapper } from 'ssh2'
|
|
3
3
|
import type capabilities from './capabilities.ts'
|
|
4
|
-
import type { ListContext, Folder,
|
|
4
|
+
import type { ListContext, Folder, CatalogPlugin } from '@data-fair/types-catalogs'
|
|
5
5
|
import { type Config, NodeSSH } from 'node-ssh'
|
|
6
6
|
|
|
7
|
+
type ResourceList = Awaited<ReturnType<CatalogPlugin['list']>>['results']
|
|
8
|
+
|
|
7
9
|
/**
|
|
8
10
|
* Stores the most recently used SFTP configuration.
|
|
9
11
|
* This variable holds the last SFTPConfig object that was used,
|
|
@@ -26,18 +28,30 @@ let clientSFTP: SFTPWrapper
|
|
|
26
28
|
*
|
|
27
29
|
* @param list - The array of file objects returned by the SFTP `readdir` method.
|
|
28
30
|
* @param path - The current directory path.
|
|
29
|
-
* @returns An array of `Folder` or `
|
|
31
|
+
* @returns An array of `Folder` or `ResourceList` objects representing the files and folders.
|
|
30
32
|
*/
|
|
31
|
-
const prepareFiles = (list: FileEntryWithStats[], path: string): (Folder |
|
|
32
|
-
return list.map((file
|
|
33
|
+
const prepareFiles = (list: FileEntryWithStats[], path: string): (Folder[] | ResourceList) => {
|
|
34
|
+
return list.map((file: FileEntryWithStats) => {
|
|
33
35
|
const pointPos = file.filename.lastIndexOf('.')
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
if (file.longname.charAt(0) === 'd') {
|
|
37
|
+
// Folder
|
|
38
|
+
return {
|
|
39
|
+
id: path + '/' + file.filename,
|
|
40
|
+
title: file.filename,
|
|
41
|
+
type: 'folder'
|
|
42
|
+
} as Folder
|
|
43
|
+
} else {
|
|
44
|
+
// ResourceList
|
|
45
|
+
return {
|
|
46
|
+
id: path + '/' + file.filename,
|
|
47
|
+
title: file.filename,
|
|
48
|
+
description: '',
|
|
49
|
+
format: (pointPos === -1) ? '' : (file.filename.substring(pointPos + 1)),
|
|
50
|
+
mimeType: '',
|
|
51
|
+
origin: path + '/' + file.filename,
|
|
52
|
+
size: file.attrs.size,
|
|
53
|
+
type: 'resource'
|
|
54
|
+
} as ResourceList[number]
|
|
41
55
|
}
|
|
42
56
|
})
|
|
43
57
|
}
|
|
@@ -49,7 +63,7 @@ const prepareFiles = (list: FileEntryWithStats[], path: string): (Folder | Resou
|
|
|
49
63
|
* @returns An object containing the count of items, the list of results (folders and resources), and the path as an array of folders.
|
|
50
64
|
* @throws Will throw an error if the connection configuration is invalid or not supported.
|
|
51
65
|
*/
|
|
52
|
-
export const list = async ({ catalogConfig, secrets, params }: ListContext<SFTPConfig, typeof capabilities>):
|
|
66
|
+
export const list = async ({ catalogConfig, secrets, params }: ListContext<SFTPConfig, typeof capabilities>): ReturnType<CatalogPlugin['list']> => {
|
|
53
67
|
if (!(lastConfig && ssh && clientSFTP) ||
|
|
54
68
|
JSON.stringify(lastConfig) !== JSON.stringify(catalogConfig) ||
|
|
55
69
|
JSON.stringify(lastSecrets) !== JSON.stringify(secrets)) {
|
|
@@ -110,21 +124,3 @@ export const list = async ({ catalogConfig, secrets, params }: ListContext<SFTPC
|
|
|
110
124
|
path: pathFolder
|
|
111
125
|
}
|
|
112
126
|
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Retrieves metadata for a specific resource (file) on the SFTP server.
|
|
116
|
-
*
|
|
117
|
-
* @param catalogConfig - The SFTP configuration object.
|
|
118
|
-
* @param resourceId - The identifier (path) of the resource.
|
|
119
|
-
* @returns A `Resource` object representing the file.
|
|
120
|
-
*/
|
|
121
|
-
export const getResource = async ({ catalogConfig, secrets, resourceId }: GetResourceContext<SFTPConfig>): Promise<Resource> => {
|
|
122
|
-
const pointPos = resourceId.lastIndexOf('.')
|
|
123
|
-
return {
|
|
124
|
-
id: resourceId,
|
|
125
|
-
title: resourceId.substring(resourceId.lastIndexOf('/') + 1),
|
|
126
|
-
type: 'resource',
|
|
127
|
-
format: (pointPos === -1) ? '' : (resourceId.substring(pointPos + 1)),
|
|
128
|
-
url: resourceId
|
|
129
|
-
}
|
|
130
|
-
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@data-fair/catalog-sftp",
|
|
3
3
|
"description": "SFTP plugin for the Data Fair catalogs service.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.1",
|
|
5
5
|
"main": "index.ts",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"scripts": {
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@commitlint/cli": "^19.8.0",
|
|
41
41
|
"@commitlint/config-conventional": "^19.8.0",
|
|
42
|
-
"@data-fair/
|
|
42
|
+
"@data-fair/types-catalogs": "^0.1.0",
|
|
43
43
|
"@data-fair/lib-types-builder": "^1.8.0",
|
|
44
44
|
"@types/debug": "^4.1.12",
|
|
45
45
|
"@types/fs-extra": "^11.0.4",
|
|
@@ -49,8 +49,5 @@
|
|
|
49
49
|
"husky": "^9.1.7",
|
|
50
50
|
"neostandard": "^0.12.1",
|
|
51
51
|
"typescript": "^5.8.3"
|
|
52
|
-
},
|
|
53
|
-
"relativeDependencies": {
|
|
54
|
-
"@data-fair/lib-common-types": "../../lib/packages/common-types"
|
|
55
52
|
}
|
|
56
53
|
}
|
|
@@ -20,7 +20,7 @@ export function returnValid(data, options) {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export const schema = {
|
|
23
|
-
"$id": "https://github.com/data-fair/catalog-
|
|
23
|
+
"$id": "https://github.com/data-fair/catalog-sftp/catalog-config",
|
|
24
24
|
"x-exports": [
|
|
25
25
|
"types",
|
|
26
26
|
"validate",
|
|
@@ -69,7 +69,7 @@ export const schema = {
|
|
|
69
69
|
"title": "Mode de connexion",
|
|
70
70
|
"description": "Le mode de connexion à utiliser (Mot de passe, clé SSH)",
|
|
71
71
|
"oneOfLayout": {
|
|
72
|
-
"label": "
|
|
72
|
+
"label": "Choisir un mode de connexion"
|
|
73
73
|
},
|
|
74
74
|
"oneOf": [
|
|
75
75
|
{
|
|
@@ -83,6 +83,12 @@ export const schema = {
|
|
|
83
83
|
"description": "Enter your account password for the remote server",
|
|
84
84
|
"x-i18n-description": {
|
|
85
85
|
"fr": "Renseigner le mot de passe associé à votre compte sur le serveur distant"
|
|
86
|
+
},
|
|
87
|
+
"layout": {
|
|
88
|
+
"props": {
|
|
89
|
+
"type": "password",
|
|
90
|
+
"autocomplete": "new-password"
|
|
91
|
+
}
|
|
86
92
|
}
|
|
87
93
|
},
|
|
88
94
|
"key": {
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
"use strict";
|
|
5
5
|
export const validate = validate14;
|
|
6
6
|
export default validate14;
|
|
7
|
-
const schema16 = {"$id":"https://github.com/data-fair/catalog-
|
|
7
|
+
const schema16 = {"$id":"https://github.com/data-fair/catalog-sftp/catalog-config","x-exports":["types","validate","schema"],"title":"SFTPConfig","type":"object","additionalProperties":false,"required":["url","port","connectionKey","login"],"properties":{"url":{"type":"string","title":"Adresse de l'hôte","description":"The host adress","x-i18n-description":{"fr":"L'adresse de l'hôte du catalogue (veuillez vous référez à la documentation technique du catalogue)"},"examples":["exemple-d-hote.fr"]},"port":{"type":"integer","title":"port","description":"The port of the catalog","x-i18n-description":{"fr":"Le port de l'API du catalogue (veuillez vous référez à la documentation technique du catalogue)"},"default":22},"login":{"type":"string","title":"Identifiant","description":"The user login","x-i18n-description":{"fr":"L'identifiant (login) utilisé pour accéder au catalogue"}},"connectionKey":{"type":"object","title":"Mode de connexion","description":"Le mode de connexion à utiliser (Mot de passe, clé SSH)","oneOfLayout":{"label":"Choisir un mode de connexion"},"oneOf":[{"title":"Mot de Passe","required":["password"],"properties":{"password":{"type":"string","description":"Enter your account password for the remote server","x-i18n-description":{"fr":"Renseigner le mot de passe associé à votre compte sur le serveur distant"},"layout":{"props":{"type":"password","autocomplete":"new-password"}}},"key":{"const":"password"}}},{"title":"Clé SHH","required":["sshKey"],"properties":{"key":{"const":"sshKey"},"sshKey":{"type":"string","layout":"textarea","description":"Enter your ssh key","x-i18n-description":{"fr":"Renseigner le votre clé SSH privée"}}}}]}}};
|
|
8
8
|
|
|
9
9
|
function validate14(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){
|
|
10
|
-
/*# sourceURL="https://github.com/data-fair/catalog-
|
|
10
|
+
/*# sourceURL="https://github.com/data-fair/catalog-sftp/catalog-config" */;
|
|
11
11
|
let vErrors = null;
|
|
12
12
|
let errors = 0;
|
|
13
13
|
if(data && typeof data == "object" && !Array.isArray(data)){
|
|
@@ -1,19 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://github.com/data-fair/catalog-
|
|
3
|
-
"x-exports": [
|
|
4
|
-
"types",
|
|
5
|
-
"validate",
|
|
6
|
-
"schema"
|
|
7
|
-
],
|
|
2
|
+
"$id": "https://github.com/data-fair/catalog-sftp/catalog-config",
|
|
3
|
+
"x-exports": ["types", "validate", "schema"],
|
|
8
4
|
"title": "SFTPConfig",
|
|
9
5
|
"type": "object",
|
|
10
6
|
"additionalProperties": false,
|
|
11
|
-
"required": [
|
|
12
|
-
"url",
|
|
13
|
-
"port",
|
|
14
|
-
"connectionKey",
|
|
15
|
-
"login"
|
|
16
|
-
],
|
|
7
|
+
"required": ["url", "port", "connectionKey", "login"],
|
|
17
8
|
"properties": {
|
|
18
9
|
"url": {
|
|
19
10
|
"type": "string",
|
|
@@ -22,9 +13,7 @@
|
|
|
22
13
|
"x-i18n-description": {
|
|
23
14
|
"fr": "L'adresse de l'hôte du catalogue (veuillez vous référez à la documentation technique du catalogue)"
|
|
24
15
|
},
|
|
25
|
-
"examples": [
|
|
26
|
-
"exemple-d-hote.fr"
|
|
27
|
-
]
|
|
16
|
+
"examples": ["exemple-d-hote.fr"]
|
|
28
17
|
},
|
|
29
18
|
"port": {
|
|
30
19
|
"type": "integer",
|
|
@@ -48,20 +37,24 @@
|
|
|
48
37
|
"title": "Mode de connexion",
|
|
49
38
|
"description": "Le mode de connexion à utiliser (Mot de passe, clé SSH)",
|
|
50
39
|
"oneOfLayout": {
|
|
51
|
-
"label": "
|
|
40
|
+
"label": "Choisir un mode de connexion"
|
|
52
41
|
},
|
|
53
42
|
"oneOf": [
|
|
54
43
|
{
|
|
55
44
|
"title": "Mot de Passe",
|
|
56
|
-
"required": [
|
|
57
|
-
"password"
|
|
58
|
-
],
|
|
45
|
+
"required": ["password"],
|
|
59
46
|
"properties": {
|
|
60
47
|
"password": {
|
|
61
48
|
"type": "string",
|
|
62
49
|
"description": "Enter your account password for the remote server",
|
|
63
50
|
"x-i18n-description": {
|
|
64
51
|
"fr": "Renseigner le mot de passe associé à votre compte sur le serveur distant"
|
|
52
|
+
},
|
|
53
|
+
"layout": {
|
|
54
|
+
"props": {
|
|
55
|
+
"type": "password",
|
|
56
|
+
"autocomplete": "new-password"
|
|
57
|
+
}
|
|
65
58
|
}
|
|
66
59
|
},
|
|
67
60
|
"key": {
|
|
@@ -71,9 +64,7 @@
|
|
|
71
64
|
},
|
|
72
65
|
{
|
|
73
66
|
"title": "Clé SHH",
|
|
74
|
-
"required": [
|
|
75
|
-
"sshKey"
|
|
76
|
-
],
|
|
67
|
+
"required": ["sshKey"],
|
|
77
68
|
"properties": {
|
|
78
69
|
"key": {
|
|
79
70
|
"const": "sshKey"
|
|
@@ -91,4 +82,4 @@
|
|
|
91
82
|
]
|
|
92
83
|
}
|
|
93
84
|
}
|
|
94
|
-
}
|
|
85
|
+
}
|