Compare commits

...

7 Commits

Author SHA1 Message Date
João Demenech
32dce434eb Merge pull request #1017 from datopian/changeset-release/main
Version Packages
2023-08-31 16:13:39 -03:00
github-actions[bot]
37ef29d9a2 Version Packages 2023-08-31 19:09:52 +00:00
João Demenech
98d62532c5 Merge pull request #1018 from datopian/ckan/feat/private-datasets
feat(ckan): makes it possible to search private datasets on the ckan api
2023-08-31 16:06:01 -03:00
João Demenech
50122cd0cb bump: new version of CKAN API 2023-08-30 18:38:35 -03:00
João Demenech
0156e72dd3 feat(ckan): makes it possible to search private datasets on the ckan api 2023-08-30 18:35:40 -03:00
Luccas Mateus
91217f3256 [packanges/ckan][xs] - fix type (#1016) 2023-08-24 16:04:44 -03:00
github-actions[bot]
11f9253709 Version Packages (#1015)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-24 16:03:42 -03:00
5 changed files with 86 additions and 110 deletions

View File

@@ -1,5 +1,15 @@
# @portaljs/ckan # @portaljs/ckan
## 0.1.0
### Minor Changes
- [#1018](https://github.com/datopian/portaljs/pull/1018) [`50122cd0`](https://github.com/datopian/portaljs/commit/50122cd0cbbf68bdadc641341279b30b22538cfd) Thanks [@demenech](https://github.com/demenech)! - package_search method now supports custom headers and include_private parameter
### Patch Changes
- [#1016](https://github.com/datopian/portaljs/pull/1016) [`91217f32`](https://github.com/datopian/portaljs/commit/91217f325657e2f298b0e632793ae9bb8b08e870) Thanks [@luccasmmg](https://github.com/luccasmmg)! - remove optional from id in resource interface
## 0.0.5 ## 0.0.5
### Patch Changes ### Patch Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@portaljs/ckan", "name": "@portaljs/ckan",
"version": "0.0.5", "version": "0.1.0",
"type": "module", "type": "module",
"description": "https://portaljs.org", "description": "https://portaljs.org",
"keywords": [ "keywords": [

View File

@@ -41,7 +41,7 @@ export interface Resource {
description?: string; description?: string;
format?: string; format?: string;
hash?: string; hash?: string;
id?: string; id: string;
last_modified?: string; last_modified?: string;
metadata_modified?: string; metadata_modified?: string;
mimetype?: string; mimetype?: string;
@@ -69,6 +69,7 @@ export interface PackageSearchOptions {
query?: string; query?: string;
resFormat?: Array<string>; resFormat?: Array<string>;
sort?: string; sort?: string;
include_private?: boolean;
} }
export interface Tag { export interface Tag {

View File

@@ -31,11 +31,7 @@ export default class CKAN {
async getDatasetsListWithDetails(options: DatasetListQueryOptions) { async getDatasetsListWithDetails(options: DatasetListQueryOptions) {
const response = await fetchRetry( const response = await fetchRetry(
`${ `${this.DMS}/api/3/action/current_package_list_with_resources?offset=${options.offset}&limit=${options.limit}`,
this.DMS
}/api/3/action/current_package_list_with_resources?offset=${
options.offset
}&limit=${options.limit}`,
3 3
); );
const responseData = await response.json(); const responseData = await response.json();
@@ -44,7 +40,8 @@ export default class CKAN {
} }
async packageSearch( async packageSearch(
options: PackageSearchOptions options: PackageSearchOptions,
reqOptions: Partial<RequestInit> = {}
): Promise<{ datasets: Dataset[]; count: number }> { ): Promise<{ datasets: Dataset[]; count: number }> {
function buildGroupsQuery(groups: Array<string>) { function buildGroupsQuery(groups: Array<string>) {
if (groups.length > 0) { if (groups.length > 0) {
@@ -99,16 +96,18 @@ export default class CKAN {
options.groups, options.groups,
options?.resFormat options?.resFormat
); );
const response = await fetchRetry(
`${ let url = `${this.DMS}/api/3/action/package_search?`;
this.DMS url += `start=${options.offset}`;
}/api/3/action/package_search?start=${options.offset}&rows=${ url += `&rows=${options.limit}`;
options.limit url += fq ? fq : '';
}${fq ? fq : ''}${options.query ? '&q=' + options.query : ''}${ url += options.query ? '&q=' + options.query : '';
options.sort ? '&sort=' + options.sort : '' url += options.sort ? '&sort=' + options.sort : '';
}`, url += options.include_private
3 ? '&include_private=' + options.include_private
); : '';
const response = await fetchRetry(url, 3, reqOptions);
const responseData = await response.json(); const responseData = await response.json();
const datasets: Array<Dataset> = responseData.result.results; const datasets: Array<Dataset> = responseData.result.results;
return { datasets, count: responseData.result.count }; return { datasets, count: responseData.result.count };
@@ -116,9 +115,7 @@ export default class CKAN {
async getDatasetDetails(datasetName: string) { async getDatasetDetails(datasetName: string) {
const response = await fetchRetry( const response = await fetchRetry(
`${ `${this.DMS}/api/3/action/package_show?id=${datasetName}`,
this.DMS
}/api/3/action/package_show?id=${datasetName}`,
1 1
); );
const responseData = await response.json(); const responseData = await response.json();
@@ -131,9 +128,7 @@ export default class CKAN {
async getDatasetActivityStream(datasetName: string) { async getDatasetActivityStream(datasetName: string) {
const response = await fetchRetry( const response = await fetchRetry(
`${ `${this.DMS}/api/3/action/package_activity_list?id=${datasetName}`,
this.DMS
}/api/3/action/package_activity_list?id=${datasetName}`,
3 3
); );
const responseData = await response.json(); const responseData = await response.json();
@@ -151,9 +146,7 @@ export default class CKAN {
async getUser(userId: string) { async getUser(userId: string) {
try { try {
const response = await fetchRetry( const response = await fetchRetry(
`${ `${this.DMS}/api/3/action/user_show?id=${userId}`,
this.DMS
}/api/3/action/user_show?id=${userId}`,
3 3
); );
const responseData = await response.json(); const responseData = await response.json();
@@ -166,10 +159,7 @@ export default class CKAN {
} }
async getGroupList() { async getGroupList() {
const response = await fetchRetry( const response = await fetchRetry(`${this.DMS}/api/3/action/group_list`, 3);
`${this.DMS}/api/3/action/group_list`,
3
);
const responseData = await response.json(); const responseData = await response.json();
const groups: Array<string> = responseData.result; const groups: Array<string> = responseData.result;
return groups; return groups;
@@ -177,9 +167,7 @@ export default class CKAN {
async getGroupsWithDetails() { async getGroupsWithDetails() {
const response = await fetchRetry( const response = await fetchRetry(
`${ `${this.DMS}/api/3/action/group_list?all_fields=True`,
this.DMS
}/api/3/action/group_list?all_fields=True`,
3 3
); );
const responseData = await response.json(); const responseData = await response.json();
@@ -189,9 +177,7 @@ export default class CKAN {
async getGroupDetails(groupName: string) { async getGroupDetails(groupName: string) {
const response = await fetchRetry( const response = await fetchRetry(
`${ `${this.DMS}/api/3/action/group_show?id=${groupName}&include_datasets=True`,
this.DMS
}/api/3/action/group_show?id=${groupName}&include_datasets=True`,
3 3
); );
const responseData = await response.json(); const responseData = await response.json();
@@ -201,9 +187,7 @@ export default class CKAN {
async getGroupActivityStream(groupName: string) { async getGroupActivityStream(groupName: string) {
const response = await fetchRetry( const response = await fetchRetry(
`${ `${this.DMS}/api/3/action/group_activity_list?id=${groupName}`,
this.DMS
}/api/3/action/group_activity_list?id=${groupName}`,
3 3
); );
const responseData = await response.json(); const responseData = await response.json();
@@ -230,9 +214,7 @@ export default class CKAN {
async getOrgsWithDetails(accrossPages?: boolean) { async getOrgsWithDetails(accrossPages?: boolean) {
if (!accrossPages) { if (!accrossPages) {
const response = await fetchRetry( const response = await fetchRetry(
`${ `${this.DMS}/api/3/action/organization_list?all_fields=True`,
this.DMS
}/api/3/action/organization_list?all_fields=True`,
3 3
); );
const responseData = await response.json(); const responseData = await response.json();
@@ -251,9 +233,7 @@ export default class CKAN {
for (let i = 0; i < pages; i++) { for (let i = 0; i < pages; i++) {
let allOrgListResponse = await fetchRetry( let allOrgListResponse = await fetchRetry(
`${ `${this.DMS}/api/3/action/organization_list?all_fields=True&offset=${
this.DMS
}/api/3/action/organization_list?all_fields=True&offset=${
i * 25 i * 25
}&limit=25`, }&limit=25`,
3 3
@@ -267,9 +247,7 @@ export default class CKAN {
async getOrgDetails(orgName: string) { async getOrgDetails(orgName: string) {
const response = await fetchRetry( const response = await fetchRetry(
`${ `${this.DMS}/api/3/action/organization_show?id=${orgName}&include_datasets=True`,
this.DMS
}/api/3/action/organization_show?id=${orgName}&include_datasets=True`,
3 3
); );
const responseData = await response.json(); const responseData = await response.json();
@@ -279,9 +257,7 @@ export default class CKAN {
async getOrgActivityStream(orgName: string) { async getOrgActivityStream(orgName: string) {
const response = await fetchRetry( const response = await fetchRetry(
`${ `${this.DMS}/api/3/action/organization_activity_list?id=${orgName}`,
this.DMS
}/api/3/action/organization_activity_list?id=${orgName}`,
3 3
); );
const responseData = await response.json(); const responseData = await response.json();
@@ -297,9 +273,7 @@ export default class CKAN {
async getAllTags() { async getAllTags() {
const response = await fetchRetry( const response = await fetchRetry(
`${ `${this.DMS}/api/3/action/tag_list?all_fields=True`,
this.DMS
}/api/3/action/tag_list?all_fields=True`,
3 3
); );
const responseData = await response.json(); const responseData = await response.json();
@@ -308,9 +282,7 @@ export default class CKAN {
} }
async getResourcesWithAliasList() { async getResourcesWithAliasList() {
const response = await fetch( const response = await fetch(`${this.DMS}/api/3/action/datastore_search`, {
`${this.DMS}/api/3/action/datastore_search`,
{
method: 'POST', method: 'POST',
headers: { headers: {
Accept: 'application/json', Accept: 'application/json',
@@ -320,17 +292,14 @@ export default class CKAN {
id: '_table_metadata', id: '_table_metadata',
limit: '32000', limit: '32000',
}), }),
} });
);
const responseData = await response.json(); const responseData = await response.json();
const tableMetadata: Array<TableMetadata> = responseData.result.records; const tableMetadata: Array<TableMetadata> = responseData.result.records;
return tableMetadata.filter((item) => item.alias_of); return tableMetadata.filter((item) => item.alias_of);
} }
async datastoreSearch(resourceId: string) { async datastoreSearch(resourceId: string) {
const response = await fetch( const response = await fetch(`${this.DMS}/api/3/action/datastore_search`, {
`${this.DMS}/api/3/action/datastore_search`,
{
method: 'POST', method: 'POST',
headers: { headers: {
Accept: 'application/json', Accept: 'application/json',
@@ -340,17 +309,14 @@ export default class CKAN {
id: resourceId, id: resourceId,
limit: '32000', limit: '32000',
}), }),
} });
);
const responseData = await response.json(); const responseData = await response.json();
return responseData.result.records; return responseData.result.records;
} }
async getResourceMetadata(resourceId: string) { async getResourceMetadata(resourceId: string) {
const response = await fetchRetry( const response = await fetchRetry(
`${ `${this.DMS}/api/3/action/resource_show?id=${resourceId}`,
this.DMS
}/api/3/action/resource_show?id=${resourceId}`,
3 3
); );
const responseData = await response.json(); const responseData = await response.json();
@@ -359,17 +325,14 @@ export default class CKAN {
} }
async getResourceInfo(resourceId: string) { async getResourceInfo(resourceId: string) {
const response = await fetch( const response = await fetch(`${this.DMS}/api/3/action/datastore_info`, {
`${this.DMS}/api/3/action/datastore_info`,
{
method: 'POST', method: 'POST',
headers: { headers: {
Accept: 'application/json', Accept: 'application/json',
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
body: JSON.stringify({ resource_id: resourceId }), body: JSON.stringify({ resource_id: resourceId }),
} });
);
const responseData = await response.json(); const responseData = await response.json();
const resourceInfo: Array<ResourceInfo> = responseData.result; const resourceInfo: Array<ResourceInfo> = responseData.result;
return resourceInfo; return resourceInfo;
@@ -377,9 +340,7 @@ export default class CKAN {
async getFacetFields(field: 'res_format' | 'tags') { async getFacetFields(field: 'res_format' | 'tags') {
const response = await fetchRetry( const response = await fetchRetry(
`${ `${this.DMS}/api/3/action/package_search?facet.field=["${field}"]&rows=0`,
this.DMS
}/api/3/action/package_search?facet.field=["${field}"]&rows=0`,
3 3
); );
const responseData = await response.json(); const responseData = await response.json();

View File

@@ -9,10 +9,14 @@ export function getDaysAgo(date: string) {
return (+today - +createdOn) / msInDay; return (+today - +createdOn) / msInDay;
} }
export default async function fetchRetry(url: string, n: number): Promise<any> { export default async function fetchRetry(
url: string,
n: number,
opts: Partial<RequestInit> = {}
): Promise<any> {
const abortController = new AbortController(); const abortController = new AbortController();
const id = setTimeout(() => abortController.abort(), 30000); const id = setTimeout(() => abortController.abort(), 30000);
const res = await fetch(url, { signal: abortController.signal }); const res = await fetch(url, { signal: abortController.signal, ...opts });
clearTimeout(id); clearTimeout(id);
if (!res.ok && n && n > 0) { if (!res.ok && n && n > 0) {
return await fetchRetry(url, n - 1); return await fetchRetry(url, n - 1);
@@ -21,13 +25,13 @@ export default async function fetchRetry(url: string, n: number): Promise<any> {
} }
export function removeTag(tag?: string) { export function removeTag(tag?: string) {
if (tag === "{{description}}" || !tag) { if (tag === '{{description}}' || !tag) {
return undefined; return undefined;
} }
if (typeof window !== "undefined") { if (typeof window !== 'undefined') {
const div = document.createElement("div"); const div = document.createElement('div');
div.innerHTML = tag; div.innerHTML = tag;
return div.textContent || div.innerText || ""; return div.textContent || div.innerText || '';
} }
return tag; return tag;
} }
@@ -38,10 +42,10 @@ export function convertFieldSchema(
) { ) {
function convertToGraphqlString(fieldName: string) { function convertToGraphqlString(fieldName: string) {
return fieldName return fieldName
.replaceAll(" ", "_") .replaceAll(' ', '_')
.replaceAll("(", "_") .replaceAll('(', '_')
.replaceAll(")", "_") .replaceAll(')', '_')
.replace(/[^\w\s]|(_)\1/gi, "_"); .replace(/[^\w\s]|(_)\1/gi, '_');
} }
const entries = Object.entries(schema); const entries = Object.entries(schema);
return { return {