@data-fair/catalog-data-fair 0.1.0 → 0.2.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/lib/download.ts CHANGED
@@ -4,6 +4,7 @@ import axios from '@data-fair/lib-node/axios.js'
4
4
  import * as fs from 'fs'
5
5
  import { join } from 'path'
6
6
  import { Transform } from 'stream'
7
+ import slugify from 'slugify'
7
8
 
8
9
  /**
9
10
  * Retrieves a resource by first fetching its metadata and then downloading the actual resource.
@@ -15,8 +16,8 @@ import { Transform } from 'stream'
15
16
  export const getResource = async (context: GetResourceContext<DataFairConfig>): ReturnType<CatalogPlugin['getResource']> => {
16
17
  context.log.step('Import de la ressource')
17
18
 
18
- const resource = await getMetaData(context)
19
- resource.filePath = await downloadResource(context, resource)
19
+ const { resource, file } = await getMetaData(context)
20
+ resource.filePath = await downloadResource(context, file, resource)
20
21
 
21
22
  return resource
22
23
  }
@@ -27,11 +28,12 @@ export const getResource = async (context: GetResourceContext<DataFairConfig>):
27
28
  * @param resourceId the dataset Id to fetch fields from
28
29
  * @returns the Resource corresponding to the id by this configuration
29
30
  */
30
- const getMetaData = async ({ catalogConfig, resourceId, log }: GetResourceContext<DataFairConfig>): Promise<Resource> => {
31
+ const getMetaData = async ({ catalogConfig, resourceId, log, secrets }: GetResourceContext<DataFairConfig>): Promise<{ resource: Resource, file: boolean }> => {
31
32
  let dataset: DataFairDataset
32
33
  try {
33
34
  const url = `${catalogConfig.url}/data-fair/api/v1/datasets/${resourceId}`
34
- const res = (await axios.get(url))
35
+ const config = secrets.apiKey ? { headers: { 'x-apiKey': secrets.apiKey } } : undefined
36
+ const res = (await axios.get(url, config))
35
37
  if (res.status !== 200) {
36
38
  throw new Error(`HTTP error : ${res.status}, ${res.data}`)
37
39
  }
@@ -42,16 +44,34 @@ const getMetaData = async ({ catalogConfig, resourceId, log }: GetResourceContex
42
44
  throw new Error(`Erreur lors de la récuperation de la resource DataFair. ${e instanceof Error ? e.message : e}`)
43
45
  }
44
46
 
47
+ dataset.schema = (dataset.schema ?? []).map((field) => {
48
+ if (field['x-extension']) {
49
+ return {
50
+ ...field,
51
+ key: slugify.default(field.key.replace(/^_/, ''), { lower: true, strict: true, replacement: '_' }), // Ensure no leading underscore
52
+ 'x-extension': undefined, // Remove x-extension property if it exists
53
+ }
54
+ }
55
+ return field
56
+ })
57
+
58
+ let size: number | undefined
59
+ if (dataset.storage?.dataFiles && dataset.storage.dataFiles.length > 0) {
60
+ // get the last elt of the array to get the /full file size
61
+ const lastFile = dataset.storage.dataFiles[dataset.storage.dataFiles.length - 1]
62
+ size = lastFile.size
63
+ }
64
+
45
65
  const resource: Resource = {
46
66
  id: resourceId,
47
67
  title: dataset.title,
48
68
  description: dataset.description,
49
69
  format: 'csv',
50
- origin: `${catalogConfig.url}/datasets/${resourceId}`,
70
+ origin: dataset.page,
51
71
  frequency: dataset.frequency,
52
72
  image: dataset.image,
53
73
  keywords: dataset.keywords,
54
- size: dataset.file?.size,
74
+ size,
55
75
  schema: dataset.schema,
56
76
  filePath: '',
57
77
  }
@@ -62,7 +82,8 @@ const getMetaData = async ({ catalogConfig, resourceId, log }: GetResourceContex
62
82
  href: dataset.license.href ?? '',
63
83
  }
64
84
  }
65
- return resource
85
+
86
+ return { resource, file: !!dataset.file }
66
87
  }
67
88
 
68
89
  /**
@@ -72,12 +93,14 @@ const getMetaData = async ({ catalogConfig, resourceId, log }: GetResourceContex
72
93
  * @param res - the metadatas about the resource.
73
94
  * @returns A promise resolving to the file path of the downloaded CSV.
74
95
  */
75
- const downloadResource = async (context: GetResourceContext<DataFairConfig>, res: Resource): Promise<string> => {
96
+ const downloadResource = async (context: GetResourceContext<DataFairConfig>, file: boolean, res: Resource): Promise<string> => {
76
97
  const filePath = join(context.tmpDir, `${context.resourceId}.csv`)
77
98
  try {
78
- if (res.size && res.size > 0 && context.importConfig.fields?.length === 0 && context.importConfig.filters?.length === 0) {
99
+ if (file && !context.importConfig.fields?.length && !context.importConfig.filters?.length) {
100
+ await context.log.task('downloading', 'Téléchargement en cours...', res.size || NaN)
79
101
  await downloadResourceFile(filePath, context)
80
102
  } else {
103
+ await context.log.task('downloading', 'Téléchargement en cours...', NaN)
81
104
  await downloadResourceLines(filePath, context)
82
105
  }
83
106
  return filePath
@@ -97,32 +120,54 @@ const downloadResource = async (context: GetResourceContext<DataFairConfig>, res
97
120
  * @returns A promise that resolves when the file is successfully downloaded and saved.
98
121
  * @throws If there is an error writing the file or fetching the dataset.
99
122
  */
100
- const downloadResourceFile = async (filePath: string, { catalogConfig, resourceId, log }: GetResourceContext<DataFairConfig>): Promise<void> => {
123
+ const downloadResourceFile = async (filePath: string, { catalogConfig, resourceId, log, secrets }: GetResourceContext<DataFairConfig>): Promise<void> => {
101
124
  const url = `${catalogConfig.url}/data-fair/api/v1/datasets/${resourceId}/full`
102
- log.info('Import des données de la ressource', url)
103
-
104
- const fileStream = fs.createWriteStream(filePath)
125
+ const headers = secrets.apiKey ? { 'x-apiKey': secrets.apiKey } : undefined
105
126
 
106
- const response = await axios.get(url, { responseType: 'stream' })
127
+ const response = await axios.get(url, { responseType: 'stream', headers })
107
128
 
108
129
  if (response.status !== 200) {
109
130
  throw new Error(`Error while fetching data: HTTP ${response.statusText}`)
110
131
  }
111
132
 
112
- return new Promise<void>((resolve, reject) => {
133
+ let downloaded = 0
134
+ let lastLogTime = Date.now()
135
+ const logInterval = 500 // ms
136
+
137
+ await new Promise<void>((resolve, reject) => {
138
+ const fileStream = fs.createWriteStream(filePath, { encoding: 'binary' }) // Ensure binary encoding
139
+
140
+ response.data.on('data', (chunk: Buffer) => {
141
+ downloaded += chunk.length
142
+ const now = Date.now()
143
+ if (now - lastLogTime > logInterval) {
144
+ lastLogTime = now
145
+ log.progress('downloading', downloaded)
146
+ .catch(err => console.warn('Progress logging failed:', err))
147
+ }
148
+ })
149
+
113
150
  response.data.pipe(fileStream)
151
+
114
152
  fileStream.on('finish', () => {
153
+ fileStream.close()
115
154
  resolve()
116
155
  })
156
+
117
157
  response.data.on('error', (err: any) => {
118
- fs.unlink(filePath, () => { }) // Delete the file in case of error
158
+ fileStream.destroy()
159
+ fs.unlink(filePath, () => { })
119
160
  reject(err)
120
161
  })
162
+
121
163
  fileStream.on('error', (err) => {
122
- fs.unlink(filePath, () => { }) // Delete the file in case of error
164
+ response.data.destroy()
165
+ fs.unlink(filePath, () => { })
123
166
  reject(err)
124
167
  })
125
168
  })
169
+
170
+ await log.progress('downloading', downloaded, downloaded)
126
171
  }
127
172
 
128
173
  /**
@@ -135,13 +180,15 @@ const downloadResourceFile = async (filePath: string, { catalogConfig, resourceI
135
180
  * @returns A promise that resolves when the file is successfully downloaded and saved.
136
181
  * @throws If there is an error writing the file or fetching the dataset.
137
182
  */
138
- const downloadResourceLines = async (destFile: string, { catalogConfig, resourceId, importConfig, log }: GetResourceContext<DataFairConfig> & { importConfig: ImportConfig }) => {
139
- let url: string | null = `${catalogConfig.url}/data-fair/api/v1/datasets/${resourceId}/lines?format=csv&size=3000`
183
+ const downloadResourceLines = async (destFile: string, { catalogConfig, resourceId, importConfig, secrets, log }: GetResourceContext<DataFairConfig> & { importConfig: ImportConfig }): Promise<void> => {
184
+ let url: string | null = `${catalogConfig.url}/data-fair/api/v1/datasets/${resourceId}/lines?format=csv&size=5000`
140
185
 
141
186
  if (importConfig.fields) {
142
187
  url += '&select=' + importConfig.fields.map(field => field.key).join(',')
143
188
  }
144
189
 
190
+ const headers = secrets.apiKey ? { 'x-apiKey': secrets.apiKey } : undefined
191
+
145
192
  if (importConfig.filters) {
146
193
  importConfig.filters.forEach((filter) => {
147
194
  switch (filter.type) {
@@ -160,13 +207,14 @@ const downloadResourceLines = async (destFile: string, { catalogConfig, resource
160
207
  })
161
208
  }
162
209
 
163
- log.info('Import des données de la ressource', url)
210
+ let downloaded = 0
211
+ let pendingLogPromise: Promise<void> | null = null
212
+
164
213
  const writer = fs.createWriteStream(destFile)
165
214
  let isFirstChunk = true
166
215
 
167
216
  while (url) {
168
- console.log(url)
169
- const response = await axios.get(url, { responseType: 'stream' })
217
+ const response = await axios.get(url, { responseType: 'stream', headers })
170
218
  if (response.status !== 200) {
171
219
  throw new Error(`Error while fetching data: HTTP ${response.statusText}`)
172
220
  }
@@ -189,6 +237,18 @@ const downloadResourceLines = async (destFile: string, { catalogConfig, resource
189
237
  }
190
238
  }))
191
239
  }
240
+
241
+ stream.on('data', (chunk: Buffer) => {
242
+ downloaded += chunk.length
243
+
244
+ // Only start a new log promise if there isn't one already running
245
+ if (!pendingLogPromise) {
246
+ pendingLogPromise = log.progress('downloading', downloaded)
247
+ .catch(err => console.warn('Progress logging failed:', err))
248
+ .finally(() => { pendingLogPromise = null })
249
+ }
250
+ })
251
+
192
252
  stream.pipe(writer, { end: false })
193
253
  stream.on('end', () => {
194
254
  const linkHeader = response.headers.link
@@ -203,6 +263,7 @@ const downloadResourceLines = async (destFile: string, { catalogConfig, resource
203
263
  })
204
264
  })
205
265
  }
266
+ await log.progress('downloading', downloaded, downloaded)
206
267
  writer.end()
207
268
  }
208
269
 
package/lib/imports.ts CHANGED
@@ -14,12 +14,18 @@ const prepareCatalog = (dataFairDatasets: DataFairDataset[]): ResourceList => {
14
14
  const catalog: ResourceList = []
15
15
 
16
16
  for (const dataFairDataset of dataFairDatasets) {
17
+ let size: number | undefined
18
+ if (dataFairDataset.storage?.dataFiles && dataFairDataset.storage.dataFiles.length > 0) {
19
+ const lastFile = dataFairDataset.storage.dataFiles[dataFairDataset.storage.dataFiles.length - 1]
20
+ size = lastFile.size
21
+ }
17
22
  catalog.push({
18
23
  id: dataFairDataset.id,
19
24
  title: dataFairDataset.title,
20
25
  format: 'csv',
21
- size: dataFairDataset.file?.size ?? dataFairDataset.storage?.size ?? dataFairDataset.originalFile?.size,
26
+ size,
22
27
  type: 'resource',
28
+ origin: dataFairDataset.page
23
29
  } as ResourceList[number])
24
30
  }
25
31
  return catalog
@@ -38,9 +44,10 @@ export const listResources = async (config: ListResourcesContext<DataFairConfig,
38
44
 
39
45
  let data: DataFairCatalog
40
46
  const url = `${config.catalogConfig.url}/data-fair/api/v1/catalog/datasets`
47
+ const headers = config.secrets.apiKey ? { 'x-apiKey': config.secrets.apiKey } : undefined
41
48
  try {
42
- const res = (await axios.get(url, { params: dataFairParams }))
43
- if (res.status !== 200) {
49
+ const res = (await axios.get(url, { params: dataFairParams, headers }))
50
+ if (res.status !== 200 || typeof res.data !== 'object') {
44
51
  throw new Error(`HTTP error : ${res.status}, ${res.data}`)
45
52
  }
46
53
  data = res.data
package/lib/prepare.ts CHANGED
@@ -4,15 +4,27 @@ import type { DataFairConfig } from '#types'
4
4
  import axios from '@data-fair/lib-node/axios.js'
5
5
 
6
6
  export default async ({ catalogConfig, capabilities, secrets }: PrepareContext<DataFairConfig, DataFairCapabilities>) => {
7
- // To remove when catalog/datasets allows q parameters
8
- capabilities = capabilities.filter(c => c !== 'search')
7
+ // set the apiKey in the secrets field if it exists
8
+ const apiKey = catalogConfig.apiKey
9
+ if (apiKey && apiKey !== '*************************') {
10
+ secrets.apiKey = apiKey
11
+ catalogConfig.apiKey = '*************************'
12
+ } else if (secrets?.apiKey && (!apiKey || apiKey === '')) {
13
+ delete secrets.apiKey
14
+ } else {
15
+ // The secret is already set, do nothing
16
+ }
9
17
 
10
18
  // test the url
11
19
  try {
12
- await axios.get(catalogConfig.url + '/data-fair/api/v1/catalog/datasets?size=1&select=id')
20
+ if (!catalogConfig.url) {
21
+ throw new Error('URL du catalogue non définie')
22
+ }
23
+ const config = secrets.apiKey ? { headers: { 'x-apiKey': secrets.apiKey } } : undefined
24
+ await axios.get(catalogConfig.url + '/data-fair/api/v1/catalog/datasets?size=1&select=id', config)
13
25
  } catch (e) {
14
26
  console.error('Erreur URL pendant la configuration : ', e instanceof Error ? e.message : e)
15
- throw new Error('Configuration invalide, vérifiez l\'URL')
27
+ throw new Error(`Configuration invalide, veuillez vérifier lURL du catalogue et la clé API si nécessaire (${e instanceof Error ? e.message : e})`)
16
28
  }
17
29
 
18
30
  return {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@data-fair/catalog-data-fair",
3
3
  "description": "A simple Data Fair plugin for the Data Fair catalogs service.",
4
- "version": "0.1.0",
4
+ "version": "0.2.1",
5
5
  "main": "index.ts",
6
6
  "type": "module",
7
7
  "scripts": {
@@ -31,7 +31,8 @@
31
31
  "dependencies": {
32
32
  "@data-fair/lib-node": "^2.8.2",
33
33
  "@data-fair/lib-utils": "^1.6.0",
34
- "prom-client": "^15.1.3"
34
+ "prom-client": "^15.1.3",
35
+ "slugify": "^1.6.6"
35
36
  },
36
37
  "devDependencies": {
37
38
  "@commitlint/cli": "^19.8.0",
@@ -6,9 +6,14 @@ export const schemaExports: string[]
6
6
  * The url of the catalog
7
7
  */
8
8
  export type URL = string;
9
+ /**
10
+ * The Data Fair API key to access the catalog. You can create one from the 'Settings' tab in Data Fair, under the 'API Keys' section.
11
+ */
12
+ export type APIKeyOptional = string;
9
13
 
10
14
  export type DataFairConfig = {
11
15
  url: URL;
16
+ apiKey?: APIKeyOptional;
12
17
  }
13
18
 
14
19
 
@@ -38,7 +38,7 @@ export const schema = {
38
38
  "title": "URL",
39
39
  "description": "The url of the catalog",
40
40
  "x-i18n-description": {
41
- "fr": "L'URL du site où le catalogue est publié. *L'URL de l'API utilisée sera* *https*[]()*://example.com***/data-fair/api/v1**"
41
+ "fr": "L'URL du portail où le catalogue est publié. Par exemple: `https://opendata.koumoul.com`."
42
42
  },
43
43
  "pattern": "^https?://.*[^/]$",
44
44
  "errorMessage": "The URL must start with http:// or https:// and must not end with `/`.",
@@ -46,8 +46,25 @@ export const schema = {
46
46
  "fr": "L'URL doit commencer par http:// ou https:// et ne pas se terminer par `/`."
47
47
  },
48
48
  "examples": [
49
- "https://example.com"
49
+ "https://opendata.koumoul.com"
50
50
  ]
51
+ },
52
+ "apiKey": {
53
+ "type": "string",
54
+ "title": "API Key (Optional)",
55
+ "x-i18n-title": {
56
+ "fr": "Clé API (Optionnelle)"
57
+ },
58
+ "description": "The Data Fair API key to access the catalog. You can create one from the 'Settings' tab in Data Fair, under the 'API Keys' section.",
59
+ "x-i18n-description": {
60
+ "fr": "La clé API Data Fair pour accéder au catalogue. Vous pouvez en créer depuis l'onglet 'Paramètres' de Data Fair, dans la section 'Clés d'API'."
61
+ },
62
+ "layout": {
63
+ "props": {
64
+ "type": "password",
65
+ "autocomplete": "new-password"
66
+ }
67
+ }
51
68
  }
52
69
  }
53
70
  }
@@ -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-data-fair/catalog-config","x-exports":["types","validate","schema"],"title":"DataFairConfig","type":"object","additionalProperties":false,"required":["url"],"properties":{"url":{"type":"string","title":"URL","description":"The url of the catalog","x-i18n-description":{"fr":"L'URL du site où le catalogue est publié. *L'URL de l'API utilisée sera* *https*[]()*://example.com***/data-fair/api/v1**"},"pattern":"^https?://.*[^/]$","errorMessage":"The URL must start with http:// or https:// and must not end with `/`.","x-i18n-errorMessage":{"fr":"L'URL doit commencer par http:// ou https:// et ne pas se terminer par `/`."},"examples":["https://example.com"]}}};
7
+ const schema16 = {"$id":"https://github.com/data-fair/catalog-data-fair/catalog-config","x-exports":["types","validate","schema"],"title":"DataFairConfig","type":"object","additionalProperties":false,"required":["url"],"properties":{"url":{"type":"string","title":"URL","description":"The url of the catalog","x-i18n-description":{"fr":"L'URL du portail où le catalogue est publié. Par exemple: `https://opendata.koumoul.com`."},"pattern":"^https?://.*[^/]$","errorMessage":"The URL must start with http:// or https:// and must not end with `/`.","x-i18n-errorMessage":{"fr":"L'URL doit commencer par http:// ou https:// et ne pas se terminer par `/`."},"examples":["https://opendata.koumoul.com"]},"apiKey":{"type":"string","title":"API Key (Optional)","x-i18n-title":{"fr":"Clé API (Optionnelle)"},"description":"The Data Fair API key to access the catalog. You can create one from the 'Settings' tab in Data Fair, under the 'API Keys' section.","x-i18n-description":{"fr":"La clé API Data Fair pour accéder au catalogue. Vous pouvez en créer depuis l'onglet 'Paramètres' de Data Fair, dans la section 'Clés d'API'."},"layout":{"props":{"type":"password","autocomplete":"new-password"}}}}};
8
8
  const pattern0 = new RegExp("^https?://.*[^/]$", "u");
9
9
 
10
10
  function validate14(data, {instancePath="", parentData, parentDataProperty, rootData=data}={}){
@@ -23,7 +23,7 @@ vErrors.push(err0);
23
23
  errors++;
24
24
  }
25
25
  for(const key0 in data){
26
- if(!(key0 === "url")){
26
+ if(!((key0 === "url") || (key0 === "apiKey"))){
27
27
  const err1 = {instancePath,schemaPath:"#/additionalProperties",keyword:"additionalProperties",params:{additionalProperty: key0},message:"must NOT have additional properties"};
28
28
  if(vErrors === null){
29
29
  vErrors = [err1];
@@ -86,9 +86,9 @@ vErrors = emErrs1;
86
86
  errors = emErrs1.length;
87
87
  }
88
88
  }
89
- }
90
- else {
91
- const err7 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"};
89
+ if(data.apiKey !== undefined){
90
+ if(typeof data.apiKey !== "string"){
91
+ const err7 = {instancePath:instancePath+"/apiKey",schemaPath:"#/properties/apiKey/type",keyword:"type",params:{type: "string"},message:"must be string"};
92
92
  if(vErrors === null){
93
93
  vErrors = [err7];
94
94
  }
@@ -97,6 +97,18 @@ vErrors.push(err7);
97
97
  }
98
98
  errors++;
99
99
  }
100
+ }
101
+ }
102
+ else {
103
+ const err8 = {instancePath,schemaPath:"#/type",keyword:"type",params:{type: "object"},message:"must be object"};
104
+ if(vErrors === null){
105
+ vErrors = [err8];
106
+ }
107
+ else {
108
+ vErrors.push(err8);
109
+ }
110
+ errors++;
111
+ }
100
112
  validate14.errors = vErrors;
101
113
  return errors === 0;
102
114
  }
@@ -17,14 +17,33 @@
17
17
  "title": "URL",
18
18
  "description": "The url of the catalog",
19
19
  "x-i18n-description": {
20
- "fr": "L'URL du site où le catalogue est publié. *L'URL de l'API utilisée sera* *https*[]()*://example.com***/data-fair/api/v1**"
20
+ "fr": "L'URL du portail où le catalogue est publié. Par exemple: `https://opendata.koumoul.com`."
21
21
  },
22
22
  "pattern": "^https?://.*[^/]$",
23
23
  "errorMessage": "The URL must start with http:// or https:// and must not end with `/`.",
24
24
  "x-i18n-errorMessage": {
25
25
  "fr": "L'URL doit commencer par http:// ou https:// et ne pas se terminer par `/`."
26
26
  },
27
- "examples": ["https://example.com"]
27
+ "examples": [
28
+ "https://opendata.koumoul.com"
29
+ ]
30
+ },
31
+ "apiKey": {
32
+ "type": "string",
33
+ "title": "API Key (Optional)",
34
+ "x-i18n-title": {
35
+ "fr": "Clé API (Optionnelle)"
36
+ },
37
+ "description": "The Data Fair API key to access the catalog. You can create one from the 'Settings' tab in Data Fair, under the 'API Keys' section.",
38
+ "x-i18n-description": {
39
+ "fr": "La clé API Data Fair pour accéder au catalogue. Vous pouvez en créer depuis l'onglet 'Paramètres' de Data Fair, dans la section 'Clés d'API'."
40
+ },
41
+ "layout": {
42
+ "props": {
43
+ "type": "password",
44
+ "autocomplete": "new-password"
45
+ }
46
+ }
28
47
  }
29
48
  }
30
- }
49
+ }
@@ -210,6 +210,19 @@ export type DataFairDataset = {
210
210
  */
211
211
  storage?: {
212
212
  size?: number;
213
+ /**
214
+ * Le tableau de résultats.
215
+ */
216
+ dataFiles?: {
217
+ key?: string;
218
+ size?: number;
219
+ name?: string;
220
+ mimetype?: string;
221
+ updatedAt?: string;
222
+ title?: string;
223
+ url?: string;
224
+ [k: string]: unknown;
225
+ }[];
213
226
  [k: string]: unknown;
214
227
  };
215
228
  /**
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://github.com/data-fair/catalog-data-fair/catlog-schemas",
2
+ "$id": "https://github.com/data-fair/catalog-data-fair/catalog-schemas",
3
3
  "x-exports": [
4
4
  "types"
5
5
  ],
@@ -347,6 +347,37 @@
347
347
  "properties": {
348
348
  "size": {
349
349
  "type": "integer"
350
+ },
351
+ "dataFiles": {
352
+ "type": "array",
353
+ "description": "Le tableau de résultats.",
354
+ "items": {
355
+ "type": "object",
356
+ "properties": {
357
+ "key": {
358
+ "type": "string"
359
+ },
360
+ "size": {
361
+ "type": "number"
362
+ },
363
+ "name": {
364
+ "type": "string"
365
+ },
366
+ "mimetype": {
367
+ "type": "string"
368
+ },
369
+ "updatedAt": {
370
+ "type": "string",
371
+ "format": "date-time"
372
+ },
373
+ "title": {
374
+ "type": "string"
375
+ },
376
+ "url": {
377
+ "type": "string"
378
+ }
379
+ }
380
+ }
350
381
  }
351
382
  }
352
383
  },
@@ -50,6 +50,7 @@ export const schema = {
50
50
  }
51
51
  },
52
52
  "layout": {
53
+ "density": "compact",
53
54
  "getItems": {
54
55
  "url": "${context.catalogConfig.url}/data-fair/api/v1/datasets/${context.resourceId}/schema?calculated=false",
55
56
  "itemTitle": "item.label",
@@ -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-data-fair/import-config","x-exports":["types","validate","schema"],"title":"Configuration de l'import","type":"object","additionalProperties":false,"properties":{"fields":{"type":"array","default":[],"title":"Colonnes du jeu de données","description":"La liste des colonnes à importer. Si ce champ est vide, toutes les colonnes seront importées.","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"type":{"type":"string"}}},"layout":{"getItems":{"url":"${context.catalogConfig.url}/data-fair/api/v1/datasets/${context.resourceId}/schema?calculated=false","itemTitle":"item.label","itemKey":"item.key"}}},"filters":{"$ref":"#/$defs/filters"}},"$defs":{"filters":{"title":"Filtres prédéfinis","type":"array","default":[],"items":{"type":"object","default":{"type":"in"},"required":["type"],"oneOf":[{"title":"Restreindre à des valeurs précises","required":["field","values","type"],"properties":{"type":{"const":"in"},"field":{"$ref":"#/$defs/filterField"},"values":{"type":"array","title":"Valeurs","description":"Importe seulement des lignes où la valeur du champ indiqué est égale à l'une des valeurs renseignées.<br>*Toutes les valeurs peuvent ne pas être affichées, écrivez pour rechercher un champ particulier.*","items":{"type":"string"},"layout":{"getItems":{"url":"${context.catalogConfig.url}/data-fair/api/v1/datasets/${context.resourceId}/values/${parent.data.field.key}?q={q}&q_mode=complete&size=100&stringify=true"},"props":{"clearable":true}},"default":[]}}},{"title":"Exclure des valeurs","required":["field","values","type"],"properties":{"type":{"const":"nin"},"field":{"$ref":"#/$defs/filterField"},"values":{"type":"array","title":"Valeurs à exclure","description":"Importe seulement des lignes où la valeur du champ indiqué est différente des valeurs renseignées.<br>*Toutes les valeurs peuvent ne pas être affichées, écrivez pour rechercher un champ particulier.*","items":{"type":"string"},"layout":{"getItems":{"url":"${context.catalogConfig.url}/data-fair/api/v1/datasets/${context.resourceId}/values/${parent.data.field.key}?q={q}&q_mode=complete&size=100&stringify=true"},"props":{"clearable":true}},"default":[]}}},{"title":"Supérieur à une valeur","required":["field","value","type"],"properties":{"type":{"const":"gte"},"field":{"$ref":"#/$defs/filterField"},"value":{"type":"string","title":"Valeur minimale","description":"Importe seulement des lignes où la valeur du champ indiqué est supérieur ou égale à la valeur renseignée. La valeur peut être un nombre, une chaîne de caractère (*ordre alphanumérique*), une date.<br>*Toutes les valeurs peuvent ne pas être affichées, écrivez pour rechercher un champ particulier.*","layout":{"comp":"combobox","getItems":{"url":"${context.catalogConfig.url}/data-fair/api/v1/datasets/${context.resourceId}/values/${parent.data.field.key}?q={q}&q_mode=complete&size=100&stringify=true&sort=asc"}}}}},{"title":"Inférieur à une valeur","required":["field","value","type"],"properties":{"type":{"const":"lte"},"field":{"$ref":"#/$defs/filterField"},"value":{"type":"string","title":"Valeur maximale","description":"Importe seulement les lignes où la valeur du champ indiqué est inférieur à la valeur renseignée. La valeur peut être un nombre, une chaîne de caractère (*ordre alphanumérique*), une date.<br>*Toutes les valeurs peuvent ne pas être affichées, écrivez pour rechercher un champ particulier.*","layout":{"comp":"combobox","getItems":{"url":"${context.catalogConfig.url}/data-fair/api/v1/datasets/${context.resourceId}/values/${parent.data.field.key}?q={q}&q_mode=complete&size=100&stringify=true&sort=asc"}}}}},{"title":"Commence par les caractères","required":["field","value","type"],"properties":{"type":{"const":"starts"},"field":{"$ref":"#/$defs/filterFieldString"},"value":{"type":"string","description":"Importe seulement les lignes où le champ (colonne) indiqué commence par une chaîne de caractères précise. La chaîne de caractères est sensible à la casse.<br>Seuls les champs (colonnes) ayant pour valeurs des chaînes de caractères sont acceptées.<br>*Toutes les valeurs peuvent ne pas être affichées, écrivez pour rechercher un champ particulier.*","title":"Commence par les caractères","layout":{"comp":"combobox","getItems":{"url":"${context.catalogConfig.url}/data-fair/api/v1/datasets/${context.resourceId}/values/${parent.data.field.key}?q={q}&q_mode=complete&size=100&stringify=true"}}}}}]}},"filterField":{"type":"object","title":"Colonne de filtre","properties":{"key":{"type":"string"},"label":{"type":"string"},"type":{"type":"string"}},"layout":{"getItems":{"url":"${context.catalogConfig.url}/data-fair/api/v1/datasets/${context.resourceId}/schema?calculated=false","itemTitle":"item.label","itemKey":"item.key"}}},"filterFieldString":{"type":"object","title":"Colonne de filtre","properties":{"key":{"type":"string"},"label":{"type":"string"},"type":{"type":"string"}},"layout":{"getItems":{"url":"${context.catalogConfig.url}/data-fair/api/v1/datasets/${context.resourceId}/schema?calculated=false&type=string","itemTitle":"item.label","itemKey":"item.key"}}}}};
7
+ const schema16 = {"$id":"https://github.com/data-fair/catalog-data-fair/import-config","x-exports":["types","validate","schema"],"title":"Configuration de l'import","type":"object","additionalProperties":false,"properties":{"fields":{"type":"array","default":[],"title":"Colonnes du jeu de données","description":"La liste des colonnes à importer. Si ce champ est vide, toutes les colonnes seront importées.","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"type":{"type":"string"}}},"layout":{"density":"compact","getItems":{"url":"${context.catalogConfig.url}/data-fair/api/v1/datasets/${context.resourceId}/schema?calculated=false","itemTitle":"item.label","itemKey":"item.key"}}},"filters":{"$ref":"#/$defs/filters"}},"$defs":{"filters":{"title":"Filtres prédéfinis","type":"array","default":[],"items":{"type":"object","default":{"type":"in"},"required":["type"],"oneOf":[{"title":"Restreindre à des valeurs précises","required":["field","values","type"],"properties":{"type":{"const":"in"},"field":{"$ref":"#/$defs/filterField"},"values":{"type":"array","title":"Valeurs","description":"Importe seulement des lignes où la valeur du champ indiqué est égale à l'une des valeurs renseignées.<br>*Toutes les valeurs peuvent ne pas être affichées, écrivez pour rechercher un champ particulier.*","items":{"type":"string"},"layout":{"getItems":{"url":"${context.catalogConfig.url}/data-fair/api/v1/datasets/${context.resourceId}/values/${parent.data.field.key}?q={q}&q_mode=complete&size=100&stringify=true"},"props":{"clearable":true}},"default":[]}}},{"title":"Exclure des valeurs","required":["field","values","type"],"properties":{"type":{"const":"nin"},"field":{"$ref":"#/$defs/filterField"},"values":{"type":"array","title":"Valeurs à exclure","description":"Importe seulement des lignes où la valeur du champ indiqué est différente des valeurs renseignées.<br>*Toutes les valeurs peuvent ne pas être affichées, écrivez pour rechercher un champ particulier.*","items":{"type":"string"},"layout":{"getItems":{"url":"${context.catalogConfig.url}/data-fair/api/v1/datasets/${context.resourceId}/values/${parent.data.field.key}?q={q}&q_mode=complete&size=100&stringify=true"},"props":{"clearable":true}},"default":[]}}},{"title":"Supérieur à une valeur","required":["field","value","type"],"properties":{"type":{"const":"gte"},"field":{"$ref":"#/$defs/filterField"},"value":{"type":"string","title":"Valeur minimale","description":"Importe seulement des lignes où la valeur du champ indiqué est supérieur ou égale à la valeur renseignée. La valeur peut être un nombre, une chaîne de caractère (*ordre alphanumérique*), une date.<br>*Toutes les valeurs peuvent ne pas être affichées, écrivez pour rechercher un champ particulier.*","layout":{"comp":"combobox","getItems":{"url":"${context.catalogConfig.url}/data-fair/api/v1/datasets/${context.resourceId}/values/${parent.data.field.key}?q={q}&q_mode=complete&size=100&stringify=true&sort=asc"}}}}},{"title":"Inférieur à une valeur","required":["field","value","type"],"properties":{"type":{"const":"lte"},"field":{"$ref":"#/$defs/filterField"},"value":{"type":"string","title":"Valeur maximale","description":"Importe seulement les lignes où la valeur du champ indiqué est inférieur à la valeur renseignée. La valeur peut être un nombre, une chaîne de caractère (*ordre alphanumérique*), une date.<br>*Toutes les valeurs peuvent ne pas être affichées, écrivez pour rechercher un champ particulier.*","layout":{"comp":"combobox","getItems":{"url":"${context.catalogConfig.url}/data-fair/api/v1/datasets/${context.resourceId}/values/${parent.data.field.key}?q={q}&q_mode=complete&size=100&stringify=true&sort=asc"}}}}},{"title":"Commence par les caractères","required":["field","value","type"],"properties":{"type":{"const":"starts"},"field":{"$ref":"#/$defs/filterFieldString"},"value":{"type":"string","description":"Importe seulement les lignes où le champ (colonne) indiqué commence par une chaîne de caractères précise. La chaîne de caractères est sensible à la casse.<br>Seuls les champs (colonnes) ayant pour valeurs des chaînes de caractères sont acceptées.<br>*Toutes les valeurs peuvent ne pas être affichées, écrivez pour rechercher un champ particulier.*","title":"Commence par les caractères","layout":{"comp":"combobox","getItems":{"url":"${context.catalogConfig.url}/data-fair/api/v1/datasets/${context.resourceId}/values/${parent.data.field.key}?q={q}&q_mode=complete&size=100&stringify=true"}}}}}]}},"filterField":{"type":"object","title":"Colonne de filtre","properties":{"key":{"type":"string"},"label":{"type":"string"},"type":{"type":"string"}},"layout":{"getItems":{"url":"${context.catalogConfig.url}/data-fair/api/v1/datasets/${context.resourceId}/schema?calculated=false","itemTitle":"item.label","itemKey":"item.key"}}},"filterFieldString":{"type":"object","title":"Colonne de filtre","properties":{"key":{"type":"string"},"label":{"type":"string"},"type":{"type":"string"}},"layout":{"getItems":{"url":"${context.catalogConfig.url}/data-fair/api/v1/datasets/${context.resourceId}/schema?calculated=false&type=string","itemTitle":"item.label","itemKey":"item.key"}}}}};
8
8
  const schema17 = {"title":"Filtres prédéfinis","type":"array","default":[],"items":{"type":"object","default":{"type":"in"},"required":["type"],"oneOf":[{"title":"Restreindre à des valeurs précises","required":["field","values","type"],"properties":{"type":{"const":"in"},"field":{"$ref":"#/$defs/filterField"},"values":{"type":"array","title":"Valeurs","description":"Importe seulement des lignes où la valeur du champ indiqué est égale à l'une des valeurs renseignées.<br>*Toutes les valeurs peuvent ne pas être affichées, écrivez pour rechercher un champ particulier.*","items":{"type":"string"},"layout":{"getItems":{"url":"${context.catalogConfig.url}/data-fair/api/v1/datasets/${context.resourceId}/values/${parent.data.field.key}?q={q}&q_mode=complete&size=100&stringify=true"},"props":{"clearable":true}},"default":[]}}},{"title":"Exclure des valeurs","required":["field","values","type"],"properties":{"type":{"const":"nin"},"field":{"$ref":"#/$defs/filterField"},"values":{"type":"array","title":"Valeurs à exclure","description":"Importe seulement des lignes où la valeur du champ indiqué est différente des valeurs renseignées.<br>*Toutes les valeurs peuvent ne pas être affichées, écrivez pour rechercher un champ particulier.*","items":{"type":"string"},"layout":{"getItems":{"url":"${context.catalogConfig.url}/data-fair/api/v1/datasets/${context.resourceId}/values/${parent.data.field.key}?q={q}&q_mode=complete&size=100&stringify=true"},"props":{"clearable":true}},"default":[]}}},{"title":"Supérieur à une valeur","required":["field","value","type"],"properties":{"type":{"const":"gte"},"field":{"$ref":"#/$defs/filterField"},"value":{"type":"string","title":"Valeur minimale","description":"Importe seulement des lignes où la valeur du champ indiqué est supérieur ou égale à la valeur renseignée. La valeur peut être un nombre, une chaîne de caractère (*ordre alphanumérique*), une date.<br>*Toutes les valeurs peuvent ne pas être affichées, écrivez pour rechercher un champ particulier.*","layout":{"comp":"combobox","getItems":{"url":"${context.catalogConfig.url}/data-fair/api/v1/datasets/${context.resourceId}/values/${parent.data.field.key}?q={q}&q_mode=complete&size=100&stringify=true&sort=asc"}}}}},{"title":"Inférieur à une valeur","required":["field","value","type"],"properties":{"type":{"const":"lte"},"field":{"$ref":"#/$defs/filterField"},"value":{"type":"string","title":"Valeur maximale","description":"Importe seulement les lignes où la valeur du champ indiqué est inférieur à la valeur renseignée. La valeur peut être un nombre, une chaîne de caractère (*ordre alphanumérique*), une date.<br>*Toutes les valeurs peuvent ne pas être affichées, écrivez pour rechercher un champ particulier.*","layout":{"comp":"combobox","getItems":{"url":"${context.catalogConfig.url}/data-fair/api/v1/datasets/${context.resourceId}/values/${parent.data.field.key}?q={q}&q_mode=complete&size=100&stringify=true&sort=asc"}}}}},{"title":"Commence par les caractères","required":["field","value","type"],"properties":{"type":{"const":"starts"},"field":{"$ref":"#/$defs/filterFieldString"},"value":{"type":"string","description":"Importe seulement les lignes où le champ (colonne) indiqué commence par une chaîne de caractères précise. La chaîne de caractères est sensible à la casse.<br>Seuls les champs (colonnes) ayant pour valeurs des chaînes de caractères sont acceptées.<br>*Toutes les valeurs peuvent ne pas être affichées, écrivez pour rechercher un champ particulier.*","title":"Commence par les caractères","layout":{"comp":"combobox","getItems":{"url":"${context.catalogConfig.url}/data-fair/api/v1/datasets/${context.resourceId}/values/${parent.data.field.key}?q={q}&q_mode=complete&size=100&stringify=true"}}}}}]}};
9
9
  const schema18 = {"type":"object","title":"Colonne de filtre","properties":{"key":{"type":"string"},"label":{"type":"string"},"type":{"type":"string"}},"layout":{"getItems":{"url":"${context.catalogConfig.url}/data-fair/api/v1/datasets/${context.resourceId}/schema?calculated=false","itemTitle":"item.label","itemKey":"item.key"}}};
10
10
  const schema22 = {"type":"object","title":"Colonne de filtre","properties":{"key":{"type":"string"},"label":{"type":"string"},"type":{"type":"string"}},"layout":{"getItems":{"url":"${context.catalogConfig.url}/data-fair/api/v1/datasets/${context.resourceId}/schema?calculated=false&type=string","itemTitle":"item.label","itemKey":"item.key"}}};
@@ -29,6 +29,7 @@
29
29
  }
30
30
  },
31
31
  "layout": {
32
+ "density": "compact",
32
33
  "getItems": {
33
34
  "url": "${context.catalogConfig.url}/data-fair/api/v1/datasets/${context.resourceId}/schema?calculated=false",
34
35
  "itemTitle": "item.label",
@@ -249,4 +250,4 @@
249
250
  }
250
251
  }
251
252
  }
252
- }
253
+ }