@data-fair/catalog-sftp 0.3.0 → 0.3.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.
package/index.ts CHANGED
@@ -1,36 +1,15 @@
1
1
  import type { CatalogPlugin } from '@data-fair/types-catalogs'
2
2
  import { type SFTPConfig, configSchema, assertConfigValid } from '#types'
3
- import capabilities from './lib/capabilities.ts'
3
+ import capabilities, { type SFTPCapabilities } from './lib/capabilities.ts'
4
4
 
5
5
  // Since the plugin is very frequently imported, each function is imported on demand,
6
6
  // instead of loading the entire plugin.
7
7
  // This file should not contain any code, but only constants and dynamic imports of functions.
8
8
 
9
- const plugin: CatalogPlugin<SFTPConfig, typeof capabilities> = {
10
- async prepare ({ catalogConfig, secrets }: { catalogConfig: SFTPConfig, secrets: Record<string, string> }) {
11
- switch (catalogConfig.connectionKey.key) {
12
- case 'sshKey':
13
- if (secrets?.sshKey && catalogConfig.connectionKey.sshKey === '') {
14
- delete secrets.sshKey
15
- } else {
16
- secrets.sshKey = catalogConfig.connectionKey.sshKey
17
- catalogConfig.connectionKey.sshKey = '********'
18
- }
19
- break
20
- case 'password':
21
- if (secrets?.password && catalogConfig.connectionKey.password === '') {
22
- delete secrets.password
23
- } else {
24
- secrets.password = catalogConfig.connectionKey.password
25
- catalogConfig.connectionKey.password = '********'
26
- }
27
- break
28
- default: break
29
- }
30
- return {
31
- catalogConfig,
32
- secrets
33
- }
9
+ const plugin: CatalogPlugin<SFTPConfig, SFTPCapabilities> = {
10
+ async prepare (context) {
11
+ const prepare = (await import('./lib/prepare.ts')).default
12
+ return prepare(context)
34
13
  },
35
14
 
36
15
  async list (context) {
@@ -1,9 +1,13 @@
1
+ import type { Capability } from '@data-fair/types-catalogs'
2
+
1
3
  /**
2
4
  * The list of capabilities of the plugin.
3
5
  * These capabilities define the actions that can be performed with the plugin.
4
- * We add "as const" to ensure the type is a list of literal type, not a list of strings.
5
- * This allows TypeScript to check if the plugin has the required funcitons for each capability.
6
+ * The capabilities must satisfy the `Capability` type.
6
7
  */
7
- export default [
8
- 'import' as const,
9
- ]
8
+ export const capabilities = [
9
+ 'import',
10
+ ] satisfies Capability[]
11
+
12
+ export type SFTPCapabilities = typeof capabilities
13
+ export default capabilities
package/lib/download.ts CHANGED
@@ -21,7 +21,6 @@ export const getMetaData = async ({ catalogConfig, resourceId }: GetResourceCont
21
21
  id: resourceId,
22
22
  title: resourceId.substring(resourceId.lastIndexOf('/') + 1),
23
23
  format: (pointPos === -1) ? '' : (resourceId.substring(pointPos + 1)),
24
- origin: catalogConfig.url + ':' + catalogConfig.port,
25
24
  filePath: ''
26
25
  }
27
26
  }
package/lib/imports.ts CHANGED
@@ -1,28 +1,11 @@
1
1
  import type { SFTPConfig } from '#types'
2
- import type { FileEntryWithStats, SFTPWrapper } from 'ssh2'
2
+ import type { FileEntryWithStats } from 'ssh2'
3
3
  import type capabilities from './capabilities.ts'
4
4
  import type { ListContext, Folder, CatalogPlugin } from '@data-fair/types-catalogs'
5
5
  import { type Config, NodeSSH } from 'node-ssh'
6
6
 
7
7
  type ResourceList = Awaited<ReturnType<CatalogPlugin['list']>>['results']
8
8
 
9
- /**
10
- * Stores the most recently used SFTP configuration.
11
- * This variable holds the last SFTPConfig object that was used,
12
- * allowing for reuse or reference in subsequent SFTP operations.
13
- */
14
- let lastConfig: SFTPConfig | undefined
15
- let lastSecrets: Record<string, string>
16
-
17
- /**
18
- * Store the ssh instance for SFTP operations.
19
- */
20
- const ssh = new NodeSSH()
21
- /**
22
- * SFTP client instance used for managing SFTP operations.
23
- */
24
- let clientSFTP: SFTPWrapper
25
-
26
9
  /**
27
10
  * Prepares a list of files and folders from the SFTP directory listing.
28
11
  *
@@ -48,7 +31,6 @@ const prepareFiles = (list: FileEntryWithStats[], path: string): (Folder[] | Res
48
31
  description: '',
49
32
  format: (pointPos === -1) ? '' : (file.filename.substring(pointPos + 1)),
50
33
  mimeType: '',
51
- origin: path + '/' + file.filename,
52
34
  size: file.attrs.size,
53
35
  type: 'resource'
54
36
  } as ResourceList[number]
@@ -64,37 +46,33 @@ const prepareFiles = (list: FileEntryWithStats[], path: string): (Folder[] | Res
64
46
  * @throws Will throw an error if the connection configuration is invalid or not supported.
65
47
  */
66
48
  export const list = async ({ catalogConfig, secrets, params }: ListContext<SFTPConfig, typeof capabilities>): ReturnType<CatalogPlugin['list']> => {
67
- if (!(lastConfig && ssh && clientSFTP) ||
68
- JSON.stringify(lastConfig) !== JSON.stringify(catalogConfig) ||
69
- JSON.stringify(lastSecrets) !== JSON.stringify(secrets)) {
70
- lastConfig = catalogConfig
71
- lastSecrets = secrets
72
- const paramsConnection: Config = {
73
- host: catalogConfig.url,
74
- username: catalogConfig.login,
75
- port: catalogConfig.port
76
- }
77
- if (catalogConfig.connectionKey.key === 'sshKey') {
78
- paramsConnection.privateKey = secrets.sshKey
79
- } else if (catalogConfig.connectionKey.key === 'password') {
80
- paramsConnection.password = secrets.password
81
- } else {
82
- throw new Error('format non pris en charge')
83
- }
49
+ const paramsConnection: Config = {
50
+ host: catalogConfig.url,
51
+ username: catalogConfig.login,
52
+ port: catalogConfig.port
53
+ }
54
+ if (catalogConfig.connectionKey.key === 'sshKey') {
55
+ paramsConnection.privateKey = secrets.sshKey
56
+ } else if (catalogConfig.connectionKey.key === 'password') {
57
+ paramsConnection.password = secrets.password
58
+ } else {
59
+ throw new Error('format non pris en charge')
60
+ }
84
61
 
85
- try {
86
- await ssh.connect(paramsConnection)
87
- } catch (err) {
88
- console.error(err)
89
- lastConfig = undefined
90
- throw new Error('Configuration invalide')
91
- }
92
- clientSFTP = await ssh.requestSFTP()
62
+ const ssh = new NodeSSH()
63
+
64
+ try {
65
+ await ssh.connect(paramsConnection)
66
+ } catch (err) {
67
+ console.error(err)
68
+ throw new Error('Configuration invalide')
93
69
  }
70
+ const clientSFTP = await ssh.requestSFTP()
71
+
94
72
  const path = params.currentFolderId ?? '.'
95
73
  const files: FileEntryWithStats[] = await new Promise((resolve, reject) => {
96
74
  if (!clientSFTP) {
97
- throw new Error('Configuration invalide')
75
+ throw new Error('Configuration invalide (clientSFTP manquant)')
98
76
  }
99
77
  clientSFTP.readdir(path, (err: any, list: any) => {
100
78
  if (err) {
package/lib/prepare.ts ADDED
@@ -0,0 +1,56 @@
1
+ import type { SFTPConfig } from '#types'
2
+ import type { PrepareContext } from '@data-fair/types-catalogs'
3
+ import type { SFTPCapabilities } from './capabilities.ts'
4
+ import { type Config, NodeSSH } from 'node-ssh'
5
+
6
+ export default async ({ catalogConfig, secrets }: PrepareContext<SFTPConfig, SFTPCapabilities>) => {
7
+ switch (catalogConfig.connectionKey.key) {
8
+ case 'sshKey':
9
+ delete secrets.password
10
+ if (catalogConfig.connectionKey.sshKey === '') {
11
+ delete secrets.sshKey
12
+ } else if (catalogConfig.connectionKey.sshKey && catalogConfig.connectionKey.sshKey !== '********') {
13
+ secrets.sshKey = catalogConfig.connectionKey.sshKey
14
+ catalogConfig.connectionKey.sshKey = '********'
15
+ }
16
+ break
17
+ case 'password':
18
+ delete secrets.sshKey
19
+ if (catalogConfig.connectionKey.password === '') {
20
+ delete secrets.password
21
+ } else if (catalogConfig.connectionKey.password && catalogConfig.connectionKey.password !== '********') {
22
+ secrets.password = catalogConfig.connectionKey.password
23
+ catalogConfig.connectionKey.password = '********'
24
+ }
25
+ break
26
+ default: break
27
+ }
28
+
29
+ // try the SFTP connection
30
+ try {
31
+ const paramsConnection: Config = {
32
+ host: catalogConfig.url,
33
+ username: catalogConfig.login,
34
+ port: catalogConfig.port
35
+ }
36
+ if (catalogConfig.connectionKey.key === 'sshKey') {
37
+ paramsConnection.privateKey = secrets.sshKey
38
+ } else if (catalogConfig.connectionKey.key === 'password') {
39
+ paramsConnection.password = secrets.password
40
+ } else {
41
+ throw new Error('format non pris en charge')
42
+ }
43
+
44
+ const ssh = new NodeSSH()
45
+ await ssh.connect(paramsConnection)
46
+ ssh.dispose()
47
+ } catch (error) {
48
+ console.error('Connection test failed:', error)
49
+ throw new Error('Connection test failed', { cause: error })
50
+ }
51
+
52
+ return {
53
+ catalogConfig,
54
+ secrets
55
+ }
56
+ }
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.3.0",
4
+ "version": "0.3.2",
5
5
  "main": "index.ts",
6
6
  "type": "module",
7
7
  "scripts": {
@@ -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": "Chosir un mode de connexion"
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,7 +4,7 @@
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-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":"Chosir 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"}},"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"}}}}]}}};
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
10
  /*# sourceURL="https://github.com/data-fair/catalog-sftp/catalog-config" */;
@@ -1,19 +1,10 @@
1
1
  {
2
2
  "$id": "https://github.com/data-fair/catalog-sftp/catalog-config",
3
- "x-exports": [
4
- "types",
5
- "validate",
6
- "schema"
7
- ],
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": "Chosir un mode de connexion"
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
+ }