@_linked/s3 1.0.3 → 1.1.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.
@@ -0,0 +1,173 @@
1
+ import { Shape } from '@_linked/core/shapes/Shape';
2
+ import mime from 'mime';
3
+ import path from 'path';
4
+ import { s3 } from '../ontologies/s3.js';
5
+ import { S3Bucket } from './S3Bucket.js';
6
+ const trimSlashes = (value = '') => value.replace(/^\/+|\/+$/g, '');
7
+ const trimTrailingSlash = (value = '') => value.replace(/\/+$/g, '');
8
+ export class S3FileStore extends Shape {
9
+ constructor(n, config = {}) {
10
+ if (typeof n === 'string') {
11
+ //set a fixed URI. This is important because the URI needs to match on the frontend and backend
12
+ super(`${process.env.DATA_ROOT}/s3-filestore/${n}`);
13
+ this.label = n;
14
+ }
15
+ else {
16
+ super(n);
17
+ }
18
+ this.config = config;
19
+ this.accessURL = this.resolveAccessURL();
20
+ }
21
+ get bucket() {
22
+ const bucketName = this.resolveBucketName();
23
+ if (!bucketName) {
24
+ throw new Error('S3_FILES_BUCKET_NAME environment variable must be set to use S3FileStore (or pass bucketName in config)');
25
+ }
26
+ if (!this._bucket) {
27
+ this._bucket = new S3Bucket(bucketName, this.config.clientConfig);
28
+ }
29
+ return this._bucket;
30
+ }
31
+ resolveBucketName() {
32
+ var _a, _b, _c;
33
+ // Scoped store config wins. Legacy shared env vars stay as fallback to keep
34
+ // existing apps working while allowing upload/static separation.
35
+ return ((_c = (_b = (_a = this.config.bucketName) !== null && _a !== void 0 ? _a : process.env.S3_FILES_BUCKET_NAME) !== null && _b !== void 0 ? _b : process.env.UPLOADS_S3_FILES_BUCKET_NAME) !== null && _c !== void 0 ? _c : process.env.STATIC_S3_FILES_BUCKET_NAME);
36
+ }
37
+ resolveAccessURL() {
38
+ var _a, _b, _c, _d, _e, _f, _g;
39
+ const explicitAccessURL = (_c = (_b = (_a = this.config.accessURL) !== null && _a !== void 0 ? _a : process.env.S3_CDN_URL) !== null && _b !== void 0 ? _b : process.env.UPLOADS_ACCESS_URL) !== null && _c !== void 0 ? _c : process.env.STATIC_ACCESS_URL;
40
+ if (explicitAccessURL) {
41
+ return trimTrailingSlash(explicitAccessURL);
42
+ }
43
+ const endpoint = (_g = (_f = (_e = (_d = this.config.clientConfig) === null || _d === void 0 ? void 0 : _d.endpoint) !== null && _e !== void 0 ? _e : process.env.S3_BUCKET_ENDPOINT) !== null && _f !== void 0 ? _f : process.env.UPLOADS_S3_BUCKET_ENDPOINT) !== null && _g !== void 0 ? _g : process.env.STATIC_S3_BUCKET_ENDPOINT;
44
+ const bucketName = this.resolveBucketName();
45
+ if (endpoint && bucketName) {
46
+ return `${trimTrailingSlash(endpoint)}/${bucketName}`;
47
+ }
48
+ return trimTrailingSlash(endpoint);
49
+ }
50
+ get prefix() {
51
+ var _a;
52
+ // Optional per-store key prefix, used for versioned static publishing.
53
+ return trimSlashes((_a = this.config.prefix) !== null && _a !== void 0 ? _a : '');
54
+ }
55
+ normalizePath(filePath) {
56
+ return filePath.replace(/^\/+/, '');
57
+ }
58
+ applyPrefix(filePath) {
59
+ const normalizedPath = this.normalizePath(filePath);
60
+ if (!this.prefix) {
61
+ return normalizedPath;
62
+ }
63
+ // Guard against accidental double prefixing when callers pass already-prefixed keys.
64
+ if (normalizedPath.startsWith(`${this.prefix}/`)) {
65
+ return normalizedPath;
66
+ }
67
+ return `${this.prefix}/${normalizedPath}`;
68
+ }
69
+ stripPrefix(filePath) {
70
+ if (!this.prefix) {
71
+ return filePath;
72
+ }
73
+ const normalizedPath = this.normalizePath(filePath);
74
+ const prefixedPath = `${this.prefix}/`;
75
+ if (normalizedPath.startsWith(prefixedPath)) {
76
+ return normalizedPath.substring(prefixedPath.length);
77
+ }
78
+ return normalizedPath;
79
+ }
80
+ /**
81
+ * List all files in the bucket
82
+ * @param recursive Whether to list files recursively or just the top-level files
83
+ * @returns A list of file paths, relative to the endpoint
84
+ * @todo Think about taking an options parameter instead of positional args
85
+ * @todo Take a path parameter to list files in a subdirectory
86
+ */
87
+ async listFiles(prefix) {
88
+ let bucket = this.bucket;
89
+ const keyPrefix = this.prefix
90
+ ? prefix
91
+ ? this.applyPrefix(prefix)
92
+ : `${this.prefix}/`
93
+ : prefix;
94
+ return bucket
95
+ .getAllObjectKeys(keyPrefix)
96
+ .then((keys) => keys.map((key) => this.stripPrefix(key)))
97
+ .catch((err) => {
98
+ console.error('Error listing files:', err);
99
+ return [];
100
+ });
101
+ }
102
+ /**
103
+ * Save a file to the bucket
104
+ * @param filePath The path to save the file to, relative to the endpoint
105
+ * @param fileContent The contents of the file as a buffer
106
+ * @returns The public URL of the file
107
+ */
108
+ async saveFile(filePath, fileContent, mimeType, preventDuplicate = false) {
109
+ let bucket = this.bucket;
110
+ filePath = this.normalizePath(filePath);
111
+ if (!mimeType) {
112
+ mimeType = mime.getType(filePath);
113
+ }
114
+ // console.log(`mimeType of ${filePath} is ${mimeType}`);
115
+ //first check if the object already exists
116
+ if (preventDuplicate && (await this.fileExists(filePath))) {
117
+ //if yes, use a more unique name based on the current unix timestamp
118
+ filePath = `${path.dirname(filePath)}/${Date.now()}-${path.basename(filePath)}`;
119
+ console.log('File already exists, renaming to avoid overwrite: ' + filePath);
120
+ }
121
+ const key = this.applyPrefix(filePath);
122
+ let res = await bucket
123
+ .putObject(key, fileContent, {
124
+ ContentType: mimeType,
125
+ })
126
+ .catch((err) => {
127
+ console.error('Error saving file to S3:', err);
128
+ return false;
129
+ });
130
+ if (!res) {
131
+ return null;
132
+ }
133
+ return this.accessURL + '/' + filePath;
134
+ }
135
+ /**
136
+ * Get a file from the bucket
137
+ * @param filePath The path of the file to get, relative to the endpoint
138
+ * @returns The contents of the file as a buffer
139
+ */
140
+ async getFile(filePath) {
141
+ let bucket = this.bucket;
142
+ const key = this.applyPrefix(filePath);
143
+ const bufferString = await bucket.getObject(key);
144
+ return Buffer.from(bufferString, 'base64');
145
+ }
146
+ /**
147
+ * Delete a file from the bucket
148
+ * @param filePath The path of the file to delete, relative to the endpoint
149
+ */
150
+ async deleteFile(filePath) {
151
+ let bucket = this.bucket;
152
+ await bucket.deleteObject(this.applyPrefix(filePath));
153
+ }
154
+ /**
155
+ * Check if a file exists in the bucket
156
+ * @param filePath The path of the file to check, relative to the endpoint
157
+ * @returns Whether the file exists
158
+ */
159
+ async fileExists(filePath) {
160
+ try {
161
+ const bucket = await this.bucket.getObject(this.applyPrefix(filePath));
162
+ if (!bucket) {
163
+ return false;
164
+ }
165
+ return true;
166
+ }
167
+ catch (e) {
168
+ return false;
169
+ }
170
+ }
171
+ }
172
+ S3FileStore.targetClass = s3.FileStore;
173
+ //# sourceMappingURL=S3FileStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"S3FileStore.js","sourceRoot":"","sources":["../../../src/shapes/S3FileStore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,93 @@
1
+ const trimTrailingSlash = (value = '') => value.replace(/\/+$/g, '');
2
+ const trimSlashes = (value = '') => value.replace(/^\/+|\/+$/g, '');
3
+ /**
4
+ * Read env vars in a browser-safe way while still allowing webpack EnvironmentPlugin
5
+ * to inline direct `process.env.X` references at build time.
6
+ */
7
+ const readEnv = (getter) => {
8
+ try {
9
+ return getter();
10
+ }
11
+ catch (_error) {
12
+ return undefined;
13
+ }
14
+ };
15
+ // Shared legacy env set used when scoped STATIC_/UPLOADS_ vars are absent.
16
+ const getSharedS3Env = () => ({
17
+ accessURL: readEnv(() => process.env.S3_CDN_URL),
18
+ endpoint: readEnv(() => process.env.S3_BUCKET_ENDPOINT),
19
+ bucketName: readEnv(() => process.env.S3_FILES_BUCKET_NAME),
20
+ });
21
+ // Returns the first defined, non-empty value from a fallback chain.
22
+ const firstNonEmpty = (...values) => {
23
+ for (const value of values) {
24
+ if (value !== undefined && value !== null && value !== '') {
25
+ return value;
26
+ }
27
+ }
28
+ return undefined;
29
+ };
30
+ // Builds versioned/static URL segments without duplicate or broken slashes.
31
+ const appendPathSegment = (base, segment) => {
32
+ const cleanBase = trimTrailingSlash(base || '');
33
+ const cleanSegment = trimSlashes(segment || '');
34
+ if (!cleanBase) {
35
+ return undefined;
36
+ }
37
+ if (!cleanSegment || cleanBase.endsWith(`/${cleanSegment}`)) {
38
+ return cleanBase;
39
+ }
40
+ return `${cleanBase}/${cleanSegment}`;
41
+ };
42
+ // Normalizes the final public access URL from either direct accessURL or endpoint+bucket.
43
+ const getAccessURL = ({ accessURL, endpoint, bucketName, }) => {
44
+ if (accessURL) {
45
+ return trimTrailingSlash(accessURL);
46
+ }
47
+ if (endpoint && bucketName) {
48
+ return `${trimTrailingSlash(endpoint)}/${bucketName}`;
49
+ }
50
+ return trimTrailingSlash(endpoint);
51
+ };
52
+ /**
53
+ * Access URL for user-uploaded files. This intentionally prefers upload-specific
54
+ * env vars, then falls back to legacy shared env vars.
55
+ */
56
+ export const getAccessURLUploadsStore = () => {
57
+ const shared = getSharedS3Env();
58
+ const uploadsAccessURL = readEnv(() => process.env.UPLOADS_ACCESS_URL);
59
+ const uploadsEndpoint = readEnv(() => process.env.UPLOADS_S3_BUCKET_ENDPOINT);
60
+ const uploadsBucketName = readEnv(() => process.env.UPLOADS_S3_FILES_BUCKET_NAME);
61
+ return getAccessURL({
62
+ accessURL: firstNonEmpty(uploadsAccessURL, shared.accessURL),
63
+ endpoint: firstNonEmpty(uploadsEndpoint, shared.endpoint),
64
+ bucketName: firstNonEmpty(uploadsBucketName, shared.bucketName),
65
+ });
66
+ };
67
+ /**
68
+ * Access URL for static web assets (bundles/images/root). This can be independent
69
+ * from uploads and is expected to include the release version when configured by
70
+ * app storage bootstrap (for example ".../4.1.1").
71
+ */
72
+ export const getAccessURLStaticStore = () => {
73
+ const shared = getSharedS3Env();
74
+ const uploadsEndpoint = readEnv(() => process.env.UPLOADS_S3_BUCKET_ENDPOINT);
75
+ const uploadsBucketName = readEnv(() => process.env.UPLOADS_S3_FILES_BUCKET_NAME);
76
+ const staticAccessURL = readEnv(() => process.env.STATIC_ACCESS_URL);
77
+ const version = readEnv(() => process.env.VERSION);
78
+ const staticEndpoint = readEnv(() => process.env.STATIC_S3_BUCKET_ENDPOINT);
79
+ const staticBucketName = readEnv(() => process.env.STATIC_S3_FILES_BUCKET_NAME);
80
+ // If STATIC_ACCESS_URL is not set, derive it from shared CDN + VERSION.
81
+ // This keeps static assets versioned even with legacy env-only configs.
82
+ const fallbackStaticAccessURL = appendPathSegment(shared.accessURL, version);
83
+ return getAccessURL({
84
+ accessURL: firstNonEmpty(staticAccessURL, fallbackStaticAccessURL),
85
+ endpoint: firstNonEmpty(staticEndpoint, uploadsEndpoint, shared.endpoint),
86
+ bucketName: firstNonEmpty(staticBucketName, uploadsBucketName, shared.bucketName),
87
+ });
88
+ };
89
+ /**
90
+ * Backward-compatible alias for existing imports.
91
+ */
92
+ export const getAccessURLS3FileStore = () => getAccessURLUploadsStore();
93
+ //# sourceMappingURL=accessUrl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accessUrl.js","sourceRoot":"","sources":["../../../src/utils/accessUrl.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -9,18 +9,19 @@
9
9
  },
10
10
  "repository": {
11
11
  "type": "git",
12
- "url": ""
12
+ "url": "git+https://github.com/linked-fw/s3.git"
13
13
  },
14
- "version": "1.0.3",
14
+ "version": "1.1.1",
15
15
  "linkedPackage": true,
16
- "main": "lib/cjs/index.js",
17
- "types": "dist/s3.d.ts",
16
+ "type": "module",
17
+ "main": "lib/esm/index.js",
18
+ "types": "./lib/esm/index.d.ts",
18
19
  "license": "ISC",
19
20
  "scripts": {
20
21
  "start": "npm exec linked dev",
21
- "build": "yarn linked build",
22
- "prepublishOnly": "yarn linked build production",
23
- "postpublish": "npm exec linked register"
22
+ "build": "rimraf ./lib && yarn build-esm && yarn copy-to-lib",
23
+ "build-esm": "echo \"compiling ESM\" && rimraf ./lib/esm && (yarn tsc -p tsconfig-esm.json || echo 'tsc returned non-zero; .js still emitted via noEmitOnError default')",
24
+ "copy-to-lib": "echo 'copying JSON assets to lib folder' && yarn copyfiles -u 1 'src/**/*.json' lib/esm"
24
25
  },
25
26
  "keywords": [
26
27
  "lincd",
@@ -35,8 +36,8 @@
35
36
  ],
36
37
  "dependencies": {
37
38
  "@_linked/core": "^2.2.1",
38
- "@_linked/server": "~1.0",
39
- "@_linked/server-utils": "~1.0",
39
+ "@_linked/server": "^2.0.0",
40
+ "@_linked/server-utils": "^1.0",
40
41
  "@aws-sdk/client-s3": "^3.159.0",
41
42
  "@aws-sdk/credential-providers": "^3.159.0",
42
43
  "cron": "^3.1.7",
@@ -47,6 +48,8 @@
47
48
  "@changesets/changelog-github": "^0.5.2",
48
49
  "@changesets/cli": "^2.29.8",
49
50
  "@types/mime": "^3.0.4",
51
+ "copyfiles": "^2.4.1",
52
+ "rimraf": "^5.0.7",
50
53
  "tsconfig-to-dual-package": "^1.2.0",
51
54
  "typescript": "^5.7.3",
52
55
  "typescript-plugin-css-modules": "^5.1.0"
@@ -55,18 +58,15 @@
55
58
  "exports": {
56
59
  ".": {
57
60
  "types": "./lib/esm/index.d.ts",
58
- "import": "./lib/esm/index.js",
59
- "require": "./lib/cjs/index.js"
61
+ "import": "./lib/esm/index.js"
60
62
  },
61
63
  "./*.js": {
62
64
  "types": "./lib/esm/*.d.ts",
63
- "import": "./lib/esm/*.js",
64
- "require": "./lib/cjs/*.js"
65
+ "import": "./lib/esm/*.js"
65
66
  },
66
67
  "./*": {
67
68
  "types": "./lib/esm/*.d.ts",
68
- "import": "./lib/esm/*.js",
69
- "require": "./lib/cjs/*.js"
69
+ "import": "./lib/esm/*.js"
70
70
  }
71
71
  },
72
72
  "typesVersions": {
package/tsconfig-esm.json CHANGED
@@ -4,6 +4,6 @@
4
4
  "module": "esnext",
5
5
  "target": "es2018",
6
6
  "outDir": "lib/esm",
7
- "moduleResolution": "node"
7
+ "moduleResolution": "bundler"
8
8
  }
9
9
  }
@@ -1,44 +0,0 @@
1
- name: Changeset Check
2
-
3
- on:
4
- pull_request:
5
- branches:
6
- - main
7
-
8
- jobs:
9
- changeset-check:
10
- name: Check for changeset
11
- # Skip the check on the automated Release PR.
12
- if: ${{ github.head_ref != 'changeset-release/main' }}
13
- runs-on: ubuntu-latest
14
- steps:
15
- - name: Checkout
16
- uses: actions/checkout@v4
17
- with:
18
- fetch-depth: 0
19
-
20
- - name: Check for changeset files
21
- uses: actions/github-script@v7
22
- with:
23
- script: |
24
- const { data: files } = await github.rest.pulls.listFiles({
25
- owner: context.repo.owner,
26
- repo: context.repo.repo,
27
- pull_number: context.issue.number,
28
- });
29
-
30
- const hasChangeset = files.some(f =>
31
- f.filename.startsWith('.changeset/') &&
32
- f.filename.endsWith('.md') &&
33
- f.filename !== '.changeset/README.md'
34
- );
35
-
36
- if (!hasChangeset) {
37
- await github.rest.issues.createComment({
38
- owner: context.repo.owner,
39
- repo: context.repo.repo,
40
- issue_number: context.issue.number,
41
- body: "No changeset found. If this PR should trigger a release, run `npx changeset` and commit the generated file.\n\nIf this change doesn't need a release (docs, CI config, etc.), you can ignore this message."
42
- });
43
- core.warning('No changeset file found in this PR.');
44
- }
@@ -1,43 +0,0 @@
1
- name: CI
2
-
3
- on:
4
- pull_request:
5
- branches:
6
- - main
7
-
8
- jobs:
9
- build-and-test:
10
- name: Build & Test
11
- runs-on: ubuntu-latest
12
- steps:
13
- - name: Detect Release PR
14
- id: rpr
15
- run: |
16
- if [[ "${{ github.event.pull_request.head.ref }}" == "changeset-release/main" ]]; then
17
- echo "is_release_pr=true" >> $GITHUB_OUTPUT
18
- echo "Release PR from changesets/action detected — skipping build/test (auto-generated version+CHANGELOG only)."
19
- else
20
- echo "is_release_pr=false" >> $GITHUB_OUTPUT
21
- fi
22
-
23
- - name: Checkout
24
- if: steps.rpr.outputs.is_release_pr == 'false'
25
- uses: actions/checkout@v4
26
-
27
- - name: Setup Node.js
28
- if: steps.rpr.outputs.is_release_pr == 'false'
29
- uses: actions/setup-node@v4
30
- with:
31
- node-version: 22.16.0
32
-
33
- - name: Install dependencies
34
- if: steps.rpr.outputs.is_release_pr == 'false'
35
- run: npm ci --legacy-peer-deps
36
-
37
- - name: Build
38
- if: steps.rpr.outputs.is_release_pr == 'false'
39
- run: npm run build
40
-
41
- - name: Test
42
- if: steps.rpr.outputs.is_release_pr == 'false'
43
- run: npm test --if-present
File without changes
@@ -1,20 +0,0 @@
1
- {
2
- "@context": {
3
- "dc": "http://purl.org/dc/elements/1.1/",
4
- "owl": "http://www.w3.org/2002/07/owl#",
5
- "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
6
- "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
7
- "s3": "http://lincd.org/ont/s3/"
8
- },
9
- "@graph": [
10
- {
11
- "@id": "s3:ExampleClass",
12
- "@type": "rdfs:Class",
13
- "rdfs:comment": "This is an example class. You can remove or rename it",
14
- "rdfs:isDefinedBy": {
15
- "@id": "s3:"
16
- },
17
- "rdfs:label": "Example Class"
18
- }
19
- ]
20
- }
@@ -1,5 +0,0 @@
1
- import './types.js';
2
- import './ontologies/s3.js';
3
- import './shapes/S3Bucket.js';
4
- import './shapes/S3FileStore.js';
5
- import './utils/accessUrl.js';
@@ -1,38 +0,0 @@
1
- export declare var loadData: () => Promise<{
2
- "@context": {
3
- dc: string;
4
- owl: string;
5
- rdf: string;
6
- rdfs: string;
7
- s3: string;
8
- };
9
- "@graph": {
10
- "@id": string;
11
- "@type": string;
12
- "rdfs:comment": string;
13
- "rdfs:isDefinedBy": {
14
- "@id": string;
15
- };
16
- "rdfs:label": string;
17
- }[];
18
- }>;
19
- export declare var ns: (term: string) => import("@_linked/core/utils/NodeReference.js").NodeReferenceValue;
20
- export declare var _self: import("@_linked/core/utils/NodeReference.js").NodeReferenceValue;
21
- export declare var Bucket: import("@_linked/core/utils/NodeReference.js").NodeReferenceValue;
22
- export declare var FileStore: import("@_linked/core/utils/NodeReference.js").NodeReferenceValue;
23
- export declare var FrontendStore: import("@_linked/core/utils/NodeReference.js").NodeReferenceValue;
24
- export declare var QuadStore: import("@_linked/core/utils/NodeReference.js").NodeReferenceValue;
25
- export declare var bucket: import("@_linked/core/utils/NodeReference.js").NodeReferenceValue;
26
- export declare var endpoint: import("@_linked/core/utils/NodeReference.js").NodeReferenceValue;
27
- export declare var key: import("@_linked/core/utils/NodeReference.js").NodeReferenceValue;
28
- export declare var secret: import("@_linked/core/utils/NodeReference.js").NodeReferenceValue;
29
- export declare const s3: {
30
- Bucket: import("@_linked/core/utils/NodeReference.js").NodeReferenceValue;
31
- FileStore: import("@_linked/core/utils/NodeReference.js").NodeReferenceValue;
32
- FrontendStore: import("@_linked/core/utils/NodeReference.js").NodeReferenceValue;
33
- QuadStore: import("@_linked/core/utils/NodeReference.js").NodeReferenceValue;
34
- bucket: import("@_linked/core/utils/NodeReference.js").NodeReferenceValue;
35
- endpoint: import("@_linked/core/utils/NodeReference.js").NodeReferenceValue;
36
- key: import("@_linked/core/utils/NodeReference.js").NodeReferenceValue;
37
- secret: import("@_linked/core/utils/NodeReference.js").NodeReferenceValue;
38
- };
@@ -1,4 +0,0 @@
1
- export declare const linkedShape: {
2
- <T extends typeof import("@_linked/core/shapes/Shape").Shape>(constructor: T): void;
3
- <T extends typeof import("@_linked/core/shapes/Shape").Shape>(config?: import("@_linked/core/utils/Package").ShapeConfig): (constructor: T) => void;
4
- }, linkedUtil: (constructor: any) => any, linkedOntology: (allFileExports: any, nameSpace: (term: string) => import("@_linked/core/utils/NodeReference").NodeReferenceValue, suggestedPrefixAndFileName: string, loadDataFunction?: () => Promise<any>, dataSource?: string | string[]) => void, registerPackageExport: (exportedObject: any) => void, packageExports: any, packageName: string;
@@ -1,63 +0,0 @@
1
- {
2
- "name": "@_linked/s3",
3
- "displayName": "s3",
4
- "description": "A general purpose Simple Storage Service (S3) package to be extended or used as is",
5
- "author": {
6
- "name": "Valentine Wilson",
7
- "email": "valentine@semantu.com",
8
- "url": "https://vw.codes"
9
- },
10
- "repository": {
11
- "type": "git",
12
- "url": ""
13
- },
14
- "version": "1.0.3",
15
- "linkedPackage": true,
16
- "license": "ISC",
17
- "scripts": {
18
- "start": "npm exec linked dev",
19
- "build": "yarn linked build",
20
- "prepublishOnly": "yarn linked build production",
21
- "postpublish": "npm exec linked register"
22
- },
23
- "keywords": [
24
- "lincd",
25
- "linked data",
26
- "interoperable",
27
- "semantic web",
28
- "web3",
29
- "s3",
30
- "simple storage service",
31
- "cloud storage",
32
- "aws"
33
- ],
34
- "dependencies": {
35
- "@_linked/core": "^2.2.1",
36
- "@_linked/server": "~1.0",
37
- "@_linked/server-utils": "~1.0",
38
- "@aws-sdk/client-s3": "^3.159.0",
39
- "@aws-sdk/credential-providers": "^3.159.0",
40
- "cron": "^3.1.7",
41
- "mime": "2.6.0"
42
- },
43
- "devDependencies": {
44
- "@_linked/cli": "^1.2",
45
- "@changesets/changelog-github": "^0.5.2",
46
- "@changesets/cli": "^2.29.8",
47
- "@types/mime": "^3.0.4",
48
- "tsconfig-to-dual-package": "^1.2.0",
49
- "typescript": "^5.7.3",
50
- "typescript-plugin-css-modules": "^5.1.0"
51
- },
52
- "typesVersions": {
53
- "*": {
54
- "*": [
55
- "lib/esm/*"
56
- ]
57
- }
58
- },
59
- "publishConfig": {
60
- "access": "public"
61
- },
62
- "type": "commonjs"
63
- }