@frictionless-ts/dataset 1.0.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/README.md +3 -0
- package/build/file/copy.d.ts +4 -0
- package/build/file/copy.js +7 -0
- package/build/file/copy.spec.d.ts +1 -0
- package/build/file/copy.spec.js +104 -0
- package/build/file/describe.d.ts +7 -0
- package/build/file/describe.js +9 -0
- package/build/file/fetch.d.ts +2 -0
- package/build/file/fetch.js +21 -0
- package/build/file/index.d.ts +9 -0
- package/build/file/index.js +10 -0
- package/build/file/infer.d.ts +10 -0
- package/build/file/infer.js +48 -0
- package/build/file/infer.spec.d.ts +1 -0
- package/build/file/infer.spec.js +141 -0
- package/build/file/load.d.ts +3 -0
- package/build/file/load.js +7 -0
- package/build/file/path.d.ts +2 -0
- package/build/file/path.js +17 -0
- package/build/file/save.d.ts +3 -0
- package/build/file/save.js +7 -0
- package/build/file/temp.d.ts +11 -0
- package/build/file/temp.js +23 -0
- package/build/file/validate.d.ts +6 -0
- package/build/file/validate.js +47 -0
- package/build/file/validate.spec.d.ts +1 -0
- package/build/file/validate.spec.js +180 -0
- package/build/folder/create.d.ts +1 -0
- package/build/folder/create.js +5 -0
- package/build/folder/index.d.ts +2 -0
- package/build/folder/index.js +3 -0
- package/build/folder/temp.d.ts +3 -0
- package/build/folder/temp.js +16 -0
- package/build/index.d.ts +36 -0
- package/build/index.js +35 -0
- package/build/package/index.d.ts +2 -0
- package/build/package/index.js +3 -0
- package/build/package/merge.d.ts +23 -0
- package/build/package/merge.js +12 -0
- package/build/package/path.d.ts +3 -0
- package/build/package/path.js +43 -0
- package/build/package/path.spec.d.ts +1 -0
- package/build/package/path.spec.js +56 -0
- package/build/plugin.d.ts +11 -0
- package/build/plugin.js +2 -0
- package/build/plugins/ckan/ckan/index.d.ts +1 -0
- package/build/plugins/ckan/ckan/index.js +2 -0
- package/build/plugins/ckan/ckan/request.d.ts +11 -0
- package/build/plugins/ckan/ckan/request.js +35 -0
- package/build/plugins/ckan/index.d.ts +4 -0
- package/build/plugins/ckan/index.js +5 -0
- package/build/plugins/ckan/package/Organization.d.ts +21 -0
- package/build/plugins/ckan/package/Organization.js +2 -0
- package/build/plugins/ckan/package/Package.d.ts +76 -0
- package/build/plugins/ckan/package/Package.js +2 -0
- package/build/plugins/ckan/package/Tag.d.ts +17 -0
- package/build/plugins/ckan/package/Tag.js +2 -0
- package/build/plugins/ckan/package/convert/fromCkan.d.ts +3 -0
- package/build/plugins/ckan/package/convert/fromCkan.js +63 -0
- package/build/plugins/ckan/package/convert/fromCkan.spec.d.ts +1 -0
- package/build/plugins/ckan/package/convert/fromCkan.spec.js +80 -0
- package/build/plugins/ckan/package/convert/toCkan.d.ts +22 -0
- package/build/plugins/ckan/package/convert/toCkan.js +51 -0
- package/build/plugins/ckan/package/convert/toCkan.spec.d.ts +1 -0
- package/build/plugins/ckan/package/convert/toCkan.spec.js +153 -0
- package/build/plugins/ckan/package/fixtures/ckan-package.json +308 -0
- package/build/plugins/ckan/package/index.d.ts +7 -0
- package/build/plugins/ckan/package/index.js +5 -0
- package/build/plugins/ckan/package/load.d.ts +21 -0
- package/build/plugins/ckan/package/load.js +74 -0
- package/build/plugins/ckan/package/load.spec.d.ts +1 -0
- package/build/plugins/ckan/package/load.spec.js +11 -0
- package/build/plugins/ckan/package/save.d.ts +10 -0
- package/build/plugins/ckan/package/save.js +83 -0
- package/build/plugins/ckan/package/save.spec.d.ts +1 -0
- package/build/plugins/ckan/package/save.spec.js +319 -0
- package/build/plugins/ckan/plugin.d.ts +19 -0
- package/build/plugins/ckan/plugin.js +18 -0
- package/build/plugins/ckan/plugin.spec.d.ts +1 -0
- package/build/plugins/ckan/plugin.spec.js +83 -0
- package/build/plugins/ckan/resource/Resource.d.ts +56 -0
- package/build/plugins/ckan/resource/Resource.js +2 -0
- package/build/plugins/ckan/resource/convert/fromCkan.d.ts +3 -0
- package/build/plugins/ckan/resource/convert/fromCkan.js +39 -0
- package/build/plugins/ckan/resource/convert/toCkan.d.ts +3 -0
- package/build/plugins/ckan/resource/convert/toCkan.js +20 -0
- package/build/plugins/ckan/resource/index.d.ts +3 -0
- package/build/plugins/ckan/resource/index.js +3 -0
- package/build/plugins/ckan/schema/Field.d.ts +34 -0
- package/build/plugins/ckan/schema/Field.js +2 -0
- package/build/plugins/ckan/schema/Schema.d.ts +10 -0
- package/build/plugins/ckan/schema/Schema.js +2 -0
- package/build/plugins/ckan/schema/convert/fixtures/ckan-schema.json +115 -0
- package/build/plugins/ckan/schema/convert/fromCkan.d.ts +3 -0
- package/build/plugins/ckan/schema/convert/fromCkan.js +47 -0
- package/build/plugins/ckan/schema/convert/fromCkan.spec.d.ts +1 -0
- package/build/plugins/ckan/schema/convert/fromCkan.spec.js +157 -0
- package/build/plugins/ckan/schema/convert/toCkan.d.ts +3 -0
- package/build/plugins/ckan/schema/convert/toCkan.js +50 -0
- package/build/plugins/ckan/schema/convert/toCkan.spec.d.ts +1 -0
- package/build/plugins/ckan/schema/convert/toCkan.spec.js +278 -0
- package/build/plugins/ckan/schema/index.d.ts +4 -0
- package/build/plugins/ckan/schema/index.js +3 -0
- package/build/plugins/datahub/index.d.ts +2 -0
- package/build/plugins/datahub/index.js +3 -0
- package/build/plugins/datahub/package/index.d.ts +1 -0
- package/build/plugins/datahub/package/index.js +2 -0
- package/build/plugins/datahub/package/load.d.ts +1 -0
- package/build/plugins/datahub/package/load.js +9 -0
- package/build/plugins/datahub/package/load.spec.d.ts +1 -0
- package/build/plugins/datahub/package/load.spec.js +11 -0
- package/build/plugins/datahub/plugin.d.ts +4 -0
- package/build/plugins/datahub/plugin.js +18 -0
- package/build/plugins/datahub/plugin.spec.d.ts +1 -0
- package/build/plugins/datahub/plugin.spec.js +78 -0
- package/build/plugins/descriptor/index.d.ts +1 -0
- package/build/plugins/descriptor/index.js +2 -0
- package/build/plugins/descriptor/plugin.d.ts +11 -0
- package/build/plugins/descriptor/plugin.js +29 -0
- package/build/plugins/descriptor/plugin.spec.d.ts +1 -0
- package/build/plugins/descriptor/plugin.spec.js +169 -0
- package/build/plugins/folder/index.d.ts +2 -0
- package/build/plugins/folder/index.js +3 -0
- package/build/plugins/folder/package/index.d.ts +2 -0
- package/build/plugins/folder/package/index.js +3 -0
- package/build/plugins/folder/package/load.d.ts +1 -0
- package/build/plugins/folder/package/load.js +6 -0
- package/build/plugins/folder/package/load.spec.d.ts +1 -0
- package/build/plugins/folder/package/load.spec.js +175 -0
- package/build/plugins/folder/package/save.d.ts +7 -0
- package/build/plugins/folder/package/save.js +35 -0
- package/build/plugins/folder/package/save.spec.d.ts +1 -0
- package/build/plugins/folder/package/save.spec.js +328 -0
- package/build/plugins/folder/plugin.d.ts +4 -0
- package/build/plugins/folder/plugin.js +19 -0
- package/build/plugins/folder/plugin.spec.d.ts +1 -0
- package/build/plugins/folder/plugin.spec.js +53 -0
- package/build/plugins/github/github/index.d.ts +1 -0
- package/build/plugins/github/github/index.js +2 -0
- package/build/plugins/github/github/path.d.ts +1 -0
- package/build/plugins/github/github/path.js +4 -0
- package/build/plugins/github/github/request.d.ts +15 -0
- package/build/plugins/github/github/request.js +43 -0
- package/build/plugins/github/index.d.ts +3 -0
- package/build/plugins/github/index.js +4 -0
- package/build/plugins/github/package/License.d.ts +21 -0
- package/build/plugins/github/package/License.js +2 -0
- package/build/plugins/github/package/Owner.d.ts +25 -0
- package/build/plugins/github/package/Owner.js +2 -0
- package/build/plugins/github/package/Package.d.ts +87 -0
- package/build/plugins/github/package/Package.js +2 -0
- package/build/plugins/github/package/convert/fromGithub.d.ts +3 -0
- package/build/plugins/github/package/convert/fromGithub.js +50 -0
- package/build/plugins/github/package/index.d.ts +6 -0
- package/build/plugins/github/package/index.js +4 -0
- package/build/plugins/github/package/load.d.ts +23 -0
- package/build/plugins/github/package/load.js +48 -0
- package/build/plugins/github/package/load.spec.d.ts +1 -0
- package/build/plugins/github/package/load.spec.js +15 -0
- package/build/plugins/github/package/save.d.ts +14 -0
- package/build/plugins/github/package/save.js +69 -0
- package/build/plugins/github/package/save.spec.d.ts +1 -0
- package/build/plugins/github/package/save.spec.js +566 -0
- package/build/plugins/github/plugin.d.ts +19 -0
- package/build/plugins/github/plugin.js +18 -0
- package/build/plugins/github/plugin.spec.d.ts +1 -0
- package/build/plugins/github/plugin.spec.js +73 -0
- package/build/plugins/github/resource/Resource.d.ts +29 -0
- package/build/plugins/github/resource/Resource.js +2 -0
- package/build/plugins/github/resource/convert/fromGithub.d.ts +5 -0
- package/build/plugins/github/resource/convert/fromGithub.js +24 -0
- package/build/plugins/github/resource/convert/toGithub.d.ts +3 -0
- package/build/plugins/github/resource/convert/toGithub.js +10 -0
- package/build/plugins/github/resource/index.d.ts +3 -0
- package/build/plugins/github/resource/index.js +3 -0
- package/build/plugins/zenodo/index.d.ts +3 -0
- package/build/plugins/zenodo/index.js +4 -0
- package/build/plugins/zenodo/package/Creator.d.ts +20 -0
- package/build/plugins/zenodo/package/Creator.js +2 -0
- package/build/plugins/zenodo/package/Package.d.ts +94 -0
- package/build/plugins/zenodo/package/Package.js +2 -0
- package/build/plugins/zenodo/package/convert/fromZenodo.d.ts +3 -0
- package/build/plugins/zenodo/package/convert/fromZenodo.js +43 -0
- package/build/plugins/zenodo/package/convert/toZenodo.d.ts +3 -0
- package/build/plugins/zenodo/package/convert/toZenodo.js +79 -0
- package/build/plugins/zenodo/package/index.d.ts +6 -0
- package/build/plugins/zenodo/package/index.js +5 -0
- package/build/plugins/zenodo/package/load.d.ts +23 -0
- package/build/plugins/zenodo/package/load.js +45 -0
- package/build/plugins/zenodo/package/load.spec.d.ts +1 -0
- package/build/plugins/zenodo/package/load.spec.js +15 -0
- package/build/plugins/zenodo/package/save.d.ts +13 -0
- package/build/plugins/zenodo/package/save.js +74 -0
- package/build/plugins/zenodo/package/save.spec.d.ts +1 -0
- package/build/plugins/zenodo/package/save.spec.js +524 -0
- package/build/plugins/zenodo/plugin.d.ts +19 -0
- package/build/plugins/zenodo/plugin.js +18 -0
- package/build/plugins/zenodo/plugin.spec.d.ts +1 -0
- package/build/plugins/zenodo/plugin.spec.js +78 -0
- package/build/plugins/zenodo/resource/Resource.d.ts +27 -0
- package/build/plugins/zenodo/resource/Resource.js +2 -0
- package/build/plugins/zenodo/resource/convert/fromZenodo.d.ts +10 -0
- package/build/plugins/zenodo/resource/convert/fromZenodo.js +18 -0
- package/build/plugins/zenodo/resource/convert/toZenodo.d.ts +3 -0
- package/build/plugins/zenodo/resource/convert/toZenodo.js +13 -0
- package/build/plugins/zenodo/resource/index.d.ts +3 -0
- package/build/plugins/zenodo/resource/index.js +3 -0
- package/build/plugins/zenodo/zenodo/index.d.ts +1 -0
- package/build/plugins/zenodo/zenodo/index.js +2 -0
- package/build/plugins/zenodo/zenodo/request.d.ts +12 -0
- package/build/plugins/zenodo/zenodo/request.js +36 -0
- package/build/plugins/zip/index.d.ts +2 -0
- package/build/plugins/zip/index.js +3 -0
- package/build/plugins/zip/package/index.d.ts +2 -0
- package/build/plugins/zip/package/index.js +3 -0
- package/build/plugins/zip/package/load.d.ts +1 -0
- package/build/plugins/zip/package/load.js +30 -0
- package/build/plugins/zip/package/load.spec.d.ts +1 -0
- package/build/plugins/zip/package/load.spec.js +173 -0
- package/build/plugins/zip/package/save.d.ts +5 -0
- package/build/plugins/zip/package/save.js +50 -0
- package/build/plugins/zip/package/save.spec.d.ts +1 -0
- package/build/plugins/zip/package/save.spec.js +287 -0
- package/build/plugins/zip/plugin.d.ts +11 -0
- package/build/plugins/zip/plugin.js +24 -0
- package/build/plugins/zip/plugin.spec.d.ts +1 -0
- package/build/plugins/zip/plugin.spec.js +158 -0
- package/build/resource/index.d.ts +1 -0
- package/build/resource/index.js +2 -0
- package/build/resource/save.d.ts +13 -0
- package/build/resource/save.js +53 -0
- package/build/resource/save.spec.d.ts +1 -0
- package/build/resource/save.spec.js +107 -0
- package/build/stream/concat.d.ts +3 -0
- package/build/stream/concat.js +5 -0
- package/build/stream/index.d.ts +3 -0
- package/build/stream/index.js +4 -0
- package/build/stream/load.d.ts +5 -0
- package/build/stream/load.js +46 -0
- package/build/stream/save.d.ts +5 -0
- package/build/stream/save.js +13 -0
- package/package.json +48 -0
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import { access, readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { beforeEach, describe, expect, it } from "vitest";
|
|
4
|
+
import { getTempFilePath, writeTempFile } from "../../../file/index.js";
|
|
5
|
+
import { loadPackageFromFolder } from "./load.js";
|
|
6
|
+
import { savePackageToFolder } from "./save.js";
|
|
7
|
+
describe("savePackageToFolder", () => {
|
|
8
|
+
let tempFolderPath;
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
tempFolderPath = getTempFilePath();
|
|
11
|
+
});
|
|
12
|
+
it("should save a basic package to folder", async () => {
|
|
13
|
+
const dataPackage = {
|
|
14
|
+
name: "test-package",
|
|
15
|
+
resources: [
|
|
16
|
+
{
|
|
17
|
+
name: "test-resource",
|
|
18
|
+
data: [],
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
};
|
|
22
|
+
await savePackageToFolder(dataPackage, { folderPath: tempFolderPath });
|
|
23
|
+
const descriptorPath = join(tempFolderPath, "datapackage.json");
|
|
24
|
+
await expect(access(descriptorPath)).resolves.toBeUndefined();
|
|
25
|
+
});
|
|
26
|
+
it("should save package with metadata", async () => {
|
|
27
|
+
const dataPackage = {
|
|
28
|
+
name: "test-package",
|
|
29
|
+
title: "Test Package",
|
|
30
|
+
description: "A test package",
|
|
31
|
+
version: "1.0.0",
|
|
32
|
+
resources: [
|
|
33
|
+
{
|
|
34
|
+
name: "test-resource",
|
|
35
|
+
data: [],
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
};
|
|
39
|
+
await savePackageToFolder(dataPackage, { folderPath: tempFolderPath });
|
|
40
|
+
const descriptorPath = join(tempFolderPath, "datapackage.json");
|
|
41
|
+
await expect(access(descriptorPath)).resolves.toBeUndefined();
|
|
42
|
+
});
|
|
43
|
+
it("should save package with inline data resources", async () => {
|
|
44
|
+
const dataPackage = {
|
|
45
|
+
name: "test-package",
|
|
46
|
+
resources: [
|
|
47
|
+
{
|
|
48
|
+
name: "test-resource",
|
|
49
|
+
data: [
|
|
50
|
+
{ id: 1, name: "alice" },
|
|
51
|
+
{ id: 2, name: "bob" },
|
|
52
|
+
],
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
};
|
|
56
|
+
await savePackageToFolder(dataPackage, { folderPath: tempFolderPath });
|
|
57
|
+
const descriptorPath = join(tempFolderPath, "datapackage.json");
|
|
58
|
+
await expect(access(descriptorPath)).resolves.toBeUndefined();
|
|
59
|
+
});
|
|
60
|
+
it("should save package with file resources", async () => {
|
|
61
|
+
const csvContent = "id,name\n1,alice\n2,bob";
|
|
62
|
+
const csvPath = await writeTempFile(csvContent);
|
|
63
|
+
const dataPackage = {
|
|
64
|
+
name: "test-package",
|
|
65
|
+
resources: [
|
|
66
|
+
{
|
|
67
|
+
name: "test-resource",
|
|
68
|
+
path: csvPath,
|
|
69
|
+
format: "csv",
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
};
|
|
73
|
+
await savePackageToFolder(dataPackage, { folderPath: tempFolderPath });
|
|
74
|
+
const descriptorPath = join(tempFolderPath, "datapackage.json");
|
|
75
|
+
await expect(access(descriptorPath)).resolves.toBeUndefined();
|
|
76
|
+
});
|
|
77
|
+
it("should save package with multiple resources", async () => {
|
|
78
|
+
const csvContent = "id,name\n1,alice\n2,bob";
|
|
79
|
+
const csvPath = await writeTempFile(csvContent);
|
|
80
|
+
const dataPackage = {
|
|
81
|
+
name: "test-package",
|
|
82
|
+
resources: [
|
|
83
|
+
{
|
|
84
|
+
name: "resource-1",
|
|
85
|
+
path: csvPath,
|
|
86
|
+
format: "csv",
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: "resource-2",
|
|
90
|
+
data: [{ id: 1, value: 100 }],
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
};
|
|
94
|
+
await savePackageToFolder(dataPackage, { folderPath: tempFolderPath });
|
|
95
|
+
const descriptorPath = join(tempFolderPath, "datapackage.json");
|
|
96
|
+
await expect(access(descriptorPath)).resolves.toBeUndefined();
|
|
97
|
+
});
|
|
98
|
+
it("should save package with schema", async () => {
|
|
99
|
+
const dataPackage = {
|
|
100
|
+
name: "test-package",
|
|
101
|
+
resources: [
|
|
102
|
+
{
|
|
103
|
+
name: "test-resource",
|
|
104
|
+
data: [{ id: 1, name: "alice" }],
|
|
105
|
+
schema: {
|
|
106
|
+
fields: [
|
|
107
|
+
{ name: "id", type: "integer" },
|
|
108
|
+
{ name: "name", type: "string" },
|
|
109
|
+
],
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
};
|
|
114
|
+
await savePackageToFolder(dataPackage, { folderPath: tempFolderPath });
|
|
115
|
+
const descriptorPath = join(tempFolderPath, "datapackage.json");
|
|
116
|
+
await expect(access(descriptorPath)).resolves.toBeUndefined();
|
|
117
|
+
});
|
|
118
|
+
it("should save package with dialect", async () => {
|
|
119
|
+
const csvContent = "id;name\n1;alice\n2;bob";
|
|
120
|
+
const csvPath = await writeTempFile(csvContent);
|
|
121
|
+
const dataPackage = {
|
|
122
|
+
name: "test-package",
|
|
123
|
+
resources: [
|
|
124
|
+
{
|
|
125
|
+
name: "test-resource",
|
|
126
|
+
path: csvPath,
|
|
127
|
+
format: "csv",
|
|
128
|
+
dialect: {
|
|
129
|
+
delimiter: ";",
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
],
|
|
133
|
+
};
|
|
134
|
+
await savePackageToFolder(dataPackage, { folderPath: tempFolderPath });
|
|
135
|
+
const descriptorPath = join(tempFolderPath, "datapackage.json");
|
|
136
|
+
await expect(access(descriptorPath)).resolves.toBeUndefined();
|
|
137
|
+
});
|
|
138
|
+
it("should save and reload package with same structure", async () => {
|
|
139
|
+
const originalPackage = {
|
|
140
|
+
name: "test-package",
|
|
141
|
+
title: "Test Package",
|
|
142
|
+
description: "A test package",
|
|
143
|
+
resources: [
|
|
144
|
+
{
|
|
145
|
+
name: "test-resource",
|
|
146
|
+
data: [{ id: 1, name: "alice" }],
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
};
|
|
150
|
+
await savePackageToFolder(originalPackage, { folderPath: tempFolderPath });
|
|
151
|
+
const reloadedPackage = await loadPackageFromFolder(tempFolderPath);
|
|
152
|
+
expect(reloadedPackage).toBeDefined();
|
|
153
|
+
expect(reloadedPackage.name).toBe("test-package");
|
|
154
|
+
expect(reloadedPackage.title).toBe("Test Package");
|
|
155
|
+
expect(reloadedPackage.description).toBe("A test package");
|
|
156
|
+
expect(reloadedPackage.resources).toHaveLength(1);
|
|
157
|
+
expect(reloadedPackage.resources[0]?.name).toBe("test-resource");
|
|
158
|
+
});
|
|
159
|
+
it("should save and reload package preserving metadata", async () => {
|
|
160
|
+
const originalPackage = {
|
|
161
|
+
name: "test-package",
|
|
162
|
+
title: "Test Package",
|
|
163
|
+
description: "A test package",
|
|
164
|
+
version: "1.0.0",
|
|
165
|
+
keywords: ["test", "package"],
|
|
166
|
+
resources: [
|
|
167
|
+
{
|
|
168
|
+
name: "test-resource",
|
|
169
|
+
data: [{ id: 1 }],
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
};
|
|
173
|
+
await savePackageToFolder(originalPackage, { folderPath: tempFolderPath });
|
|
174
|
+
const reloadedPackage = await loadPackageFromFolder(tempFolderPath);
|
|
175
|
+
expect(reloadedPackage.name).toBe("test-package");
|
|
176
|
+
expect(reloadedPackage.title).toBe("Test Package");
|
|
177
|
+
expect(reloadedPackage.version).toBe("1.0.0");
|
|
178
|
+
expect(reloadedPackage.keywords).toEqual(["test", "package"]);
|
|
179
|
+
});
|
|
180
|
+
it("should save and reload package with schema", async () => {
|
|
181
|
+
const originalPackage = {
|
|
182
|
+
name: "test-package",
|
|
183
|
+
resources: [
|
|
184
|
+
{
|
|
185
|
+
name: "test-resource",
|
|
186
|
+
data: [{ id: 1, name: "alice" }],
|
|
187
|
+
schema: {
|
|
188
|
+
fields: [
|
|
189
|
+
{ name: "id", type: "integer" },
|
|
190
|
+
{ name: "name", type: "string" },
|
|
191
|
+
],
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
],
|
|
195
|
+
};
|
|
196
|
+
await savePackageToFolder(originalPackage, { folderPath: tempFolderPath });
|
|
197
|
+
const reloadedPackage = await loadPackageFromFolder(tempFolderPath);
|
|
198
|
+
const schema = reloadedPackage.resources[0]?.schema;
|
|
199
|
+
expect(schema).toBeDefined();
|
|
200
|
+
expect(typeof schema === "object" && "fields" in schema).toBe(true);
|
|
201
|
+
if (typeof schema === "object" && "fields" in schema) {
|
|
202
|
+
expect(schema.fields).toHaveLength(2);
|
|
203
|
+
expect(schema.fields?.[0]?.name).toBe("id");
|
|
204
|
+
expect(schema.fields?.[1]?.name).toBe("name");
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
it("should save and reload package with file resources", async () => {
|
|
208
|
+
const csvContent = "id,name\n1,alice\n2,bob";
|
|
209
|
+
const csvPath = await writeTempFile(csvContent);
|
|
210
|
+
const originalPackage = {
|
|
211
|
+
name: "test-package",
|
|
212
|
+
resources: [
|
|
213
|
+
{
|
|
214
|
+
name: "test-resource",
|
|
215
|
+
path: csvPath,
|
|
216
|
+
format: "csv",
|
|
217
|
+
},
|
|
218
|
+
],
|
|
219
|
+
};
|
|
220
|
+
await savePackageToFolder(originalPackage, { folderPath: tempFolderPath });
|
|
221
|
+
const reloadedPackage = await loadPackageFromFolder(tempFolderPath);
|
|
222
|
+
expect(reloadedPackage.resources).toHaveLength(1);
|
|
223
|
+
expect(reloadedPackage.resources[0]?.name).toBe("test-resource");
|
|
224
|
+
expect(reloadedPackage.resources[0]?.format).toBe("csv");
|
|
225
|
+
});
|
|
226
|
+
it("should throw error when saving to existing folder", async () => {
|
|
227
|
+
const dataPackage = {
|
|
228
|
+
name: "test-package",
|
|
229
|
+
resources: [
|
|
230
|
+
{
|
|
231
|
+
name: "test-resource",
|
|
232
|
+
data: [],
|
|
233
|
+
},
|
|
234
|
+
],
|
|
235
|
+
};
|
|
236
|
+
const fs = await import("node:fs/promises");
|
|
237
|
+
await fs.mkdir(tempFolderPath, { recursive: true });
|
|
238
|
+
await fs.writeFile(join(tempFolderPath, "existing.txt"), "content");
|
|
239
|
+
await expect(savePackageToFolder(dataPackage, { folderPath: tempFolderPath })).rejects.toThrow();
|
|
240
|
+
});
|
|
241
|
+
it("should create valid folder structure", async () => {
|
|
242
|
+
const dataPackage = {
|
|
243
|
+
name: "test-package",
|
|
244
|
+
resources: [
|
|
245
|
+
{
|
|
246
|
+
name: "test-resource",
|
|
247
|
+
data: [{ id: 1 }],
|
|
248
|
+
},
|
|
249
|
+
],
|
|
250
|
+
};
|
|
251
|
+
await savePackageToFolder(dataPackage, { folderPath: tempFolderPath });
|
|
252
|
+
const reloadedPackage = await loadPackageFromFolder(tempFolderPath);
|
|
253
|
+
expect(reloadedPackage).toMatchObject({
|
|
254
|
+
name: "test-package",
|
|
255
|
+
resources: [
|
|
256
|
+
{
|
|
257
|
+
name: "test-resource",
|
|
258
|
+
},
|
|
259
|
+
],
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
it("should save package with multiple file resources", async () => {
|
|
263
|
+
const csv1Content = "id,name\n1,alice";
|
|
264
|
+
const csv2Content = "id,value\n1,100";
|
|
265
|
+
const csv1Path = await writeTempFile(csv1Content);
|
|
266
|
+
const csv2Path = await writeTempFile(csv2Content);
|
|
267
|
+
const originalPackage = {
|
|
268
|
+
name: "test-package",
|
|
269
|
+
resources: [
|
|
270
|
+
{
|
|
271
|
+
name: "resource-1",
|
|
272
|
+
path: csv1Path,
|
|
273
|
+
format: "csv",
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
name: "resource-2",
|
|
277
|
+
path: csv2Path,
|
|
278
|
+
format: "csv",
|
|
279
|
+
},
|
|
280
|
+
],
|
|
281
|
+
};
|
|
282
|
+
await savePackageToFolder(originalPackage, { folderPath: tempFolderPath });
|
|
283
|
+
const reloadedPackage = await loadPackageFromFolder(tempFolderPath);
|
|
284
|
+
expect(reloadedPackage.resources).toHaveLength(2);
|
|
285
|
+
expect(reloadedPackage.resources[0]?.name).toBe("resource-1");
|
|
286
|
+
expect(reloadedPackage.resources[1]?.name).toBe("resource-2");
|
|
287
|
+
});
|
|
288
|
+
it("should create datapackage.json in folder", async () => {
|
|
289
|
+
const dataPackage = {
|
|
290
|
+
name: "test-package",
|
|
291
|
+
resources: [
|
|
292
|
+
{
|
|
293
|
+
name: "test-resource",
|
|
294
|
+
data: [{ id: 1 }],
|
|
295
|
+
},
|
|
296
|
+
],
|
|
297
|
+
};
|
|
298
|
+
await savePackageToFolder(dataPackage, { folderPath: tempFolderPath });
|
|
299
|
+
const descriptorPath = join(tempFolderPath, "datapackage.json");
|
|
300
|
+
const descriptorContent = await readFile(descriptorPath, "utf-8");
|
|
301
|
+
const descriptor = JSON.parse(descriptorContent);
|
|
302
|
+
expect(descriptor.name).toBe("test-package");
|
|
303
|
+
expect(descriptor.resources).toHaveLength(1);
|
|
304
|
+
});
|
|
305
|
+
it("should copy file resources to folder", async () => {
|
|
306
|
+
const csvContent = "id,name\n1,alice\n2,bob";
|
|
307
|
+
const csvPath = await writeTempFile(csvContent);
|
|
308
|
+
const dataPackage = {
|
|
309
|
+
name: "test-package",
|
|
310
|
+
resources: [
|
|
311
|
+
{
|
|
312
|
+
name: "test-resource",
|
|
313
|
+
path: csvPath,
|
|
314
|
+
format: "csv",
|
|
315
|
+
},
|
|
316
|
+
],
|
|
317
|
+
};
|
|
318
|
+
await savePackageToFolder(dataPackage, { folderPath: tempFolderPath });
|
|
319
|
+
const descriptorPath = join(tempFolderPath, "datapackage.json");
|
|
320
|
+
const descriptorContent = await readFile(descriptorPath, "utf-8");
|
|
321
|
+
const descriptor = JSON.parse(descriptorContent);
|
|
322
|
+
const resourcePath = descriptor.resources[0].path;
|
|
323
|
+
const resourceFilePath = join(tempFolderPath, resourcePath);
|
|
324
|
+
const resourceContent = await readFile(resourceFilePath, "utf-8");
|
|
325
|
+
expect(resourceContent).toBe(csvContent);
|
|
326
|
+
});
|
|
327
|
+
});
|
|
328
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2F2ZS5zcGVjLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcGx1Z2lucy9mb2xkZXIvcGFja2FnZS9zYXZlLnNwZWMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQTtBQUNuRCxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sV0FBVyxDQUFBO0FBRWhDLE9BQU8sRUFBRSxVQUFVLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQUUsTUFBTSxRQUFRLENBQUE7QUFDekQsT0FBTyxFQUFFLGVBQWUsRUFBRSxhQUFhLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQTtBQUN2RSxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxXQUFXLENBQUE7QUFDakQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sV0FBVyxDQUFBO0FBRS9DLFFBQVEsQ0FBQyxxQkFBcUIsRUFBRSxHQUFHLEVBQUU7SUFDbkMsSUFBSSxjQUFzQixDQUFBO0lBRTFCLFVBQVUsQ0FBQyxHQUFHLEVBQUU7UUFDZCxjQUFjLEdBQUcsZUFBZSxFQUFFLENBQUE7SUFDcEMsQ0FBQyxDQUFDLENBQUE7SUFFRixFQUFFLENBQUMsdUNBQXVDLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDckQsTUFBTSxXQUFXLEdBQVk7WUFDM0IsSUFBSSxFQUFFLGNBQWM7WUFDcEIsU0FBUyxFQUFFO2dCQUNUO29CQUNFLElBQUksRUFBRSxlQUFlO29CQUNyQixJQUFJLEVBQUUsRUFBRTtpQkFDVDthQUNGO1NBQ0YsQ0FBQTtRQUVELE1BQU0sbUJBQW1CLENBQUMsV0FBVyxFQUFFLEVBQUUsVUFBVSxFQUFFLGNBQWMsRUFBRSxDQUFDLENBQUE7UUFFdEUsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLGNBQWMsRUFBRSxrQkFBa0IsQ0FBQyxDQUFBO1FBQy9ELE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FB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RyxNQUFNLGFBQWEsQ0FBQyxVQUFVLENBQUMsQ0FBQTtRQUUvQyxNQUFNLFdBQVcsR0FBWTtZQUMzQixJQUFJLEVBQUUsY0FBYztZQUNwQixTQUFTLEVBQUU7Z0JBQ1Q7b0JBQ0UsSUFBSSxFQUFFLGVBQWU7b0JBQ3JCLElBQUksRUFBRSxPQUFPO29CQUNiLE1BQU0sRUFBRSxLQUFLO2lCQUNkO2FBQ0Y7U0FDRixDQUFBO1FBRUQsTUFBTSxtQkFBbUIsQ0FBQyxXQUFXLEVBQUUsRUFBRSxVQUFVLEVBQUUsY0FBYyxFQUFFLENBQUMsQ0FBQTtRQUV0RSxNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsY0FBYyxFQUFFLGtCQUFrQixDQUFDLENBQUE7UUFDL0QsTUFBTSxpQkFBaUIsR0FBRyxNQUFNLFFBQVEsQ0FBQyxjQUFjLEVBQUUsT0FBTyxDQUFDLENBQUE7UUFDakUsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxDQUFBO1FBRWhELE1BQU0sWUFBWSxHQUFHLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFBO1FBQ2pELE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLGNBQWMsRUFBRSxZQUFZLENBQUMsQ0FBQTtRQUMzRCxNQUFNLGVBQWUsR0FBRyxNQUFNLFFBQVEsQ0FBQyxnQkFBZ0IsRUFBRSxPQUFPLENBQUMsQ0FBQTtRQUVqRSxNQUFNLENBQUMsZUFBZSxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFBO0lBQzFDLENBQUMsQ0FBQyxDQUFBO0FBQ0osQ0FBQyxDQUFDLENBQUEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBhY2Nlc3MsIHJlYWRGaWxlIH0gZnJvbSBcIm5vZGU6ZnMvcHJvbWlzZXNcIlxuaW1wb3J0IHsgam9pbiB9IGZyb20gXCJub2RlOnBhdGhcIlxuaW1wb3J0IHR5cGUgeyBQYWNrYWdlIH0gZnJvbSBcIkBmcmljdGlvbmxlc3MtdHMvbWV0YWRhdGFcIlxuaW1wb3J0IHsgYmVmb3JlRWFjaCwgZGVzY3JpYmUsIGV4cGVjdCwgaXQgfSBmcm9tIFwidml0ZXN0XCJcbmltcG9ydCB7IGdldFRlbXBGaWxlUGF0aCwgd3JpdGVUZW1wRmlsZSB9IGZyb20gXCIuLi8uLi8uLi9maWxlL2luZGV4LnRzXCJcbmltcG9ydCB7IGxvYWRQYWNrYWdlRnJvbUZvbGRlciB9IGZyb20gXCIuL2xvYWQudHNcIlxuaW1wb3J0IHsgc2F2ZVBhY2thZ2VUb0ZvbGRlciB9IGZyb20gXCIuL3NhdmUudHNcIlxuXG5kZXNjcmliZShcInNhdmVQYWNrYWdlVG9Gb2xkZXJcIiwgKCkgPT4ge1xuICBsZXQgdGVtcEZvbGRlclBhdGg6IHN0cmluZ1xuXG4gIGJlZm9yZUVhY2goKCkgPT4ge1xuICAgIHRlbXBGb2xkZXJQYXRoID0gZ2V0VGVtcEZpbGVQYXRoKClcbiAgfSlcblxuICBpdChcInNob3VsZCBzYXZlIGEgYmFzaWMgcGFja2FnZSB0byBmb2xkZXJcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGRhdGFQYWNrYWdlOiBQYWNrYWdlID0ge1xuICAgICAgbmFtZTogXCJ0ZXN0LXBhY2thZ2VcIixcbiAgICAgIHJlc291cmNlczogW1xuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogXCJ0ZXN0LXJlc291cmNlXCIsXG4gICAgICAgICAgZGF0YTogW10sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH1cblxuICAgIGF3YWl0IHNhdmVQYWNrYWdlVG9Gb2xkZXIoZGF0YVBhY2thZ2UsIHsgZm9sZGVyUGF0aDogdGVtcEZvbGRlclBhdGggfSlcblxuICAgIGNvbnN0IGRlc2NyaXB0b3JQYXRoID0gam9pbih0ZW1wRm9sZGVyUGF0aCwgXCJkYXRhcGFja2FnZS5qc29uXCIpXG4gICAgYXdhaXQgZXhwZWN0KGFjY2VzcyhkZXNjcmlwdG9yUGF0aCkpLnJlc29sdmVzLnRvQmVVbmRlZmluZWQoKVxuICB9KVxuXG4gIGl0KFwic2hvdWxkIHNhdmUgcGFja2FnZSB3aXRoIG1ldGFkYXRhXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBkYXRhUGFja2FnZTogUGFja2FnZSA9IHtcbiAgICAgIG5hbWU6IFwidGVzdC1wYWNrYWdlXCIsXG4gICAgICB0aXRsZTogXCJUZXN0IFBhY2thZ2VcIixcbiAgICAgIGRlc2NyaXB0aW9uOiBcIkEgdGVzdCBwYWNrYWdlXCIsXG4gICAgICB2ZXJzaW9uOiBcIjEuMC4wXCIsXG4gICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IFwidGVzdC1yZXNvdXJjZVwiLFxuICAgICAgICAgIGRhdGE6IFtdLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9XG5cbiAgICBhd2FpdCBzYXZlUGFja2FnZVRvRm9sZGVyKGRhdGFQYWNrYWdlLCB7IGZvbGRlclBhdGg6IHRlbXBGb2xkZXJQYXRoIH0pXG5cbiAgICBjb25zdCBkZXNjcmlwdG9yUGF0aCA9IGpvaW4odGVtcEZvbGRlclBhdGgsIFwiZGF0YXBhY2thZ2UuanNvblwiKVxuICAgIGF3YWl0IGV4cGVjdChhY2Nlc3MoZGVzY3JpcHRvclBhdGgpKS5yZXNvbHZlcy50b0JlVW5kZWZpbmVkKClcbiAgfSlcblxuICBpdChcInNob3VsZCBzYXZlIHBhY2thZ2Ugd2l0aCBpbmxpbmUgZGF0YSByZXNvdXJjZXNcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGRhdGFQYWNrYWdlOiBQYWNrYWdlID0ge1xuICAgICAgbmFtZTogXCJ0ZXN0LXBhY2thZ2VcIixcbiAgICAgIHJlc291cmNlczogW1xuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogXCJ0ZXN0LXJlc291cmNlXCIsXG4gICAgICAgICAgZGF0YTogW1xuICAgICAgICAgICAgeyBpZDogMSwgbmFtZTogXCJhbGljZVwiIH0sXG4gICAgICAgICAgICB7IGlkOiAyLCBuYW1lOiBcImJvYlwiIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfVxuXG4gICAgYXdhaXQgc2F2ZVBhY2thZ2VUb0ZvbGRlcihkYXRhUGFja2FnZSwgeyBmb2xkZXJQYXRoOiB0ZW1wRm9sZGVyUGF0aCB9KVxuXG4gICAgY29uc3QgZGVzY3JpcHRvclBhdGggPSBqb2luKHRlbXBGb2xkZXJQYXRoLCBcImRhdGFwYWNrYWdlLmpzb25cIilcbiAgICBhd2FpdCBleHBlY3QoYWNjZXNzKGRlc2NyaXB0b3JQYXRoKSkucmVzb2x2ZXMudG9CZVVuZGVmaW5lZCgpXG4gIH0pXG5cbiAgaXQoXCJzaG91bGQgc2F2ZSBwYWNrYWdlIHdpdGggZmlsZSByZXNvdXJjZXNcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGNzdkNvbnRlbnQgPSBcImlkLG5hbWVcXG4xLGFsaWNlXFxuMixib2JcIlxuICAgIGNvbnN0IGNzdlBhdGggPSBhd2FpdCB3cml0ZVRlbXBGaWxlKGNzdkNvbnRlbnQpXG5cbiAgICBjb25zdCBkYXRhUGFja2FnZTogUGFja2FnZSA9IHtcbiAgICAgIG5hbWU6IFwidGVzdC1wYWNrYWdlXCIsXG4gICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IFwidGVzdC1yZXNvdXJjZVwiLFxuICAgICAgICAgIHBhdGg6IGNzdlBhdGgsXG4gICAgICAgICAgZm9ybWF0OiBcImNzdlwiLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9XG5cbiAgICBhd2FpdCBzYXZlUGFja2FnZVRvRm9sZGVyKGRhdGFQYWNrYWdlLCB7IGZvbGRlclBhdGg6IHRlbXBGb2xkZXJQYXRoIH0pXG5cbiAgICBjb25zdCBkZXNjcmlwdG9yUGF0aCA9IGpvaW4odGVtcEZvbGRlclBhdGgsIFwiZGF0YXBhY2thZ2UuanNvblwiKVxuICAgIGF3YWl0IGV4cGVjdChhY2Nlc3MoZGVzY3JpcHRvclBhdGgpKS5yZXNvbHZlcy50b0JlVW5kZWZpbmVkKClcbiAgfSlcblxuICBpdChcInNob3VsZCBzYXZlIHBhY2thZ2Ugd2l0aCBtdWx0aXBsZSByZXNvdXJjZXNcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGNzdkNvbnRlbnQgPSBcImlkLG5hbWVcXG4xLGFsaWNlXFxuMixib2JcIlxuICAgIGNvbnN0IGNzdlBhdGggPSBhd2FpdCB3cml0ZVRlbXBGaWxlKGNzdkNvbnRlbnQpXG5cbiAgICBjb25zdCBkYXRhUGFja2FnZTogUGFja2FnZSA9IHtcbiAgICAgIG5hbWU6IFwidGVzdC1wYWNrYWdlXCIsXG4gICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IFwicmVzb3VyY2UtMVwiLFxuICAgICAgICAgIHBhdGg6IGNzdlBhdGgsXG4gICAgICAgICAgZm9ybWF0OiBcImNzdlwiLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogXCJyZXNvdXJjZS0yXCIsXG4gICAgICAgICAgZGF0YTogW3sgaWQ6IDEsIHZhbHVlOiAxMDAgfV0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH1cblxuICAgIGF3YWl0IHNhdmVQYWNrYWdlVG9Gb2xkZXIoZGF0YVBhY2thZ2UsIHsgZm9sZGVyUGF0aDogdGVtcEZvbGRlclBhdGggfSlcblxuICAgIGNvbnN0IGRlc2NyaXB0b3JQYXRoID0gam9pbih0ZW1wRm9sZGVyUGF0aCwgXCJkYXRhcGFja2FnZS5qc29uXCIpXG4gICAgYXdhaXQgZXhwZWN0KGFjY2VzcyhkZXNjcmlwdG9yUGF0aCkpLnJlc29sdmVzLnRvQmVVbmRlZmluZWQoKVxuICB9KVxuXG4gIGl0KFwic2hvdWxkIHNhdmUgcGFja2FnZSB3aXRoIHNjaGVtYVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZGF0YVBhY2thZ2U6IFBhY2thZ2UgPSB7XG4gICAgICBuYW1lOiBcInRlc3QtcGFja2FnZVwiLFxuICAgICAgcmVzb3VyY2VzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiBcInRlc3QtcmVzb3VyY2VcIixcbiAgICAgICAgICBkYXRhOiBbeyBpZDogMSwgbmFtZTogXCJhbGljZVwiIH1dLFxuICAgICAgICAgIHNjaGVtYToge1xuICAgICAgICAgICAgZmllbGRzOiBbXG4gICAgICAgICAgICAgIHsgbmFtZTogXCJpZFwiLCB0eXBlOiBcImludGVnZXJcIiB9LFxuICAgICAgICAgICAgICB7IG5hbWU6IFwibmFtZVwiLCB0eXBlOiBcInN0cmluZ1wiIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH1cblxuICAgIGF3YWl0IHNhdmVQYWNrYWdlVG9Gb2xkZXIoZGF0YVBhY2thZ2UsIHsgZm9sZGVyUGF0aDogdGVtcEZvbGRlclBhdGggfSlcblxuICAgIGNvbnN0IGRlc2NyaXB0b3JQYXRoID0gam9pbih0ZW1wRm9sZGVyUGF0aCwgXCJkYXRhcGFja2FnZS5qc29uXCIpXG4gICAgYXdhaXQgZXhwZWN0KGFjY2VzcyhkZXNjcmlwdG9yUGF0aCkpLnJlc29sdmVzLnRvQmVVbmRlZmluZWQoKVxuICB9KVxuXG4gIGl0KFwic2hvdWxkIHNhdmUgcGFja2FnZSB3aXRoIGRpYWxlY3RcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGNzdkNvbnRlbnQgPSBcImlkO25hbWVcXG4xO2FsaWNlXFxuMjtib2JcIlxuICAgIGNvbnN0IGNzdlBhdGggPSBhd2FpdCB3cml0ZVRlbXBGaWxlKGNzdkNvbnRlbnQpXG5cbiAgICBjb25zdCBkYXRhUGFja2FnZTogUGFja2FnZSA9IHtcbiAgICAgIG5hbWU6IFwidGVzdC1wYWNrYWdlXCIsXG4gICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IFwidGVzdC1yZXNvdXJjZVwiLFxuICAgICAgICAgIHBhdGg6IGNzdlBhdGgsXG4gICAgICAgICAgZm9ybWF0OiBcImNzdlwiLFxuICAgICAgICAgIGRpYWxlY3Q6IHtcbiAgICAgICAgICAgIGRlbGltaXRlcjogXCI7XCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfVxuXG4gICAgYXdhaXQgc2F2ZVBhY2thZ2VUb0ZvbGRlcihkYXRhUGFja2FnZSwgeyBmb2xkZXJQYXRoOiB0ZW1wRm9sZGVyUGF0aCB9KVxuXG4gICAgY29uc3QgZGVzY3JpcHRvclBhdGggPSBqb2luKHRlbXBGb2xkZXJQYXRoLCBcImRhdGFwYWNrYWdlLmpzb25cIilcbiAgICBhd2FpdCBleHBlY3QoYWNjZXNzKGRlc2NyaXB0b3JQYXRoKSkucmVzb2x2ZXMudG9CZVVuZGVmaW5lZCgpXG4gIH0pXG5cbiAgaXQoXCJzaG91bGQgc2F2ZSBhbmQgcmVsb2FkIHBhY2thZ2Ugd2l0aCBzYW1lIHN0cnVjdHVyZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgb3JpZ2luYWxQYWNrYWdlOiBQYWNrYWdlID0ge1xuICAgICAgbmFtZTogXCJ0ZXN0LXBhY2thZ2VcIixcbiAgICAgIHRpdGxlOiBcIlRlc3QgUGFja2FnZVwiLFxuICAgICAgZGVzY3JpcHRpb246IFwiQSB0ZXN0IHBhY2thZ2VcIixcbiAgICAgIHJlc291cmNlczogW1xuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogXCJ0ZXN0LXJlc291cmNlXCIsXG4gICAgICAgICAgZGF0YTogW3sgaWQ6IDEsIG5hbWU6IFwiYWxpY2VcIiB9XSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfVxuXG4gICAgYXdhaXQgc2F2ZVBhY2thZ2VUb0ZvbGRlcihvcmlnaW5hbFBhY2thZ2UsIHsgZm9sZGVyUGF0aDogdGVtcEZvbGRlclBhdGggfSlcbiAgICBjb25zdCByZWxvYWRlZFBhY2thZ2UgPSBhd2FpdCBsb2FkUGFja2FnZUZyb21Gb2xkZXIodGVtcEZvbGRlclBhdGgpXG5cbiAgICBleHBlY3QocmVsb2FkZWRQYWNrYWdlKS50b0JlRGVmaW5lZCgpXG4gICAgZXhwZWN0KHJlbG9hZGVkUGFja2FnZS5uYW1lKS50b0JlKFwidGVzdC1wYWNrYWdlXCIpXG4gICAgZXhwZWN0KHJlbG9hZGVkUGFja2FnZS50aXRsZSkudG9CZShcIlRlc3QgUGFja2FnZVwiKVxuICAgIGV4cGVjdChyZWxvYWRlZFBhY2thZ2UuZGVzY3JpcHRpb24pLnRvQmUoXCJBIHRlc3QgcGFja2FnZVwiKVxuICAgIGV4cGVjdChyZWxvYWRlZFBhY2thZ2UucmVzb3VyY2VzKS50b0hhdmVMZW5ndGgoMSlcbiAgICBleHBlY3QocmVsb2FkZWRQYWNrYWdlLnJlc291cmNlc1swXT8ubmFtZSkudG9CZShcInRlc3QtcmVzb3VyY2VcIilcbiAgfSlcblxuICBpdChcInNob3VsZCBzYXZlIGFuZCByZWxvYWQgcGFja2FnZSBwcmVzZXJ2aW5nIG1ldGFkYXRhXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBvcmlnaW5hbFBhY2thZ2U6IFBhY2thZ2UgPSB7XG4gICAgICBuYW1lOiBcInRlc3QtcGFja2FnZVwiLFxuICAgICAgdGl0bGU6IFwiVGVzdCBQYWNrYWdlXCIsXG4gICAgICBkZXNjcmlwdGlvbjogXCJBIHRlc3QgcGFja2FnZVwiLFxuICAgICAgdmVyc2lvbjogXCIxLjAuMFwiLFxuICAgICAga2V5d29yZHM6IFtcInRlc3RcIiwgXCJwYWNrYWdlXCJdLFxuICAgICAgcmVzb3VyY2VzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiBcInRlc3QtcmVzb3VyY2VcIixcbiAgICAgICAgICBkYXRhOiBbeyBpZDogMSB9XSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfVxuXG4gICAgYXdhaXQgc2F2ZVBhY2thZ2VUb0ZvbGRlcihvcmlnaW5hbFBhY2thZ2UsIHsgZm9sZGVyUGF0aDogdGVtcEZvbGRlclBhdGggfSlcbiAgICBjb25zdCByZWxvYWRlZFBhY2thZ2UgPSBhd2FpdCBsb2FkUGFja2FnZUZyb21Gb2xkZXIodGVtcEZvbGRlclBhdGgpXG5cbiAgICBleHBlY3QocmVsb2FkZWRQYWNrYWdlLm5hbWUpLnRvQmUoXCJ0ZXN0LXBhY2thZ2VcIilcbiAgICBleHBlY3QocmVsb2FkZWRQYWNrYWdlLnRpdGxlKS50b0JlKFwiVGVzdCBQYWNrYWdlXCIpXG4gICAgZXhwZWN0KHJlbG9hZGVkUGFja2FnZS52ZXJzaW9uKS50b0JlKFwiMS4wLjBcIilcbiAgICBleHBlY3QocmVsb2FkZWRQYWNrYWdlLmtleXdvcmRzKS50b0VxdWFsKFtcInRlc3RcIiwgXCJwYWNrYWdlXCJdKVxuICB9KVxuXG4gIGl0KFwic2hvdWxkIHNhdmUgYW5kIHJlbG9hZCBwYWNrYWdlIHdpdGggc2NoZW1hXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBvcmlnaW5hbFBhY2thZ2U6IFBhY2thZ2UgPSB7XG4gICAgICBuYW1lOiBcInRlc3QtcGFja2FnZVwiLFxuICAgICAgcmVzb3VyY2VzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiBcInRlc3QtcmVzb3VyY2VcIixcbiAgICAgICAgICBkYXRhOiBbeyBpZDogMSwgbmFtZTogXCJhbGljZVwiIH1dLFxuICAgICAgICAgIHNjaGVtYToge1xuICAgICAgICAgICAgZmllbGRzOiBbXG4gICAgICAgICAgICAgIHsgbmFtZTogXCJpZFwiLCB0eXBlOiBcImludGVnZXJcIiB9LFxuICAgICAgICAgICAgICB7IG5hbWU6IFwibmFtZVwiLCB0eXBlOiBcInN0cmluZ1wiIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH1cblxuICAgIGF3YWl0IHNhdmVQYWNrYWdlVG9Gb2xkZXIob3JpZ2luYWxQYWNrYWdlLCB7IGZvbGRlclBhdGg6IHRlbXBGb2xkZXJQYXRoIH0pXG4gICAgY29uc3QgcmVsb2FkZWRQYWNrYWdlID0gYXdhaXQgbG9hZFBhY2thZ2VGcm9tRm9sZGVyKHRlbXBGb2xkZXJQYXRoKVxuXG4gICAgY29uc3Qgc2NoZW1hID0gcmVsb2FkZWRQYWNrYWdlLnJlc291cmNlc1swXT8uc2NoZW1hXG4gICAgZXhwZWN0KHNjaGVtYSkudG9CZURlZmluZWQoKVxuICAgIGV4cGVjdCh0eXBlb2Ygc2NoZW1hID09PSBcIm9iamVjdFwiICYmIFwiZmllbGRzXCIgaW4gc2NoZW1hKS50b0JlKHRydWUpXG4gICAgaWYgKHR5cGVvZiBzY2hlbWEgPT09IFwib2JqZWN0XCIgJiYgXCJmaWVsZHNcIiBpbiBzY2hlbWEpIHtcbiAgICAgIGV4cGVjdChzY2hlbWEuZmllbGRzKS50b0hhdmVMZW5ndGgoMilcbiAgICAgIGV4cGVjdChzY2hlbWEuZmllbGRzPy5bMF0/Lm5hbWUpLnRvQmUoXCJpZFwiKVxuICAgICAgZXhwZWN0KHNjaGVtYS5maWVsZHM/LlsxXT8ubmFtZSkudG9CZShcIm5hbWVcIilcbiAgICB9XG4gIH0pXG5cbiAgaXQoXCJzaG91bGQgc2F2ZSBhbmQgcmVsb2FkIHBhY2thZ2Ugd2l0aCBmaWxlIHJlc291cmNlc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgY3N2Q29udGVudCA9IFwiaWQsbmFtZVxcbjEsYWxpY2VcXG4yLGJvYlwiXG4gICAgY29uc3QgY3N2UGF0aCA9IGF3YWl0IHdyaXRlVGVtcEZpbGUoY3N2Q29udGVudClcblxuICAgIGNvbnN0IG9yaWdpbmFsUGFja2FnZTogUGFja2FnZSA9IHtcbiAgICAgIG5hbWU6IFwidGVzdC1wYWNrYWdlXCIsXG4gICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IFwidGVzdC1yZXNvdXJjZVwiLFxuICAgICAgICAgIHBhdGg6IGNzdlBhdGgsXG4gICAgICAgICAgZm9ybWF0OiBcImNzdlwiLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9XG5cbiAgICBhd2FpdCBzYXZlUGFja2FnZVRvRm9sZGVyKG9yaWdpbmFsUGFja2FnZSwgeyBmb2xkZXJQYXRoOiB0ZW1wRm9sZGVyUGF0aCB9KVxuICAgIGNvbnN0IHJlbG9hZGVkUGFja2FnZSA9IGF3YWl0IGxvYWRQYWNrYWdlRnJvbUZvbGRlcih0ZW1wRm9sZGVyUGF0aClcblxuICAgIGV4cGVjdChyZWxvYWRlZFBhY2thZ2UucmVzb3VyY2VzKS50b0hhdmVMZW5ndGgoMSlcbiAgICBleHBlY3QocmVsb2FkZWRQYWNrYWdlLnJlc291cmNlc1swXT8ubmFtZSkudG9CZShcInRlc3QtcmVzb3VyY2VcIilcbiAgICBleHBlY3QocmVsb2FkZWRQYWNrYWdlLnJlc291cmNlc1swXT8uZm9ybWF0KS50b0JlKFwiY3N2XCIpXG4gIH0pXG5cbiAgaXQoXCJzaG91bGQgdGhyb3cgZXJyb3Igd2hlbiBzYXZpbmcgdG8gZXhpc3RpbmcgZm9sZGVyXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBkYXRhUGFja2FnZTogUGFja2FnZSA9IHtcbiAgICAgIG5hbWU6IFwidGVzdC1wYWNrYWdlXCIsXG4gICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IFwidGVzdC1yZXNvdXJjZVwiLFxuICAgICAgICAgIGRhdGE6IFtdLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9XG5cbiAgICBjb25zdCBmcyA9IGF3YWl0IGltcG9ydChcIm5vZGU6ZnMvcHJvbWlzZXNcIilcbiAgICBhd2FpdCBmcy5ta2Rpcih0ZW1wRm9sZGVyUGF0aCwgeyByZWN1cnNpdmU6IHRydWUgfSlcbiAgICBhd2FpdCBmcy53cml0ZUZpbGUoam9pbih0ZW1wRm9sZGVyUGF0aCwgXCJleGlzdGluZy50eHRcIiksIFwiY29udGVudFwiKVxuXG4gICAgYXdhaXQgZXhwZWN0KFxuICAgICAgc2F2ZVBhY2thZ2VUb0ZvbGRlcihkYXRhUGFja2FnZSwgeyBmb2xkZXJQYXRoOiB0ZW1wRm9sZGVyUGF0aCB9KSxcbiAgICApLnJlamVjdHMudG9UaHJvdygpXG4gIH0pXG5cbiAgaXQoXCJzaG91bGQgY3JlYXRlIHZhbGlkIGZvbGRlciBzdHJ1Y3R1cmVcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGRhdGFQYWNrYWdlOiBQYWNrYWdlID0ge1xuICAgICAgbmFtZTogXCJ0ZXN0LXBhY2thZ2VcIixcbiAgICAgIHJlc291cmNlczogW1xuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogXCJ0ZXN0LXJlc291cmNlXCIsXG4gICAgICAgICAgZGF0YTogW3sgaWQ6IDEgfV0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH1cblxuICAgIGF3YWl0IHNhdmVQYWNrYWdlVG9Gb2xkZXIoZGF0YVBhY2thZ2UsIHsgZm9sZGVyUGF0aDogdGVtcEZvbGRlclBhdGggfSlcbiAgICBjb25zdCByZWxvYWRlZFBhY2thZ2UgPSBhd2FpdCBsb2FkUGFja2FnZUZyb21Gb2xkZXIodGVtcEZvbGRlclBhdGgpXG5cbiAgICBleHBlY3QocmVsb2FkZWRQYWNrYWdlKS50b01hdGNoT2JqZWN0KHtcbiAgICAgIG5hbWU6IFwidGVzdC1wYWNrYWdlXCIsXG4gICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IFwidGVzdC1yZXNvdXJjZVwiLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KVxuICB9KVxuXG4gIGl0KFwic2hvdWxkIHNhdmUgcGFja2FnZSB3aXRoIG11bHRpcGxlIGZpbGUgcmVzb3VyY2VzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBjc3YxQ29udGVudCA9IFwiaWQsbmFtZVxcbjEsYWxpY2VcIlxuICAgIGNvbnN0IGNzdjJDb250ZW50ID0gXCJpZCx2YWx1ZVxcbjEsMTAwXCJcbiAgICBjb25zdCBjc3YxUGF0aCA9IGF3YWl0IHdyaXRlVGVtcEZpbGUoY3N2MUNvbnRlbnQpXG4gICAgY29uc3QgY3N2MlBhdGggPSBhd2FpdCB3cml0ZVRlbXBGaWxlKGNzdjJDb250ZW50KVxuXG4gICAgY29uc3Qgb3JpZ2luYWxQYWNrYWdlOiBQYWNrYWdlID0ge1xuICAgICAgbmFtZTogXCJ0ZXN0LXBhY2thZ2VcIixcbiAgICAgIHJlc291cmNlczogW1xuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogXCJyZXNvdXJjZS0xXCIsXG4gICAgICAgICAgcGF0aDogY3N2MVBhdGgsXG4gICAgICAgICAgZm9ybWF0OiBcImNzdlwiLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogXCJyZXNvdXJjZS0yXCIsXG4gICAgICAgICAgcGF0aDogY3N2MlBhdGgsXG4gICAgICAgICAgZm9ybWF0OiBcImNzdlwiLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9XG5cbiAgICBhd2FpdCBzYXZlUGFja2FnZVRvRm9sZGVyKG9yaWdpbmFsUGFja2FnZSwgeyBmb2xkZXJQYXRoOiB0ZW1wRm9sZGVyUGF0aCB9KVxuICAgIGNvbnN0IHJlbG9hZGVkUGFja2FnZSA9IGF3YWl0IGxvYWRQYWNrYWdlRnJvbUZvbGRlcih0ZW1wRm9sZGVyUGF0aClcblxuICAgIGV4cGVjdChyZWxvYWRlZFBhY2thZ2UucmVzb3VyY2VzKS50b0hhdmVMZW5ndGgoMilcbiAgICBleHBlY3QocmVsb2FkZWRQYWNrYWdlLnJlc291cmNlc1swXT8ubmFtZSkudG9CZShcInJlc291cmNlLTFcIilcbiAgICBleHBlY3QocmVsb2FkZWRQYWNrYWdlLnJlc291cmNlc1sxXT8ubmFtZSkudG9CZShcInJlc291cmNlLTJcIilcbiAgfSlcblxuICBpdChcInNob3VsZCBjcmVhdGUgZGF0YXBhY2thZ2UuanNvbiBpbiBmb2xkZXJcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGRhdGFQYWNrYWdlOiBQYWNrYWdlID0ge1xuICAgICAgbmFtZTogXCJ0ZXN0LXBhY2thZ2VcIixcbiAgICAgIHJlc291cmNlczogW1xuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogXCJ0ZXN0LXJlc291cmNlXCIsXG4gICAgICAgICAgZGF0YTogW3sgaWQ6IDEgfV0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH1cblxuICAgIGF3YWl0IHNhdmVQYWNrYWdlVG9Gb2xkZXIoZGF0YVBhY2thZ2UsIHsgZm9sZGVyUGF0aDogdGVtcEZvbGRlclBhdGggfSlcblxuICAgIGNvbnN0IGRlc2NyaXB0b3JQYXRoID0gam9pbih0ZW1wRm9sZGVyUGF0aCwgXCJkYXRhcGFja2FnZS5qc29uXCIpXG4gICAgY29uc3QgZGVzY3JpcHRvckNvbnRlbnQgPSBhd2FpdCByZWFkRmlsZShkZXNjcmlwdG9yUGF0aCwgXCJ1dGYtOFwiKVxuICAgIGNvbnN0IGRlc2NyaXB0b3IgPSBKU09OLnBhcnNlKGRlc2NyaXB0b3JDb250ZW50KVxuXG4gICAgZXhwZWN0KGRlc2NyaXB0b3IubmFtZSkudG9CZShcInRlc3QtcGFja2FnZVwiKVxuICAgIGV4cGVjdChkZXNjcmlwdG9yLnJlc291cmNlcykudG9IYXZlTGVuZ3RoKDEpXG4gIH0pXG5cbiAgaXQoXCJzaG91bGQgY29weSBmaWxlIHJlc291cmNlcyB0byBmb2xkZXJcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGNzdkNvbnRlbnQgPSBcImlkLG5hbWVcXG4xLGFsaWNlXFxuMixib2JcIlxuICAgIGNvbnN0IGNzdlBhdGggPSBhd2FpdCB3cml0ZVRlbXBGaWxlKGNzdkNvbnRlbnQpXG5cbiAgICBjb25zdCBkYXRhUGFja2FnZTogUGFja2FnZSA9IHtcbiAgICAgIG5hbWU6IFwidGVzdC1wYWNrYWdlXCIsXG4gICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IFwidGVzdC1yZXNvdXJjZVwiLFxuICAgICAgICAgIHBhdGg6IGNzdlBhdGgsXG4gICAgICAgICAgZm9ybWF0OiBcImNzdlwiLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9XG5cbiAgICBhd2FpdCBzYXZlUGFja2FnZVRvRm9sZGVyKGRhdGFQYWNrYWdlLCB7IGZvbGRlclBhdGg6IHRlbXBGb2xkZXJQYXRoIH0pXG5cbiAgICBjb25zdCBkZXNjcmlwdG9yUGF0aCA9IGpvaW4odGVtcEZvbGRlclBhdGgsIFwiZGF0YXBhY2thZ2UuanNvblwiKVxuICAgIGNvbnN0IGRlc2NyaXB0b3JDb250ZW50ID0gYXdhaXQgcmVhZEZpbGUoZGVzY3JpcHRvclBhdGgsIFwidXRmLThcIilcbiAgICBjb25zdCBkZXNjcmlwdG9yID0gSlNPTi5wYXJzZShkZXNjcmlwdG9yQ29udGVudClcblxuICAgIGNvbnN0IHJlc291cmNlUGF0aCA9IGRlc2NyaXB0b3IucmVzb3VyY2VzWzBdLnBhdGhcbiAgICBjb25zdCByZXNvdXJjZUZpbGVQYXRoID0gam9pbih0ZW1wRm9sZGVyUGF0aCwgcmVzb3VyY2VQYXRoKVxuICAgIGNvbnN0IHJlc291cmNlQ29udGVudCA9IGF3YWl0IHJlYWRGaWxlKHJlc291cmNlRmlsZVBhdGgsIFwidXRmLThcIilcblxuICAgIGV4cGVjdChyZXNvdXJjZUNvbnRlbnQpLnRvQmUoY3N2Q29udGVudClcbiAgfSlcbn0pXG4iXX0=
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { stat } from "node:fs/promises";
|
|
2
|
+
import { isRemotePath } from "@frictionless-ts/metadata";
|
|
3
|
+
import { loadPackageFromFolder } from "./package/index.js";
|
|
4
|
+
export class FolderPlugin {
|
|
5
|
+
async loadPackage(source) {
|
|
6
|
+
const isFolder = await getIsFolder(source);
|
|
7
|
+
if (!isFolder)
|
|
8
|
+
return undefined;
|
|
9
|
+
const dataPackage = await loadPackageFromFolder(source);
|
|
10
|
+
return dataPackage;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
async function getIsFolder(path) {
|
|
14
|
+
const isRemote = isRemotePath(path);
|
|
15
|
+
if (isRemote)
|
|
16
|
+
return false;
|
|
17
|
+
return (await stat(path)).isDirectory();
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vcGx1Z2lucy9mb2xkZXIvcGx1Z2luLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQTtBQUN2QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sMkJBQTJCLENBQUE7QUFFeEQsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sb0JBQW9CLENBQUE7QUFFMUQsTUFBTSxPQUFPLFlBQVk7SUFDdkIsS0FBSyxDQUFDLFdBQVcsQ0FBQyxNQUFjO1FBQzlCLE1BQU0sUUFBUSxHQUFHLE1BQU0sV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFBO1FBQzFDLElBQUksQ0FBQyxRQUFRO1lBQUUsT0FBTyxTQUFTLENBQUE7UUFFL0IsTUFBTSxXQUFXLEdBQUcsTUFBTSxxQkFBcUIsQ0FBQyxNQUFNLENBQUMsQ0FBQTtRQUN2RCxPQUFPLFdBQVcsQ0FBQTtJQUNwQixDQUFDO0NBR0Y7QUFFRCxLQUFLLFVBQVUsV0FBVyxDQUFDLElBQVk7SUFDckMsTUFBTSxRQUFRLEdBQUcsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFBO0lBQ25DLElBQUksUUFBUTtRQUFFLE9BQU8sS0FBSyxDQUFBO0lBRTFCLE9BQU8sQ0FBQyxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFBO0FBQ3pDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBzdGF0IH0gZnJvbSBcIm5vZGU6ZnMvcHJvbWlzZXNcIlxuaW1wb3J0IHsgaXNSZW1vdGVQYXRoIH0gZnJvbSBcIkBmcmljdGlvbmxlc3MtdHMvbWV0YWRhdGFcIlxuaW1wb3J0IHR5cGUgeyBEYXRhc2V0UGx1Z2luIH0gZnJvbSBcIi4uLy4uL3BsdWdpbi50c1wiXG5pbXBvcnQgeyBsb2FkUGFja2FnZUZyb21Gb2xkZXIgfSBmcm9tIFwiLi9wYWNrYWdlL2luZGV4LnRzXCJcblxuZXhwb3J0IGNsYXNzIEZvbGRlclBsdWdpbiBpbXBsZW1lbnRzIERhdGFzZXRQbHVnaW4ge1xuICBhc3luYyBsb2FkUGFja2FnZShzb3VyY2U6IHN0cmluZykge1xuICAgIGNvbnN0IGlzRm9sZGVyID0gYXdhaXQgZ2V0SXNGb2xkZXIoc291cmNlKVxuICAgIGlmICghaXNGb2xkZXIpIHJldHVybiB1bmRlZmluZWRcblxuICAgIGNvbnN0IGRhdGFQYWNrYWdlID0gYXdhaXQgbG9hZFBhY2thZ2VGcm9tRm9sZGVyKHNvdXJjZSlcbiAgICByZXR1cm4gZGF0YVBhY2thZ2VcbiAgfVxuXG4gIC8vIFRPT0Q6IGltcGxlbWVudCBzYXZlUGFja2FnZT9cbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0SXNGb2xkZXIocGF0aDogc3RyaW5nKSB7XG4gIGNvbnN0IGlzUmVtb3RlID0gaXNSZW1vdGVQYXRoKHBhdGgpXG4gIGlmIChpc1JlbW90ZSkgcmV0dXJuIGZhbHNlXG5cbiAgcmV0dXJuIChhd2FpdCBzdGF0KHBhdGgpKS5pc0RpcmVjdG9yeSgpXG59XG4iXX0=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import * as packageModule from "./package/index.js";
|
|
3
|
+
import { FolderPlugin } from "./plugin.js";
|
|
4
|
+
vi.mock("./package/index.ts", () => ({
|
|
5
|
+
loadPackageFromFolder: vi.fn(),
|
|
6
|
+
}));
|
|
7
|
+
describe("FolderPlugin", () => {
|
|
8
|
+
let plugin;
|
|
9
|
+
let mockLoadPackageFromFolder;
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
plugin = new FolderPlugin();
|
|
12
|
+
mockLoadPackageFromFolder = vi.mocked(packageModule.loadPackageFromFolder);
|
|
13
|
+
vi.clearAllMocks();
|
|
14
|
+
});
|
|
15
|
+
describe("loadPackage", () => {
|
|
16
|
+
it("should load package from local directory", async () => {
|
|
17
|
+
const mockPackage = {
|
|
18
|
+
name: "test-package",
|
|
19
|
+
resources: [{ name: "test", data: [] }],
|
|
20
|
+
};
|
|
21
|
+
mockLoadPackageFromFolder.mockResolvedValue(mockPackage);
|
|
22
|
+
const result = await plugin.loadPackage(".");
|
|
23
|
+
expect(mockLoadPackageFromFolder).toHaveBeenCalledWith(".");
|
|
24
|
+
expect(result).toEqual(mockPackage);
|
|
25
|
+
});
|
|
26
|
+
it("should return undefined for remote paths", async () => {
|
|
27
|
+
const result = await plugin.loadPackage("http://example.com/data");
|
|
28
|
+
expect(mockLoadPackageFromFolder).not.toHaveBeenCalled();
|
|
29
|
+
expect(result).toBeUndefined();
|
|
30
|
+
});
|
|
31
|
+
it("should return undefined for https paths", async () => {
|
|
32
|
+
const result = await plugin.loadPackage("https://example.com/data");
|
|
33
|
+
expect(mockLoadPackageFromFolder).not.toHaveBeenCalled();
|
|
34
|
+
expect(result).toBeUndefined();
|
|
35
|
+
});
|
|
36
|
+
it("should return undefined for github urls", async () => {
|
|
37
|
+
const result = await plugin.loadPackage("https://github.com/owner/repo/data");
|
|
38
|
+
expect(mockLoadPackageFromFolder).not.toHaveBeenCalled();
|
|
39
|
+
expect(result).toBeUndefined();
|
|
40
|
+
});
|
|
41
|
+
it("should return undefined for ftp paths", async () => {
|
|
42
|
+
const result = await plugin.loadPackage("ftp://example.com/data");
|
|
43
|
+
expect(mockLoadPackageFromFolder).not.toHaveBeenCalled();
|
|
44
|
+
expect(result).toBeUndefined();
|
|
45
|
+
});
|
|
46
|
+
it("should return undefined for zenodo urls", async () => {
|
|
47
|
+
const result = await plugin.loadPackage("https://zenodo.org/record/123");
|
|
48
|
+
expect(mockLoadPackageFromFolder).not.toHaveBeenCalled();
|
|
49
|
+
expect(result).toBeUndefined();
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLnNwZWMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9wbHVnaW5zL2ZvbGRlci9wbHVnaW4uc3BlYy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxNQUFNLFFBQVEsQ0FBQTtBQUM3RCxPQUFPLEtBQUssYUFBYSxNQUFNLG9CQUFvQixDQUFBO0FBQ25ELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxhQUFhLENBQUE7QUFFMUMsRUFBRSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDO0lBQ25DLHFCQUFxQixFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUU7Q0FDL0IsQ0FBQyxDQUFDLENBQUE7QUFFSCxRQUFRLENBQUMsY0FBYyxFQUFFLEdBQUcsRUFBRTtJQUM1QixJQUFJLE1BQW9CLENBQUE7SUFDeEIsSUFBSSx5QkFBbUQsQ0FBQTtJQUV2RCxVQUFVLENBQUMsR0FBRyxFQUFFO1FBQ2QsTUFBTSxHQUFHLElBQUksWUFBWSxFQUFFLENBQUE7UUFDM0IseUJBQXlCLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMscUJBQXFCLENBQUMsQ0FBQTtRQUMxRSxFQUFFLENBQUMsYUFBYSxFQUFFLENBQUE7SUFDcEIsQ0FBQyxDQUFDLENBQUE7SUFFRixRQUFRLENBQUMsYUFBYSxFQUFFLEdBQUcsRUFBRTtRQUMzQixFQUFFLENBQUMsMENBQTBDLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDeEQsTUFBTSxXQUFXLEdBQVk7Z0JBQzNCLElBQUksRUFBRSxjQUFjO2dCQUNwQixTQUFTLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxDQUFDO2FBQ3hDLENBQUE7WUFDRCx5QkFBeUIsQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLENBQUMsQ0FBQTtZQUV4RCxNQUFNLE1BQU0sR0FBRyxNQUFNLE1BQU0sQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUE7WUFFNUMsTUFBTSxDQUFDLHlCQUF5QixDQUFDLENBQUMsb0JBQW9CLENBQUMsR0FBRyxDQUFDLENBQUE7WUFDM0QsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQTtRQUNyQyxDQUFDLENBQUMsQ0FBQTtRQUVGLEVBQUUsQ0FBQywwQ0FBMEMsRUFBRSxLQUFLLElBQUksRUFBRTtZQUN4RCxNQUFNLE1BQU0sR0FBRyxNQUFNLE1BQU0sQ0FBQyxXQUFXLENBQUMseUJBQXlCLENBQUMsQ0FBQTtZQUVsRSxNQUFNLENBQUMseUJBQXlCLENBQUMsQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQTtZQUN4RCxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsYUFBYSxFQUFFLENBQUE7UUFDaEMsQ0FBQyxDQUFDLENBQUE7UUFFRixFQUFFLENBQUMseUNBQXlDLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDdkQsTUFBTSxNQUFNLEdBQUcsTUFBTSxNQUFNLENBQUMsV0FBVyxDQUFDLDBCQUEwQixDQUFDLENBQUE7WUFFbkUsTUFBTSxDQUFDLHlCQUF5QixDQUFDLENBQUMsR0FBRyxDQUFDLGdCQUFnQixFQUFFLENBQUE7WUFDeEQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFBO1FBQ2hDLENBQUMsQ0FBQyxDQUFBO1FBRUYsRUFBRSxDQUFDLHlDQUF5QyxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQ3ZELE1BQU0sTUFBTSxHQUFHLE1BQU0sTUFBTSxDQUFDLFdBQVcsQ0FDckMsb0NBQW9DLENBQ3JDLENBQUE7WUFFRCxNQUFNLENBQUMseUJBQXlCLENBQUMsQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQTtZQUN4RCxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsYUFBYSxFQUFFLENBQUE7UUFDaEMsQ0FBQyxDQUFDLENBQUE7UUFFRixFQUFFLENBQUMsdUNBQXVDLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDckQsTUFBTSxNQUFNLEdBQUcsTUFBTSxNQUFNLENBQUMsV0FBVyxDQUFDLHdCQUF3QixDQUFDLENBQUE7WUFFakUsTUFBTSxDQUFDLHlCQUF5QixDQUFDLENBQUMsR0FBRyxDQUFDLGdCQUFnQixFQUFFLENBQUE7WUFDeEQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFBO1FBQ2hDLENBQUMsQ0FBQyxDQUFBO1FBRUYsRUFBRSxDQUFDLHlDQUF5QyxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQ3ZELE1BQU0sTUFBTSxHQUFHLE1BQU0sTUFBTSxDQUFDLFdBQVcsQ0FBQywrQkFBK0IsQ0FBQyxDQUFBO1lBRXhFLE1BQU0sQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFBO1lBQ3hELE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxhQUFhLEVBQUUsQ0FBQTtRQUNoQyxDQUFDLENBQUMsQ0FBQTtJQUNKLENBQUMsQ0FBQyxDQUFBO0FBQ0osQ0FBQyxDQUFDLENBQUEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IFBhY2thZ2UgfSBmcm9tIFwiQGZyaWN0aW9ubGVzcy10cy9tZXRhZGF0YVwiXG5pbXBvcnQgeyBiZWZvcmVFYWNoLCBkZXNjcmliZSwgZXhwZWN0LCBpdCwgdmkgfSBmcm9tIFwidml0ZXN0XCJcbmltcG9ydCAqIGFzIHBhY2thZ2VNb2R1bGUgZnJvbSBcIi4vcGFja2FnZS9pbmRleC50c1wiXG5pbXBvcnQgeyBGb2xkZXJQbHVnaW4gfSBmcm9tIFwiLi9wbHVnaW4udHNcIlxuXG52aS5tb2NrKFwiLi9wYWNrYWdlL2luZGV4LnRzXCIsICgpID0+ICh7XG4gIGxvYWRQYWNrYWdlRnJvbUZvbGRlcjogdmkuZm4oKSxcbn0pKVxuXG5kZXNjcmliZShcIkZvbGRlclBsdWdpblwiLCAoKSA9PiB7XG4gIGxldCBwbHVnaW46IEZvbGRlclBsdWdpblxuICBsZXQgbW9ja0xvYWRQYWNrYWdlRnJvbUZvbGRlcjogUmV0dXJuVHlwZTx0eXBlb2YgdmkuZm4+XG5cbiAgYmVmb3JlRWFjaCgoKSA9PiB7XG4gICAgcGx1Z2luID0gbmV3IEZvbGRlclBsdWdpbigpXG4gICAgbW9ja0xvYWRQYWNrYWdlRnJvbUZvbGRlciA9IHZpLm1vY2tlZChwYWNrYWdlTW9kdWxlLmxvYWRQYWNrYWdlRnJvbUZvbGRlcilcbiAgICB2aS5jbGVhckFsbE1vY2tzKClcbiAgfSlcblxuICBkZXNjcmliZShcImxvYWRQYWNrYWdlXCIsICgpID0+IHtcbiAgICBpdChcInNob3VsZCBsb2FkIHBhY2thZ2UgZnJvbSBsb2NhbCBkaXJlY3RvcnlcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgbW9ja1BhY2thZ2U6IFBhY2thZ2UgPSB7XG4gICAgICAgIG5hbWU6IFwidGVzdC1wYWNrYWdlXCIsXG4gICAgICAgIHJlc291cmNlczogW3sgbmFtZTogXCJ0ZXN0XCIsIGRhdGE6IFtdIH1dLFxuICAgICAgfVxuICAgICAgbW9ja0xvYWRQYWNrYWdlRnJvbUZvbGRlci5tb2NrUmVzb2x2ZWRWYWx1ZShtb2NrUGFja2FnZSlcblxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcGx1Z2luLmxvYWRQYWNrYWdlKFwiLlwiKVxuXG4gICAgICBleHBlY3QobW9ja0xvYWRQYWNrYWdlRnJvbUZvbGRlcikudG9IYXZlQmVlbkNhbGxlZFdpdGgoXCIuXCIpXG4gICAgICBleHBlY3QocmVzdWx0KS50b0VxdWFsKG1vY2tQYWNrYWdlKVxuICAgIH0pXG5cbiAgICBpdChcInNob3VsZCByZXR1cm4gdW5kZWZpbmVkIGZvciByZW1vdGUgcGF0aHNcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcGx1Z2luLmxvYWRQYWNrYWdlKFwiaHR0cDovL2V4YW1wbGUuY29tL2RhdGFcIilcblxuICAgICAgZXhwZWN0KG1vY2tMb2FkUGFja2FnZUZyb21Gb2xkZXIpLm5vdC50b0hhdmVCZWVuQ2FsbGVkKClcbiAgICAgIGV4cGVjdChyZXN1bHQpLnRvQmVVbmRlZmluZWQoKVxuICAgIH0pXG5cbiAgICBpdChcInNob3VsZCByZXR1cm4gdW5kZWZpbmVkIGZvciBodHRwcyBwYXRoc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBwbHVnaW4ubG9hZFBhY2thZ2UoXCJodHRwczovL2V4YW1wbGUuY29tL2RhdGFcIilcblxuICAgICAgZXhwZWN0KG1vY2tMb2FkUGFja2FnZUZyb21Gb2xkZXIpLm5vdC50b0hhdmVCZWVuQ2FsbGVkKClcbiAgICAgIGV4cGVjdChyZXN1bHQpLnRvQmVVbmRlZmluZWQoKVxuICAgIH0pXG5cbiAgICBpdChcInNob3VsZCByZXR1cm4gdW5kZWZpbmVkIGZvciBnaXRodWIgdXJsc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBwbHVnaW4ubG9hZFBhY2thZ2UoXG4gICAgICAgIFwiaHR0cHM6Ly9naXRodWIuY29tL293bmVyL3JlcG8vZGF0YVwiLFxuICAgICAgKVxuXG4gICAgICBleHBlY3QobW9ja0xvYWRQYWNrYWdlRnJvbUZvbGRlcikubm90LnRvSGF2ZUJlZW5DYWxsZWQoKVxuICAgICAgZXhwZWN0KHJlc3VsdCkudG9CZVVuZGVmaW5lZCgpXG4gICAgfSlcblxuICAgIGl0KFwic2hvdWxkIHJldHVybiB1bmRlZmluZWQgZm9yIGZ0cCBwYXRoc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBwbHVnaW4ubG9hZFBhY2thZ2UoXCJmdHA6Ly9leGFtcGxlLmNvbS9kYXRhXCIpXG5cbiAgICAgIGV4cGVjdChtb2NrTG9hZFBhY2thZ2VGcm9tRm9sZGVyKS5ub3QudG9IYXZlQmVlbkNhbGxlZCgpXG4gICAgICBleHBlY3QocmVzdWx0KS50b0JlVW5kZWZpbmVkKClcbiAgICB9KVxuXG4gICAgaXQoXCJzaG91bGQgcmV0dXJuIHVuZGVmaW5lZCBmb3IgemVub2RvIHVybHNcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcGx1Z2luLmxvYWRQYWNrYWdlKFwiaHR0cHM6Ly96ZW5vZG8ub3JnL3JlY29yZC8xMjNcIilcblxuICAgICAgZXhwZWN0KG1vY2tMb2FkUGFja2FnZUZyb21Gb2xkZXIpLm5vdC50b0hhdmVCZWVuQ2FsbGVkKClcbiAgICAgIGV4cGVjdChyZXN1bHQpLnRvQmVVbmRlZmluZWQoKVxuICAgIH0pXG4gIH0pXG59KVxuIl19
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { makeGithubApiRequest } from "./request.ts";
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { makeGithubApiRequest } from "./request.js";
|
|
2
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wbHVnaW5zL2dpdGh1Yi9naXRodWIvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sY0FBYyxDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IHsgbWFrZUdpdGh1YkFwaVJlcXVlc3QgfSBmcm9tIFwiLi9yZXF1ZXN0LnRzXCJcbiJdfQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function normalizeFileLink(link: string): string;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export function normalizeFileLink(link) {
|
|
2
|
+
return link.replace("/api/", "/").replace(/\/content$/, "");
|
|
3
|
+
}
|
|
4
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGF0aC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3BsdWdpbnMvZ2l0aHViL2dpdGh1Yi9wYXRoLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE1BQU0sVUFBVSxpQkFBaUIsQ0FBQyxJQUFZO0lBQzVDLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLFlBQVksRUFBRSxFQUFFLENBQUMsQ0FBQTtBQUM3RCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGZ1bmN0aW9uIG5vcm1hbGl6ZUZpbGVMaW5rKGxpbms6IHN0cmluZykge1xuICByZXR1cm4gbGluay5yZXBsYWNlKFwiL2FwaS9cIiwgXCIvXCIpLnJlcGxhY2UoL1xcL2NvbnRlbnQkLywgXCJcIilcbn1cbiJdfQ==
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Descriptor } from "@frictionless-ts/metadata";
|
|
2
|
+
/**
|
|
3
|
+
* Makes a request to the Github API
|
|
4
|
+
*/
|
|
5
|
+
export declare function makeGithubApiRequest<T = Descriptor>(options: {
|
|
6
|
+
endpoint: string;
|
|
7
|
+
method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
8
|
+
payload?: Descriptor;
|
|
9
|
+
apiKey?: string;
|
|
10
|
+
upload?: {
|
|
11
|
+
name: string;
|
|
12
|
+
data: Blob;
|
|
13
|
+
path?: string;
|
|
14
|
+
};
|
|
15
|
+
}): Promise<T>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Makes a request to the Github API
|
|
3
|
+
*/
|
|
4
|
+
export async function makeGithubApiRequest(options) {
|
|
5
|
+
const { endpoint, method = "GET", payload, upload, apiKey } = options;
|
|
6
|
+
let body;
|
|
7
|
+
const headers = {};
|
|
8
|
+
if (apiKey) {
|
|
9
|
+
headers["Authorization"] = `Bearer ${apiKey}`;
|
|
10
|
+
}
|
|
11
|
+
// Create full API URL
|
|
12
|
+
const baseUrl = "https://api.github.com";
|
|
13
|
+
const url = `${baseUrl}${endpoint}`;
|
|
14
|
+
if (upload) {
|
|
15
|
+
body = new FormData();
|
|
16
|
+
body.append("file", upload.data, upload.name);
|
|
17
|
+
if (payload) {
|
|
18
|
+
for (const [key, value] of Object.entries(payload)) {
|
|
19
|
+
if (typeof value === "object" && value !== null) {
|
|
20
|
+
body.append(key, JSON.stringify(value));
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
body.append(key, String(value));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
else if (payload) {
|
|
29
|
+
body = JSON.stringify(payload);
|
|
30
|
+
headers["Content-Type"] = "application/json";
|
|
31
|
+
}
|
|
32
|
+
const response = await fetch(url, {
|
|
33
|
+
method,
|
|
34
|
+
headers,
|
|
35
|
+
body,
|
|
36
|
+
});
|
|
37
|
+
if (!response.ok || response.status === 204) {
|
|
38
|
+
const errorText = await response.text();
|
|
39
|
+
throw new Error(`Github API error: ${response.status} ${response.statusText}\n${errorText}`);
|
|
40
|
+
}
|
|
41
|
+
return (await response.json());
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVxdWVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3BsdWdpbnMvZ2l0aHViL2dpdGh1Yi9yZXF1ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxvQkFBb0IsQ0FBaUIsT0FVMUQ7SUFDQyxNQUFNLEVBQUUsUUFBUSxFQUFFLE1BQU0sR0FBRyxLQUFLLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsR0FBRyxPQUFPLENBQUE7SUFFckUsSUFBSSxJQUFtQyxDQUFBO0lBQ3ZDLE1BQU0sT0FBTyxHQUF3QixFQUFFLENBQUE7SUFFdkMsSUFBSSxNQUFNLEVBQUUsQ0FBQztRQUNYLE9BQU8sQ0FBQyxlQUFlLENBQUMsR0FBRyxVQUFVLE1BQU0sRUFBRSxDQUFBO0lBQy9DLENBQUM7SUFFRCxzQkFBc0I7SUFDdEIsTUFBTSxPQUFPLEdBQUcsd0JBQXdCLENBQUE7SUFDeEMsTUFBTSxHQUFHLEdBQUcsR0FBRyxPQUFPLEdBQUcsUUFBUSxFQUFFLENBQUE7SUFFbkMsSUFBSSxNQUFNLEVBQUUsQ0FBQztRQUNYLElBQUksR0FBRyxJQUFJLFFBQVEsRUFBRSxDQUFBO1FBQ3JCLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBRTdDLElBQUksT0FBTyxFQUFFLENBQUM7WUFDWixLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO2dCQUNuRCxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxLQUFLLEtBQUssSUFBSSxFQUFFLENBQUM7b0JBQ2hELElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQTtnQkFDekMsQ0FBQztxQkFBTSxDQUFDO29CQUNOLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFBO2dCQUNqQyxDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO1NBQU0sSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUNuQixJQUFJLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQTtRQUM5QixPQUFPLENBQUMsY0FBYyxDQUFDLEdBQUcsa0JBQWtCLENBQUE7SUFDOUMsQ0FBQztJQUVELE1BQU0sUUFBUSxHQUFHLE1BQU0sS0FBSyxDQUFDLEdBQUcsRUFBRTtRQUNoQyxNQUFNO1FBQ04sT0FBTztRQUNQLElBQUk7S0FDTCxDQUFDLENBQUE7SUFFRixJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUUsSUFBSSxRQUFRLENBQUMsTUFBTSxLQUFLLEdBQUcsRUFBRSxDQUFDO1FBQzVDLE1BQU0sU0FBUyxHQUFHLE1BQU0sUUFBUSxDQUFDLElBQUksRUFBRSxDQUFBO1FBQ3ZDLE1BQU0sSUFBSSxLQUFLLENBQ2IscUJBQXFCLFFBQVEsQ0FBQyxNQUFNLElBQUksUUFBUSxDQUFDLFVBQVUsS0FBSyxTQUFTLEVBQUUsQ0FDNUUsQ0FBQTtJQUNILENBQUM7SUFFRCxPQUFPLENBQUMsTUFBTSxRQUFRLENBQUMsSUFBSSxFQUFFLENBQU0sQ0FBQTtBQUNyQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBEZXNjcmlwdG9yIH0gZnJvbSBcIkBmcmljdGlvbmxlc3MtdHMvbWV0YWRhdGFcIlxuXG4vKipcbiAqIE1ha2VzIGEgcmVxdWVzdCB0byB0aGUgR2l0aHViIEFQSVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbWFrZUdpdGh1YkFwaVJlcXVlc3Q8VCA9IERlc2NyaXB0b3I+KG9wdGlvbnM6IHtcbiAgZW5kcG9pbnQ6IHN0cmluZ1xuICBtZXRob2Q/OiBcIkdFVFwiIHwgXCJQT1NUXCIgfCBcIlBVVFwiIHwgXCJERUxFVEVcIiB8IFwiUEFUQ0hcIlxuICBwYXlsb2FkPzogRGVzY3JpcHRvclxuICBhcGlLZXk/OiBzdHJpbmdcbiAgdXBsb2FkPzoge1xuICAgIG5hbWU6IHN0cmluZ1xuICAgIGRhdGE6IEJsb2JcbiAgICBwYXRoPzogc3RyaW5nIC8vIFBhdGggd2l0aGluIHJlcG9zaXRvcnlcbiAgfVxufSkge1xuICBjb25zdCB7IGVuZHBvaW50LCBtZXRob2QgPSBcIkdFVFwiLCBwYXlsb2FkLCB1cGxvYWQsIGFwaUtleSB9ID0gb3B0aW9uc1xuXG4gIGxldCBib2R5OiBzdHJpbmcgfCBGb3JtRGF0YSB8IHVuZGVmaW5lZFxuICBjb25zdCBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge31cblxuICBpZiAoYXBpS2V5KSB7XG4gICAgaGVhZGVyc1tcIkF1dGhvcml6YXRpb25cIl0gPSBgQmVhcmVyICR7YXBpS2V5fWBcbiAgfVxuXG4gIC8vIENyZWF0ZSBmdWxsIEFQSSBVUkxcbiAgY29uc3QgYmFzZVVybCA9IFwiaHR0cHM6Ly9hcGkuZ2l0aHViLmNvbVwiXG4gIGNvbnN0IHVybCA9IGAke2Jhc2VVcmx9JHtlbmRwb2ludH1gXG5cbiAgaWYgKHVwbG9hZCkge1xuICAgIGJvZHkgPSBuZXcgRm9ybURhdGEoKVxuICAgIGJvZHkuYXBwZW5kKFwiZmlsZVwiLCB1cGxvYWQuZGF0YSwgdXBsb2FkLm5hbWUpXG5cbiAgICBpZiAocGF5bG9hZCkge1xuICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMocGF5bG9hZCkpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJvYmplY3RcIiAmJiB2YWx1ZSAhPT0gbnVsbCkge1xuICAgICAgICAgIGJvZHkuYXBwZW5kKGtleSwgSlNPTi5zdHJpbmdpZnkodmFsdWUpKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGJvZHkuYXBwZW5kKGtleSwgU3RyaW5nKHZhbHVlKSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIGlmIChwYXlsb2FkKSB7XG4gICAgYm9keSA9IEpTT04uc3RyaW5naWZ5KHBheWxvYWQpXG4gICAgaGVhZGVyc1tcIkNvbnRlbnQtVHlwZVwiXSA9IFwiYXBwbGljYXRpb24vanNvblwiXG4gIH1cblxuICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKHVybCwge1xuICAgIG1ldGhvZCxcbiAgICBoZWFkZXJzLFxuICAgIGJvZHksXG4gIH0pXG5cbiAgaWYgKCFyZXNwb25zZS5vayB8fCByZXNwb25zZS5zdGF0dXMgPT09IDIwNCkge1xuICAgIGNvbnN0IGVycm9yVGV4dCA9IGF3YWl0IHJlc3BvbnNlLnRleHQoKVxuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBHaXRodWIgQVBJIGVycm9yOiAke3Jlc3BvbnNlLnN0YXR1c30gJHtyZXNwb25zZS5zdGF0dXNUZXh0fVxcbiR7ZXJyb3JUZXh0fWAsXG4gICAgKVxuICB9XG5cbiAgcmV0dXJuIChhd2FpdCByZXNwb25zZS5qc29uKCkpIGFzIFRcbn1cbiJdfQ==
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export * from "./package/index.js";
|
|
2
|
+
export * from "./resource/index.js";
|
|
3
|
+
export * from "./plugin.js";
|
|
4
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9wbHVnaW5zL2dpdGh1Yi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLG9CQUFvQixDQUFBO0FBQ2xDLGNBQWMscUJBQXFCLENBQUE7QUFDbkMsY0FBYyxhQUFhLENBQUEiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tIFwiLi9wYWNrYWdlL2luZGV4LnRzXCJcbmV4cG9ydCAqIGZyb20gXCIuL3Jlc291cmNlL2luZGV4LnRzXCJcbmV4cG9ydCAqIGZyb20gXCIuL3BsdWdpbi50c1wiXG4iXX0=
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub repository license
|
|
3
|
+
*/
|
|
4
|
+
export interface GithubLicense {
|
|
5
|
+
/**
|
|
6
|
+
* License key
|
|
7
|
+
*/
|
|
8
|
+
key: string;
|
|
9
|
+
/**
|
|
10
|
+
* License name
|
|
11
|
+
*/
|
|
12
|
+
name: string;
|
|
13
|
+
/**
|
|
14
|
+
* License SPDX ID
|
|
15
|
+
*/
|
|
16
|
+
spdx_id: string;
|
|
17
|
+
/**
|
|
18
|
+
* License URL
|
|
19
|
+
*/
|
|
20
|
+
url: string;
|
|
21
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export {};
|
|
2
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTGljZW5zZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3BsdWdpbnMvZ2l0aHViL3BhY2thZ2UvTGljZW5zZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBHaXRIdWIgcmVwb3NpdG9yeSBsaWNlbnNlXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR2l0aHViTGljZW5zZSB7XG4gIC8qKlxuICAgKiBMaWNlbnNlIGtleVxuICAgKi9cbiAga2V5OiBzdHJpbmdcblxuICAvKipcbiAgICogTGljZW5zZSBuYW1lXG4gICAqL1xuICBuYW1lOiBzdHJpbmdcblxuICAvKipcbiAgICogTGljZW5zZSBTUERYIElEXG4gICAqL1xuICBzcGR4X2lkOiBzdHJpbmdcblxuICAvKipcbiAgICogTGljZW5zZSBVUkxcbiAgICovXG4gIHVybDogc3RyaW5nXG59XG4iXX0=
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub repository owner
|
|
3
|
+
*/
|
|
4
|
+
export interface GithubOwner {
|
|
5
|
+
/**
|
|
6
|
+
* Owner login name
|
|
7
|
+
*/
|
|
8
|
+
login: string;
|
|
9
|
+
/**
|
|
10
|
+
* Owner ID
|
|
11
|
+
*/
|
|
12
|
+
id: number;
|
|
13
|
+
/**
|
|
14
|
+
* Owner avatar URL
|
|
15
|
+
*/
|
|
16
|
+
avatar_url: string;
|
|
17
|
+
/**
|
|
18
|
+
* Owner URL
|
|
19
|
+
*/
|
|
20
|
+
html_url: string;
|
|
21
|
+
/**
|
|
22
|
+
* Owner type (User/Organization)
|
|
23
|
+
*/
|
|
24
|
+
type: "User" | "Organization";
|
|
25
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export {};
|
|
2
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiT3duZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wbHVnaW5zL2dpdGh1Yi9wYWNrYWdlL093bmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEdpdEh1YiByZXBvc2l0b3J5IG93bmVyXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR2l0aHViT3duZXIge1xuICAvKipcbiAgICogT3duZXIgbG9naW4gbmFtZVxuICAgKi9cbiAgbG9naW46IHN0cmluZ1xuXG4gIC8qKlxuICAgKiBPd25lciBJRFxuICAgKi9cbiAgaWQ6IG51bWJlclxuXG4gIC8qKlxuICAgKiBPd25lciBhdmF0YXIgVVJMXG4gICAqL1xuICBhdmF0YXJfdXJsOiBzdHJpbmdcblxuICAvKipcbiAgICogT3duZXIgVVJMXG4gICAqL1xuICBodG1sX3VybDogc3RyaW5nXG5cbiAgLyoqXG4gICAqIE93bmVyIHR5cGUgKFVzZXIvT3JnYW5pemF0aW9uKVxuICAgKi9cbiAgdHlwZTogXCJVc2VyXCIgfCBcIk9yZ2FuaXphdGlvblwiXG59XG4iXX0=
|