Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@balena/sbvr-types

Package Overview
Dependencies
Maintainers
3
Versions
222
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@balena/sbvr-types - npm Package Compare versions

Comparing version 3.5.0-build-web-resource-2-a2bd417d257b1cfe74d327855816d43274c04b4c-1 to 3.5.0-build-web-resource-2-bcf04a246da11367b67f9683c035a749b5741ca2-1

5

CHANGELOG.md

@@ -8,6 +8,5 @@ # Change Log

# v3.5.0
## (2023-02-06)
## (2023-03-10)
* Address feedback on new sbvr-type [Nitish Agarwal]
* Add type WebResource [Ramiro González Maciel]
* Adds WebResource type [Otávio Jacobi]

@@ -14,0 +13,0 @@ # v3.4.19

22

out/types/web-resource.d.ts

@@ -1,4 +0,2 @@

/// <reference types="node" />
import { Buffer } from 'buffer';
export type WebResourceRef = {
export type WebResource = {
filename: string;

@@ -10,10 +8,2 @@ href: string;

};
export type WebResourceInput = {
filename: string;
data: Buffer;
contentType?: string;
contentDisposition?: string;
size?: number;
storage: string;
};
export declare const types: {

@@ -30,7 +20,7 @@ postgres: string;

has: {
Filename: (from: any) => any[];
HRef: (from: any) => any[];
'Content Type': (from: any) => any[];
'Content Disposition': (from: any) => any[];
Size: (from: any) => any[];
Filename: (stringifiedResource: string) => (string | (string | string[])[])[];
HRef: (stringifiedResource: string) => (string | (string | string[])[])[];
'Content Type': (stringifiedResource: string) => (string | (string | string[])[])[];
'Content Disposition': (stringifiedResource: string) => (string | (string | string[])[])[];
Size: (stringifiedResource: string) => (string | (string | (string | string[])[])[])[];
};

@@ -37,0 +27,0 @@ };

@@ -5,4 +5,2 @@ "use strict";

const TypeUtils = require("../type-utils");
const index_1 = require("../storage-adapters/index");
const buffer_1 = require("buffer");
exports.types = {

@@ -26,26 +24,30 @@ postgres: 'JSONB',

has: {
Filename: (from) => [
Filename: (stringifiedResource) => [
'ExtractJSONPathAsText',
from,
stringifiedResource,
['TextArray', ['EmbeddedText', 'filename']],
],
HRef: (from) => [
HRef: (stringifiedResource) => [
'ExtractJSONPathAsText',
from,
stringifiedResource,
['TextArray', ['EmbeddedText', 'href']],
],
'Content Type': (from) => [
'Content Type': (stringifiedResource) => [
'ExtractJSONPathAsText',
from,
stringifiedResource,
['TextArray', ['EmbeddedText', 'contentType']],
],
'Content Disposition': (from) => [
'Content Disposition': (stringifiedResource) => [
'ExtractJSONPathAsText',
from,
stringifiedResource,
['TextArray', ['EmbeddedText', 'contentDisposition']],
],
Size: (from) => [
'ExtractJSONPathAsText',
from,
['TextArray', ['EmbeddedText', 'size']],
Size: (stringifiedResource) => [
'Cast',
[
'ExtractJSONPathAsText',
stringifiedResource,
['TextArray', ['EmbeddedText', 'size']],
],
'Integer',
],

@@ -86,37 +88,26 @@ },

}
if (!value.filename) {
throw new Error('filename is required');
}
if (typeof value.filename !== 'string') {
throw new Error('filename string is required');
throw new Error('filename must be a string');
}
if (!buffer_1.Buffer.isBuffer(value.data)) {
throw new Error('data is required');
if (!value.href) {
throw new Error('href is required');
}
const storage = value.storage;
if (typeof storage !== 'string') {
throw new Error('storage is required');
if (typeof value.href !== 'string') {
throw new Error('href must be a string');
}
const storageAdapter = (0, index_1.getStorageAdapter)(storage);
if (!storageAdapter) {
throw new Error(`storage named '${storage}' not defined`);
if (value.contentType && typeof value.contentType !== 'string') {
throw new Error('contentType must be a string');
}
let webresource;
const contentOptions = {
contentType: value.contentType,
contentDisposition: value.contentDisposition,
};
try {
webresource = await storageAdapter.saveFile(value.filename, value.data, contentOptions);
if (value.contentDisposition &&
typeof value.contentDisposition !== 'string') {
throw new Error('contentDisposition must be a string');
}
catch (e) {
throw new Error(`can't be saved; error ${e.message}`);
if (value.size && !Number.isInteger(value.size)) {
throw new Error('size must be an integer');
}
const refData = {
filename: value.filename,
href: webresource.href,
contentType: value.contentType,
contentDisposition: value.contentDisposition,
size: value.size,
};
try {
const processedValue = JSON.stringify(refData);
return processedValue;
return JSON.stringify(value);
}

@@ -123,0 +114,0 @@ catch (e) {

{
"name": "@balena/sbvr-types",
"version": "3.5.0-build-web-resource-2-a2bd417d257b1cfe74d327855816d43274c04b4c-1",
"version": "3.5.0-build-web-resource-2-bcf04a246da11367b67f9683c035a749b5741ca2-1",
"description": "SBVR type definitions.",

@@ -55,4 +55,4 @@ "main": "out",

"versionist": {
"publishedAt": "2023-02-06T13:22:06.975Z"
"publishedAt": "2023-03-10T12:08:27.231Z"
}
}

@@ -155,33 +155,1 @@ # sbvr-types

Tests can be found under the `test/` folder, to run the whole suite use `npm test`
## Storing files and other large objects
An application can choose between two types to save file content or another large object: `File` or `WebResource`. When using a `File`, PineJS saves the content in the database using a binary data type like `BYTEA` or `BLOB`. When using a `WebResource`, PineJS saves the binary content on an external storage service and then writes metadata, including the content public URL, to the database. Client apps use the `WebResource` `href` to get the content.
### WebResource
Type [`WebResource`](./src//types/web-resource.ts) can be used to persist files or other large content on an external object storage service like MinIO or Amazon S3. By "object storage" we refer to a service that can store the content and provide a URL to access that content.
In order to save a `WebResource` you send an instance of [`WebResourceInput`](./src/types/web-resource.ts#L18)
```js
{
filename: string;
data: Buffer;
contentType?: string;
contentDisposition?: string;
size?: number;
storage: string;
}
```
A typical use case is to have a web app where users can upload a file. The app will use [multer](https://github.com/expressjs/multer) to get the file from the http request as a `Buffer` and pass it as the `data` attribute of a `WebResourceInput`.
When retrieving a `WebResource` the `data` attribute is replaced by an `href`( URL ) attribute. See [`WebResourceRef`](./src/types/web-resource.ts#L7)
#### Storage Adapters
The `storage` attribute specifies the name of an [`StorageAdapter`](./src/storage-adapters/storage-adapter.ts#L7). A `StorageAdapter` saves the content to a specific storage, performing a function similar to what a database driver provides. For example, [pinejs-s3-storage](https://github.com/balena-io-modules/pinejs-s3-storage) saves the content to S3/MinIO and returns a URL to the persisted object. For testing purposes, this module uses [disk-storage-adapter](./test/storage-adapters/disk-storage-adapter.js).
Applications need to load the `StorageAdapter`s they need in the `storageRegistry`(./src/storage-adapters/index.ts#L4). Please refer to each specific storage adapter for more configuration and setup details.
import * as TypeUtils from '../type-utils';
import { ContentOptions, getStorageAdapter } from '../storage-adapters/index';
import { Buffer } from 'buffer';
/**
* This is how WebResources are stored on the DB
*/
export type WebResourceRef = {
export type WebResource = {
filename: string;

@@ -16,14 +11,2 @@ href: string;

/**
* This is how WebResources are defined on creation
*/
export type WebResourceInput = {
filename: string;
data: Buffer;
contentType?: string;
contentDisposition?: string;
size?: number;
storage: string;
};
export const types = {

@@ -48,26 +31,30 @@ postgres: 'JSONB',

has: {
Filename: (from: any) => [
Filename: (stringifiedResource: string) => [
'ExtractJSONPathAsText',
from,
stringifiedResource,
['TextArray', ['EmbeddedText', 'filename']],
],
HRef: (from: any) => [
HRef: (stringifiedResource: string) => [
'ExtractJSONPathAsText',
from,
stringifiedResource,
['TextArray', ['EmbeddedText', 'href']],
],
'Content Type': (from: any) => [
'Content Type': (stringifiedResource: string) => [
'ExtractJSONPathAsText',
from,
stringifiedResource,
['TextArray', ['EmbeddedText', 'contentType']],
],
'Content Disposition': (from: any) => [
'Content Disposition': (stringifiedResource: string) => [
'ExtractJSONPathAsText',
from,
stringifiedResource,
['TextArray', ['EmbeddedText', 'contentDisposition']],
],
Size: (from: any) => [
'ExtractJSONPathAsText',
from,
['TextArray', ['EmbeddedText', 'size']],
Size: (stringifiedResource: string) => [
'Cast',
[
'ExtractJSONPathAsText',
stringifiedResource,
['TextArray', ['EmbeddedText', 'size']],
],
'Integer',
],

@@ -77,4 +64,11 @@ },

/**
* Converts the data, which comes from the DB as a string or object depending on the
* column type, to a WebResource object
*
* @param data string|object
* @returns a WebResource parsed from the DB
*/
export const fetchProcessing = (data: any) => {
let refData: WebResourceRef;
let refData: WebResource;
if (data === null) {

@@ -108,49 +102,39 @@ return data;

/**
* Validates the value content.
*
* Returns a Stringified WebResource that will be persisted on the DB
*
*/
export const validate = TypeUtils.validate.checkRequired(
async (value: WebResourceInput) => {
async (value: WebResource) => {
if (typeof value !== 'object') {
throw new Error(`is not an object: ${typeof value}`);
}
if (!value.filename) {
throw new Error('filename is required');
}
if (typeof value.filename !== 'string') {
throw new Error('filename string is required');
throw new Error('filename must be a string');
}
if (!Buffer.isBuffer(value.data)) {
throw new Error('data is required');
if (!value.href) {
throw new Error('href is required');
}
const storage = value.storage;
if (typeof storage !== 'string') {
throw new Error('storage is required');
if (typeof value.href !== 'string') {
throw new Error('href must be a string');
}
const storageAdapter = getStorageAdapter(storage);
if (!storageAdapter) {
throw new Error(`storage named '${storage}' not defined`);
if (value.contentType && typeof value.contentType !== 'string') {
throw new Error('contentType must be a string');
}
let webresource;
const contentOptions: ContentOptions = {
contentType: value.contentType,
contentDisposition: value.contentDisposition,
};
try {
webresource = await storageAdapter.saveFile(
value.filename,
value.data,
contentOptions,
);
} catch (e: any) {
throw new Error(`can't be saved; error ${e.message}`);
if (
value.contentDisposition &&
typeof value.contentDisposition !== 'string'
) {
throw new Error('contentDisposition must be a string');
}
const refData: WebResourceRef = {
filename: value.filename,
href: webresource.href,
contentType: value.contentType,
contentDisposition: value.contentDisposition,
size: value.size,
};
if (value.size && !Number.isInteger(value.size)) {
throw new Error('size must be an integer');
}
try {
const processedValue = JSON.stringify(refData);
return processedValue;
return JSON.stringify(value);
} catch (e: any) {

@@ -157,0 +141,0 @@ throw new Error(`can't be stringified; error ${e.message}`);

@@ -7,2 +7,3 @@ {

"noImplicitAny": true,
"noUncheckedIndexedAccess": true,
"noUnusedParameters": true,

@@ -9,0 +10,0 @@ "noUnusedLocals": true,

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc