@data-fair/catalog-sftp 0.1.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.
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # <img alt="Data FAIR logo" src="https://cdn.jsdelivr.net/gh/data-fair/data-fair@master/ui/public/assets/logo.svg" width="40"> @data-fair/catalog-sftp
2
+
3
+ SFTP plugin for the Data Fair catalogs service.
package/index.ts ADDED
@@ -0,0 +1,59 @@
1
+ import type { CatalogPlugin } from '@data-fair/lib-common-types/catalog/index.js'
2
+ import { type SFTPConfig, configSchema, assertConfigValid } from '#types'
3
+ import capabilities from './lib/capabilities.ts'
4
+
5
+ // Since the plugin is very frequently imported, each function is imported on demand,
6
+ // instead of loading the entire plugin.
7
+ // This file should not contain any code, but only constants and dynamic imports of functions.
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
+ }
34
+ },
35
+
36
+ async list (context) {
37
+ const { list } = await import('./lib/imports.ts')
38
+ return list(context)
39
+ },
40
+
41
+ async getResource (context) {
42
+ const { getResource } = await import('./lib/imports.ts')
43
+ return getResource(context)
44
+ },
45
+
46
+ async downloadResource (context) {
47
+ const { downloadResource } = await import('./lib/download.ts')
48
+ return downloadResource(context)
49
+ },
50
+
51
+ metadata: {
52
+ title: 'Catalog SFTP',
53
+ description: 'SFTP plugin for Data Fair Catalog',
54
+ capabilities
55
+ },
56
+ configSchema,
57
+ assertConfigValid
58
+ }
59
+ export default plugin
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The list of capabilities of the plugin.
3
+ * 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
+ */
7
+ export default [
8
+ 'import' as const,
9
+ ]
@@ -0,0 +1,48 @@
1
+ import type { DownloadResourceContext } from '@data-fair/lib-common-types/catalog/index.js'
2
+ import type { SFTPConfig } from '#types'
3
+ import { type Config, NodeSSH } from 'node-ssh'
4
+
5
+ /**
6
+ * Downloads a resource (file) from the SFTP server to a temporary directory.
7
+ *
8
+ * @param context - The context containing catalog configuration, resource ID, import configuration, and temporary directory path.
9
+ * @returns The local path to the downloaded file, or `undefined` if the download fails.
10
+ * @throws Will throw an error if the connection configuration is invalid or not supported.
11
+ */
12
+ export const downloadResource = async ({ catalogConfig, resourceId, secrets, tmpDir }: DownloadResourceContext<SFTPConfig>) => {
13
+ const ssh = new NodeSSH()
14
+
15
+ const paramsConnection: Config = {
16
+ host: catalogConfig.url,
17
+ username: catalogConfig.login,
18
+ port: catalogConfig.port
19
+ }
20
+ if (catalogConfig.connectionKey.key === 'sshKey') {
21
+ paramsConnection.privateKey = secrets.sshKey
22
+ } else if (catalogConfig.connectionKey.key === 'password') {
23
+ paramsConnection.password = secrets.password
24
+ } else {
25
+ throw new Error('format non pris en charge')
26
+ }
27
+
28
+ try {
29
+ await ssh.connect(paramsConnection)
30
+ } catch (err) {
31
+ throw new Error('Configuration invalide')
32
+ }
33
+
34
+ const fs = await import('node:fs/promises')
35
+ resourceId = resourceId.substring(resourceId.indexOf('./') + 2)
36
+ const destinationPath = tmpDir + '/' + resourceId
37
+
38
+ // creation du dossier pour stocker le fichier distant
39
+ await fs.mkdir(destinationPath.substring(0, destinationPath.lastIndexOf('/')), { recursive: true })
40
+
41
+ try {
42
+ await ssh.getFile(destinationPath, resourceId)
43
+ return destinationPath
44
+ } catch (error) {
45
+ console.error('Error downloading file:', error)
46
+ throw error
47
+ }
48
+ }
package/lib/imports.ts ADDED
@@ -0,0 +1,129 @@
1
+ import type { SFTPConfig } from '#types'
2
+ import type { SFTPWrapper } from 'ssh2'
3
+ import type capabilities from './capabilities.ts'
4
+ import type { ListContext, Folder, Resource, GetResourceContext } from '@data-fair/lib-common-types/catalog/index.js'
5
+ import { type Config, NodeSSH } from 'node-ssh'
6
+
7
+ /**
8
+ * Stores the most recently used SFTP configuration.
9
+ * This variable holds the last SFTPConfig object that was used,
10
+ * allowing for reuse or reference in subsequent SFTP operations.
11
+ */
12
+ let lastConfig: SFTPConfig | undefined
13
+ let lastSecrets: Record<string, string>
14
+
15
+ /**
16
+ * Store the ssh instance for SFTP operations.
17
+ */
18
+ const ssh = new NodeSSH()
19
+ /**
20
+ * SFTP client instance used for managing SFTP operations.
21
+ */
22
+ let clientSFTP: SFTPWrapper
23
+
24
+ /**
25
+ * Prepares a list of files and folders from the SFTP directory listing.
26
+ *
27
+ * @param list - The array of file objects returned by the SFTP `readdir` method.
28
+ * @param path - The current directory path.
29
+ * @returns An array of `Folder` or `Resource` objects representing the files and folders.
30
+ */
31
+ const prepareFiles = (list: any[], path: string): (Folder | Resource)[] => {
32
+ return list.map((file) => {
33
+ const pointPos = file.filename.lastIndexOf('.')
34
+ return {
35
+ id: path + '/' + file.filename,
36
+ title: file.filename,
37
+ type: (file.longname.charAt(0) === 'd') ? 'folder' : 'resource',
38
+ url: path + '/' + file.filename,
39
+ format: (pointPos === -1) ? '' : (file.filename.substring(pointPos + 1))
40
+ }
41
+ })
42
+ }
43
+
44
+ /**
45
+ * Lists the contents of a folder on an SFTP server.
46
+ *
47
+ * @param context - The context containing catalog configuration and parameters.
48
+ * @returns An object containing the count of items, the list of results (folders and resources), and the path as an array of folders.
49
+ * @throws Will throw an error if the connection configuration is invalid or not supported.
50
+ */
51
+ export const list = async ({ catalogConfig, secrets, params }: ListContext<SFTPConfig, typeof capabilities>): Promise<{ count: number; results: (Folder | Resource)[]; path: Folder[] }> => {
52
+ if (!(lastConfig && ssh && clientSFTP) ||
53
+ JSON.stringify(lastConfig) !== JSON.stringify(catalogConfig) ||
54
+ JSON.stringify(lastSecrets) !== JSON.stringify(secrets)) {
55
+ lastConfig = catalogConfig
56
+ lastSecrets = secrets
57
+ const paramsConnection: Config = {
58
+ host: catalogConfig.url,
59
+ username: catalogConfig.login,
60
+ port: catalogConfig.port
61
+ }
62
+ if (catalogConfig.connectionKey.key === 'sshKey') {
63
+ paramsConnection.privateKey = secrets.sshKey
64
+ } else if (catalogConfig.connectionKey.key === 'password') {
65
+ paramsConnection.password = secrets.password
66
+ } else {
67
+ throw new Error('format non pris en charge')
68
+ }
69
+
70
+ try {
71
+ await ssh.connect(paramsConnection)
72
+ } catch (err) {
73
+ console.error(err)
74
+ lastConfig = undefined
75
+ throw new Error('Configuration invalide')
76
+ }
77
+ clientSFTP = await ssh.requestSFTP()
78
+ }
79
+ const path = params.currentFolderId ?? '.'
80
+ const files: any[] = await new Promise((resolve, reject) => {
81
+ if (!clientSFTP) {
82
+ throw new Error('Configuration invalide')
83
+ }
84
+ clientSFTP.readdir(path, (err: any, list: any) => {
85
+ if (err) {
86
+ console.error('Error reading directory:', err)
87
+ return reject(err)
88
+ }
89
+ resolve(list)
90
+ })
91
+ })
92
+
93
+ const results = prepareFiles(files, path)
94
+
95
+ const pathFolder: Folder[] = []
96
+ let parentId: string | undefined = (params.currentFolderId?.indexOf('./')) === -1 ? params.currentFolderId : params.currentFolderId?.substring(params.currentFolderId.indexOf('./') + 2)
97
+ while (parentId && parentId !== '') {
98
+ pathFolder.unshift({
99
+ id: parentId,
100
+ title: parentId.substring(parentId.lastIndexOf('/') + 1),
101
+ type: 'folder'
102
+ })
103
+ parentId = parentId.substring(0, parentId.lastIndexOf('/'))
104
+ }
105
+
106
+ return {
107
+ count: results.length,
108
+ results,
109
+ path: pathFolder
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Retrieves metadata for a specific resource (file) on the SFTP server.
115
+ *
116
+ * @param catalogConfig - The SFTP configuration object.
117
+ * @param resourceId - The identifier (path) of the resource.
118
+ * @returns A `Resource` object representing the file.
119
+ */
120
+ export const getResource = async ({ catalogConfig, secrets, resourceId }: GetResourceContext<SFTPConfig>): Promise<Resource> => {
121
+ const pointPos = resourceId.lastIndexOf('.')
122
+ return {
123
+ id: resourceId,
124
+ title: resourceId.substring(resourceId.lastIndexOf('/') + 1),
125
+ type: 'resource',
126
+ format: (pointPos === -1) ? '' : (resourceId.substring(pointPos + 1)),
127
+ url: resourceId
128
+ }
129
+ }
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@data-fair/catalog-sftp",
3
+ "description": "SFTP plugin for the Data Fair catalogs service.",
4
+ "version": "0.1.0",
5
+ "main": "index.ts",
6
+ "type": "module",
7
+ "scripts": {
8
+ "build-types": "df-build-types ./",
9
+ "check-types": "tsc",
10
+ "lint": "eslint .",
11
+ "prepare": "husky || true",
12
+ "test-base": "NODE_ENV=test EVENTS_LOG_LEVEL=alert node --disable-warning=ExperimentalWarning --test-force-exit --test-concurrency=1 --test",
13
+ "test-only": "npm run test-base -- --test-only test-it/*.ts",
14
+ "test": "npm run test-base test-it/*.ts",
15
+ "quality": "npm run lint && npm run build-types && npm run check-types && npm run test && npm audit --omit=dev --audit-level=critical",
16
+ "prepublishOnly": "npm run build-types"
17
+ },
18
+ "files": [
19
+ "./lib/**",
20
+ "./types/**",
21
+ "index.ts"
22
+ ],
23
+ "imports": {
24
+ "#types": "./types/index.ts",
25
+ "#type/*": "./types/*"
26
+ },
27
+ "keywords": [
28
+ "data-fair-catalogs-plugin"
29
+ ],
30
+ "license": "MIT",
31
+ "dependencies": {
32
+ "@data-fair/lib-node": "^2.8.1",
33
+ "@data-fair/lib-utils": "^1.6.0",
34
+ "debug": "^4.4.1",
35
+ "fs-extra": "^11.3.0",
36
+ "prom-client": "^15.1.3"
37
+ },
38
+ "devDependencies": {
39
+ "@commitlint/cli": "^19.8.0",
40
+ "@commitlint/config-conventional": "^19.8.0",
41
+ "@data-fair/lib-common-types": "^1.11.0",
42
+ "@data-fair/lib-types-builder": "^1.8.0",
43
+ "@types/debug": "^4.1.12",
44
+ "@types/fs-extra": "^11.0.4",
45
+ "@types/node": "^24.0.3",
46
+ "@types/ssh2": "^1.15.5",
47
+ "eslint": "^9.25.1",
48
+ "husky": "^9.1.7",
49
+ "neostandard": "^0.12.1",
50
+ "node-ssh": "^13.2.1",
51
+ "typescript": "^5.8.3"
52
+ },
53
+ "relativeDependencies": {
54
+ "@data-fair/lib-common-types": "../../lib/packages/common-types"
55
+ }
56
+ }
@@ -0,0 +1,51 @@
1
+
2
+ export const schemaExports: string[]
3
+
4
+ // see https://github.com/bcherny/json-schema-to-typescript/issues/439 if some types are not exported
5
+ /**
6
+ * The host adress
7
+ */
8
+ export type AdresseDeLHote = string;
9
+ /**
10
+ * The port of the catalog
11
+ */
12
+ export type Port = number;
13
+ /**
14
+ * The user login
15
+ */
16
+ export type Identifiant = string;
17
+ /**
18
+ * Le mode de connexion à utiliser (Mot de passe, clé SSH)
19
+ */
20
+ export type ModeDeConnexion = MotDePasse | CleSHH;
21
+
22
+ export type SFTPConfig = {
23
+ url: AdresseDeLHote;
24
+ port: Port;
25
+ login: Identifiant;
26
+ connectionKey: ModeDeConnexion;
27
+ }
28
+ export type MotDePasse = {
29
+ /**
30
+ * Enter your account password for the remote server
31
+ */
32
+ password: string;
33
+ key?: "password";
34
+ [k: string]: unknown;
35
+ }
36
+ export type CleSHH = {
37
+ key?: "sshKey";
38
+ /**
39
+ * Enter your ssh key
40
+ */
41
+ sshKey: string;
42
+ [k: string]: unknown;
43
+ }
44
+
45
+
46
+ export declare function validate(data: any): data is SftpConfig
47
+ export declare function assertValid(data: any, options?: import('@data-fair/lib-validation').AssertValidOptions): asserts data is SftpConfig
48
+ export declare function returnValid(data: any, options?: import('@data-fair/lib-validation').AssertValidOptions): SftpConfig
49
+
50
+ export declare const schema: any
51
+
@@ -0,0 +1,115 @@
1
+ /* eslint-disable */
2
+
3
+
4
+ import validate from './validate.js'
5
+ import { assertValid as assertValidGeneric } from '@data-fair/lib-validation'
6
+
7
+ export const schemaExports = [
8
+ "types",
9
+ "validate",
10
+ "schema"
11
+ ]
12
+
13
+ export { validate } from './validate.js'
14
+ export function assertValid(data, options) {
15
+ assertValidGeneric(validate, data, options)
16
+ }
17
+ export function returnValid(data, options) {
18
+ assertValid(data, options)
19
+ return data
20
+ }
21
+
22
+ export const schema = {
23
+ "$id": "https://github.com/data-fair/catalog-udata/catalog-config",
24
+ "x-exports": [
25
+ "types",
26
+ "validate",
27
+ "schema"
28
+ ],
29
+ "title": "SFTPConfig",
30
+ "type": "object",
31
+ "additionalProperties": false,
32
+ "required": [
33
+ "url",
34
+ "port",
35
+ "connectionKey",
36
+ "login"
37
+ ],
38
+ "properties": {
39
+ "url": {
40
+ "type": "string",
41
+ "title": "Adresse de l'hôte",
42
+ "description": "The host adress",
43
+ "x-i18n-description": {
44
+ "fr": "L'adresse de l'hôte du catalogue (veuillez vous référez à la documentation technique du catalogue)"
45
+ },
46
+ "examples": [
47
+ "exemple-d-hote.fr"
48
+ ]
49
+ },
50
+ "port": {
51
+ "type": "integer",
52
+ "title": "port",
53
+ "description": "The port of the catalog",
54
+ "x-i18n-description": {
55
+ "fr": "Le port de l'API du catalogue (veuillez vous référez à la documentation technique du catalogue)"
56
+ },
57
+ "default": 22
58
+ },
59
+ "login": {
60
+ "type": "string",
61
+ "title": "Identifiant",
62
+ "description": "The user login",
63
+ "x-i18n-description": {
64
+ "fr": "L'identifiant (login) utilisé pour accéder au catalogue"
65
+ }
66
+ },
67
+ "connectionKey": {
68
+ "type": "object",
69
+ "title": "Mode de connexion",
70
+ "description": "Le mode de connexion à utiliser (Mot de passe, clé SSH)",
71
+ "oneOfLayout": {
72
+ "label": "Chosir un mode de connexion"
73
+ },
74
+ "oneOf": [
75
+ {
76
+ "title": "Mot de Passe",
77
+ "required": [
78
+ "password"
79
+ ],
80
+ "properties": {
81
+ "password": {
82
+ "type": "string",
83
+ "description": "Enter your account password for the remote server",
84
+ "x-i18n-description": {
85
+ "fr": "Renseigner le mot de passe associé à votre compte sur le serveur distant"
86
+ }
87
+ },
88
+ "key": {
89
+ "const": "password"
90
+ }
91
+ }
92
+ },
93
+ {
94
+ "title": "Clé SHH",
95
+ "required": [
96
+ "sshKey"
97
+ ],
98
+ "properties": {
99
+ "key": {
100
+ "const": "sshKey"
101
+ },
102
+ "sshKey": {
103
+ "type": "string",
104
+ "layout": "textarea",
105
+ "description": "Enter your ssh key",
106
+ "x-i18n-description": {
107
+ "fr": "Renseigner le votre clé SSH privée"
108
+ }
109
+ }
110
+ }
111
+ }
112
+ ]
113
+ }
114
+ }
115
+ }
@@ -0,0 +1,243 @@
1
+ /* eslint-disable */
2
+ // @ts-nocheck
3
+
4
+ "use strict";
5
+ export const validate = validate14;
6
+ export default validate14;
7
+ const schema16 = {"$id":"https://github.com/data-fair/catalog-udata/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"}}}}]}}};
8
+
9
+ function validate14(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){
10
+ /*# sourceURL="https://github.com/data-fair/catalog-udata/catalog-config" */;
11
+ let vErrors = null;
12
+ let errors = 0;
13
+ if(data && typeof data == "object" && !Array.isArray(data)){
14
+ if(data.url === undefined){
15
+ const err0 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "url"},message:"must have required property '"+"url"+"'"};
16
+ if(vErrors === null){
17
+ vErrors = [err0];
18
+ }
19
+ else {
20
+ vErrors.push(err0);
21
+ }
22
+ errors++;
23
+ }
24
+ if(data.port === undefined){
25
+ const err1 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "port"},message:"must have required property '"+"port"+"'"};
26
+ if(vErrors === null){
27
+ vErrors = [err1];
28
+ }
29
+ else {
30
+ vErrors.push(err1);
31
+ }
32
+ errors++;
33
+ }
34
+ if(data.connectionKey === undefined){
35
+ const err2 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "connectionKey"},message:"must have required property '"+"connectionKey"+"'"};
36
+ if(vErrors === null){
37
+ vErrors = [err2];
38
+ }
39
+ else {
40
+ vErrors.push(err2);
41
+ }
42
+ errors++;
43
+ }
44
+ if(data.login === undefined){
45
+ const err3 = {instancePath,schemaPath:"#/required",keyword:"required",params:{missingProperty: "login"},message:"must have required property '"+"login"+"'"};
46
+ if(vErrors === null){
47
+ vErrors = [err3];
48
+ }
49
+ else {
50
+ vErrors.push(err3);
51
+ }
52
+ errors++;
53
+ }
54
+ for(const key0 in data){
55
+ if(!((((key0 === "url") || (key0 === "port")) || (key0 === "login")) || (key0 === "connectionKey"))){
56
+ const err4 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"};
57
+ if(vErrors === null){
58
+ vErrors = [err4];
59
+ }
60
+ else {
61
+ vErrors.push(err4);
62
+ }
63
+ errors++;
64
+ }
65
+ }
66
+ if(data.url !== undefined){
67
+ if(typeof data.url !== "string"){
68
+ const err5 = {instancePath:instancePath+"/url",schemaPath:"#/properties/url/type",keyword:"type",params:{type: "string"},message:"must be string"};
69
+ if(vErrors === null){
70
+ vErrors = [err5];
71
+ }
72
+ else {
73
+ vErrors.push(err5);
74
+ }
75
+ errors++;
76
+ }
77
+ }
78
+ if(data.port !== undefined){
79
+ let data1 = data.port;
80
+ if(!((typeof data1 == "number") && (!(data1 % 1) && !isNaN(data1)))){
81
+ const err6 = {instancePath:instancePath+"/port",schemaPath:"#/properties/port/type",keyword:"type",params:{type: "integer"},message:"must be integer"};
82
+ if(vErrors === null){
83
+ vErrors = [err6];
84
+ }
85
+ else {
86
+ vErrors.push(err6);
87
+ }
88
+ errors++;
89
+ }
90
+ }
91
+ if(data.login !== undefined){
92
+ if(typeof data.login !== "string"){
93
+ const err7 = {instancePath:instancePath+"/login",schemaPath:"#/properties/login/type",keyword:"type",params:{type: "string"},message:"must be string"};
94
+ if(vErrors === null){
95
+ vErrors = [err7];
96
+ }
97
+ else {
98
+ vErrors.push(err7);
99
+ }
100
+ errors++;
101
+ }
102
+ }
103
+ if(data.connectionKey !== undefined){
104
+ let data3 = data.connectionKey;
105
+ if(!(data3 && typeof data3 == "object" && !Array.isArray(data3))){
106
+ const err8 = {instancePath:instancePath+"/connectionKey",schemaPath:"#/properties/connectionKey/type",keyword:"type",params:{type: "object"},message:"must be object"};
107
+ if(vErrors === null){
108
+ vErrors = [err8];
109
+ }
110
+ else {
111
+ vErrors.push(err8);
112
+ }
113
+ errors++;
114
+ }
115
+ const _errs10 = errors;
116
+ let valid1 = false;
117
+ let passing0 = null;
118
+ const _errs11 = errors;
119
+ if(data3 && typeof data3 == "object" && !Array.isArray(data3)){
120
+ if(data3.password === undefined){
121
+ const err9 = {instancePath:instancePath+"/connectionKey",schemaPath:"#/properties/connectionKey/oneOf/0/required",keyword:"required",params:{missingProperty: "password"},message:"must have required property '"+"password"+"'"};
122
+ if(vErrors === null){
123
+ vErrors = [err9];
124
+ }
125
+ else {
126
+ vErrors.push(err9);
127
+ }
128
+ errors++;
129
+ }
130
+ if(data3.password !== undefined){
131
+ if(typeof data3.password !== "string"){
132
+ const err10 = {instancePath:instancePath+"/connectionKey/password",schemaPath:"#/properties/connectionKey/oneOf/0/properties/password/type",keyword:"type",params:{type: "string"},message:"must be string"};
133
+ if(vErrors === null){
134
+ vErrors = [err10];
135
+ }
136
+ else {
137
+ vErrors.push(err10);
138
+ }
139
+ errors++;
140
+ }
141
+ }
142
+ if(data3.key !== undefined){
143
+ if("password" !== data3.key){
144
+ const err11 = {instancePath:instancePath+"/connectionKey/key",schemaPath:"#/properties/connectionKey/oneOf/0/properties/key/const",keyword:"const",params:{allowedValue: "password"},message:"must be equal to constant"};
145
+ if(vErrors === null){
146
+ vErrors = [err11];
147
+ }
148
+ else {
149
+ vErrors.push(err11);
150
+ }
151
+ errors++;
152
+ }
153
+ }
154
+ }
155
+ var _valid0 = _errs11 === errors;
156
+ if(_valid0){
157
+ valid1 = true;
158
+ passing0 = 0;
159
+ }
160
+ const _errs15 = errors;
161
+ if(data3 && typeof data3 == "object" && !Array.isArray(data3)){
162
+ if(data3.sshKey === undefined){
163
+ const err12 = {instancePath:instancePath+"/connectionKey",schemaPath:"#/properties/connectionKey/oneOf/1/required",keyword:"required",params:{missingProperty: "sshKey"},message:"must have required property '"+"sshKey"+"'"};
164
+ if(vErrors === null){
165
+ vErrors = [err12];
166
+ }
167
+ else {
168
+ vErrors.push(err12);
169
+ }
170
+ errors++;
171
+ }
172
+ if(data3.key !== undefined){
173
+ if("sshKey" !== data3.key){
174
+ const err13 = {instancePath:instancePath+"/connectionKey/key",schemaPath:"#/properties/connectionKey/oneOf/1/properties/key/const",keyword:"const",params:{allowedValue: "sshKey"},message:"must be equal to constant"};
175
+ if(vErrors === null){
176
+ vErrors = [err13];
177
+ }
178
+ else {
179
+ vErrors.push(err13);
180
+ }
181
+ errors++;
182
+ }
183
+ }
184
+ if(data3.sshKey !== undefined){
185
+ if(typeof data3.sshKey !== "string"){
186
+ const err14 = {instancePath:instancePath+"/connectionKey/sshKey",schemaPath:"#/properties/connectionKey/oneOf/1/properties/sshKey/type",keyword:"type",params:{type: "string"},message:"must be string"};
187
+ if(vErrors === null){
188
+ vErrors = [err14];
189
+ }
190
+ else {
191
+ vErrors.push(err14);
192
+ }
193
+ errors++;
194
+ }
195
+ }
196
+ }
197
+ var _valid0 = _errs15 === errors;
198
+ if(_valid0 && valid1){
199
+ valid1 = false;
200
+ passing0 = [passing0, 1];
201
+ }
202
+ else {
203
+ if(_valid0){
204
+ valid1 = true;
205
+ passing0 = 1;
206
+ }
207
+ }
208
+ if(!valid1){
209
+ const err15 = {instancePath:instancePath+"/connectionKey",schemaPath:"#/properties/connectionKey/oneOf",keyword:"oneOf",params:{passingSchemas: passing0},message:"must match exactly one schema in oneOf"};
210
+ if(vErrors === null){
211
+ vErrors = [err15];
212
+ }
213
+ else {
214
+ vErrors.push(err15);
215
+ }
216
+ errors++;
217
+ }
218
+ else {
219
+ errors = _errs10;
220
+ if(vErrors !== null){
221
+ if(_errs10){
222
+ vErrors.length = _errs10;
223
+ }
224
+ else {
225
+ vErrors = null;
226
+ }
227
+ }
228
+ }
229
+ }
230
+ }
231
+ else {
232
+ const err16 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"};
233
+ if(vErrors === null){
234
+ vErrors = [err16];
235
+ }
236
+ else {
237
+ vErrors.push(err16);
238
+ }
239
+ errors++;
240
+ }
241
+ validate14.errors = vErrors;
242
+ return errors === 0;
243
+ }
@@ -0,0 +1 @@
1
+ export * from './.type/index.js'
@@ -0,0 +1,94 @@
1
+ {
2
+ "$id": "https://github.com/data-fair/catalog-udata/catalog-config",
3
+ "x-exports": [
4
+ "types",
5
+ "validate",
6
+ "schema"
7
+ ],
8
+ "title": "SFTPConfig",
9
+ "type": "object",
10
+ "additionalProperties": false,
11
+ "required": [
12
+ "url",
13
+ "port",
14
+ "connectionKey",
15
+ "login"
16
+ ],
17
+ "properties": {
18
+ "url": {
19
+ "type": "string",
20
+ "title": "Adresse de l'hôte",
21
+ "description": "The host adress",
22
+ "x-i18n-description": {
23
+ "fr": "L'adresse de l'hôte du catalogue (veuillez vous référez à la documentation technique du catalogue)"
24
+ },
25
+ "examples": [
26
+ "exemple-d-hote.fr"
27
+ ]
28
+ },
29
+ "port": {
30
+ "type": "integer",
31
+ "title": "port",
32
+ "description": "The port of the catalog",
33
+ "x-i18n-description": {
34
+ "fr": "Le port de l'API du catalogue (veuillez vous référez à la documentation technique du catalogue)"
35
+ },
36
+ "default": 22
37
+ },
38
+ "login": {
39
+ "type": "string",
40
+ "title": "Identifiant",
41
+ "description": "The user login",
42
+ "x-i18n-description": {
43
+ "fr": "L'identifiant (login) utilisé pour accéder au catalogue"
44
+ }
45
+ },
46
+ "connectionKey": {
47
+ "type": "object",
48
+ "title": "Mode de connexion",
49
+ "description": "Le mode de connexion à utiliser (Mot de passe, clé SSH)",
50
+ "oneOfLayout": {
51
+ "label": "Chosir un mode de connexion"
52
+ },
53
+ "oneOf": [
54
+ {
55
+ "title": "Mot de Passe",
56
+ "required": [
57
+ "password"
58
+ ],
59
+ "properties": {
60
+ "password": {
61
+ "type": "string",
62
+ "description": "Enter your account password for the remote server",
63
+ "x-i18n-description": {
64
+ "fr": "Renseigner le mot de passe associé à votre compte sur le serveur distant"
65
+ }
66
+ },
67
+ "key": {
68
+ "const": "password"
69
+ }
70
+ }
71
+ },
72
+ {
73
+ "title": "Clé SHH",
74
+ "required": [
75
+ "sshKey"
76
+ ],
77
+ "properties": {
78
+ "key": {
79
+ "const": "sshKey"
80
+ },
81
+ "sshKey": {
82
+ "type": "string",
83
+ "layout": "textarea",
84
+ "description": "Enter your ssh key",
85
+ "x-i18n-description": {
86
+ "fr": "Renseigner le votre clé SSH privée"
87
+ }
88
+ }
89
+ }
90
+ }
91
+ ]
92
+ }
93
+ }
94
+ }
package/types/index.ts ADDED
@@ -0,0 +1 @@
1
+ export { schema as configSchema, assertValid as assertConfigValid, type SFTPConfig } from './catalogConfig/index.ts'