@coreviz/sdk 1.0.0
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 +24 -0
- package/dist/describe.d.ts +1 -0
- package/dist/describe.js +29 -0
- package/dist/edit.d.ts +7 -0
- package/dist/edit.js +35 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +11 -0
- package/dist/resize.d.ts +1 -0
- package/dist/resize.js +161 -0
- package/dist/tag.d.ts +10 -0
- package/dist/tag.js +44 -0
- package/package.json +37 -0
package/README.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# @coreviz/sdk
|
|
2
|
+
|
|
3
|
+
CoreViz SDK - A JavaScript/Node.js interface for CoreViz's Vision AI APIs.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @coreviz/sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
const coreviz = require('@coreviz/sdk');
|
|
15
|
+
coreviz();
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Development
|
|
19
|
+
|
|
20
|
+
This is currently a placeholder package. The actual API functionality will be implemented soon.
|
|
21
|
+
|
|
22
|
+
## License
|
|
23
|
+
|
|
24
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function describe(image: string): Promise<string | undefined>;
|
package/dist/describe.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.describe = describe;
|
|
4
|
+
const resize_1 = require("./resize");
|
|
5
|
+
async function describe(image) {
|
|
6
|
+
try {
|
|
7
|
+
const resizedImage = await (0, resize_1.resize)(image);
|
|
8
|
+
const response = await fetch(`https://lab.coreviz.io/api/ai/describe`, {
|
|
9
|
+
method: 'POST',
|
|
10
|
+
headers: {
|
|
11
|
+
'x-api-key': process.env.COREVIZ_API_KEY || "",
|
|
12
|
+
'Content-Type': 'application/json',
|
|
13
|
+
},
|
|
14
|
+
body: JSON.stringify({ image: resizedImage }),
|
|
15
|
+
});
|
|
16
|
+
if (!response.ok) {
|
|
17
|
+
throw new Error(`Failed to describe image (${response.status})`);
|
|
18
|
+
}
|
|
19
|
+
const data = await response.json();
|
|
20
|
+
if (data.error) {
|
|
21
|
+
throw new Error(data.error);
|
|
22
|
+
}
|
|
23
|
+
return data.description;
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
console.error('Error in describeImage:', err);
|
|
27
|
+
throw err instanceof Error ? err : new Error("An unexpected error occurred.");
|
|
28
|
+
}
|
|
29
|
+
}
|
package/dist/edit.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface EditOptions {
|
|
2
|
+
prompt: string;
|
|
3
|
+
aspectRatio?: 'match_input_image' | '1:1' | '16:9' | '9:16' | '4:3' | '3:4';
|
|
4
|
+
outputFormat?: 'jpg' | 'png';
|
|
5
|
+
model?: 'flux-kontext-max' | 'google/nano-banana' | 'seedream-4';
|
|
6
|
+
}
|
|
7
|
+
export declare function edit(image: string, options: EditOptions): Promise<string | undefined>;
|
package/dist/edit.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.edit = edit;
|
|
4
|
+
const resize_1 = require("./resize");
|
|
5
|
+
async function edit(image, options) {
|
|
6
|
+
try {
|
|
7
|
+
const resizedImage = await (0, resize_1.resize)(image);
|
|
8
|
+
const response = await fetch(`https://lab.coreviz.io/api/ai/edit`, {
|
|
9
|
+
method: 'POST',
|
|
10
|
+
headers: {
|
|
11
|
+
'x-api-key': process.env.COREVIZ_API_KEY || "",
|
|
12
|
+
'Content-Type': 'application/json',
|
|
13
|
+
},
|
|
14
|
+
body: JSON.stringify({
|
|
15
|
+
image: resizedImage,
|
|
16
|
+
prompt: options.prompt,
|
|
17
|
+
aspectRatio: options.aspectRatio || 'match_input_image',
|
|
18
|
+
outputFormat: options.outputFormat || 'jpg',
|
|
19
|
+
model: options.model || 'flux-kontext-max',
|
|
20
|
+
}),
|
|
21
|
+
});
|
|
22
|
+
if (!response.ok) {
|
|
23
|
+
throw new Error(`Failed to edit image (${response.status})`);
|
|
24
|
+
}
|
|
25
|
+
const data = await response.json();
|
|
26
|
+
if (data.error) {
|
|
27
|
+
throw new Error(data.error);
|
|
28
|
+
}
|
|
29
|
+
return data.result;
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
console.error('Error in editImage:', err);
|
|
33
|
+
throw err instanceof Error ? err : new Error("An unexpected error occurred.");
|
|
34
|
+
}
|
|
35
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { describe } from './describe';
|
|
2
|
+
import { resize } from './resize';
|
|
3
|
+
import { edit, EditOptions } from './edit';
|
|
4
|
+
import { tag, TagOptions, TagResponse } from './tag';
|
|
5
|
+
export { describe, resize, edit, tag };
|
|
6
|
+
export type { EditOptions, TagOptions, TagResponse };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.tag = exports.edit = exports.resize = exports.describe = void 0;
|
|
4
|
+
const describe_1 = require("./describe");
|
|
5
|
+
Object.defineProperty(exports, "describe", { enumerable: true, get: function () { return describe_1.describe; } });
|
|
6
|
+
const resize_1 = require("./resize");
|
|
7
|
+
Object.defineProperty(exports, "resize", { enumerable: true, get: function () { return resize_1.resize; } });
|
|
8
|
+
const edit_1 = require("./edit");
|
|
9
|
+
Object.defineProperty(exports, "edit", { enumerable: true, get: function () { return edit_1.edit; } });
|
|
10
|
+
const tag_1 = require("./tag");
|
|
11
|
+
Object.defineProperty(exports, "tag", { enumerable: true, get: function () { return tag_1.tag; } });
|
package/dist/resize.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function resize(input: string | File, maxWidth?: number, maxHeight?: number): Promise<string>;
|
package/dist/resize.js
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.resize = resize;
|
|
37
|
+
const isBrowser = typeof window !== 'undefined';
|
|
38
|
+
async function resize(input, maxWidth = 1920, maxHeight = 1080) {
|
|
39
|
+
if (isBrowser) {
|
|
40
|
+
return clientResize(input, maxWidth, maxHeight);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
if (typeof input !== 'string') {
|
|
44
|
+
throw new Error("Server-side resizing only supports base64 strings or URLs.");
|
|
45
|
+
}
|
|
46
|
+
return serverResize(input, maxWidth, maxHeight);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async function clientResize(input, maxWidth, maxHeight) {
|
|
50
|
+
return new Promise((resolve, reject) => {
|
|
51
|
+
const img = new window.Image();
|
|
52
|
+
const handleLoad = () => {
|
|
53
|
+
let width = img.width;
|
|
54
|
+
let height = img.height;
|
|
55
|
+
if (width > height) {
|
|
56
|
+
if (width > maxWidth) {
|
|
57
|
+
height *= maxWidth / width;
|
|
58
|
+
width = maxWidth;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
if (height > maxHeight) {
|
|
63
|
+
width *= maxHeight / height;
|
|
64
|
+
height = maxHeight;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const canvas = document.createElement('canvas');
|
|
68
|
+
canvas.width = width;
|
|
69
|
+
canvas.height = height;
|
|
70
|
+
const ctx = canvas.getContext('2d');
|
|
71
|
+
if (!ctx) {
|
|
72
|
+
reject(new Error("Could not get canvas context"));
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
ctx.drawImage(img, 0, 0, width, height);
|
|
76
|
+
// Attempt to determine format from input if possible, defaulting to jpeg for efficiency/compatibility
|
|
77
|
+
// If input was a file, we can use its type. If string, we can try to parse.
|
|
78
|
+
let mimeType = 'image/jpeg';
|
|
79
|
+
if (input instanceof File) {
|
|
80
|
+
mimeType = input.type;
|
|
81
|
+
}
|
|
82
|
+
else if (typeof input === 'string') {
|
|
83
|
+
const match = input.match(/^data:(image\/\w+);base64,/);
|
|
84
|
+
if (match)
|
|
85
|
+
mimeType = match[1];
|
|
86
|
+
}
|
|
87
|
+
resolve(canvas.toDataURL(mimeType));
|
|
88
|
+
};
|
|
89
|
+
img.onload = handleLoad;
|
|
90
|
+
img.onerror = (error) => reject(error);
|
|
91
|
+
if (input instanceof File) {
|
|
92
|
+
const reader = new FileReader();
|
|
93
|
+
reader.onload = (e) => {
|
|
94
|
+
if (e.target?.result) {
|
|
95
|
+
img.src = e.target.result;
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
reader.onerror = reject;
|
|
99
|
+
reader.readAsDataURL(input);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
img.src = input;
|
|
103
|
+
}
|
|
104
|
+
// For base64 strings, we don't need to wait for reader, but we do need to wait for img.onload which is handled above.
|
|
105
|
+
// If input is string, setting src triggers load.
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
async function serverResize(inputStr, maxWidth, maxHeight) {
|
|
109
|
+
// If running in browser context, do not attempt to load sharp or Buffer
|
|
110
|
+
if (typeof window !== 'undefined') {
|
|
111
|
+
throw new Error("serverResize called in browser environment");
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
// Dynamic import to prevent bundling sharp on the client
|
|
115
|
+
const sharpModule = await Promise.resolve().then(() => __importStar(require('sharp')));
|
|
116
|
+
const sharp = sharpModule.default;
|
|
117
|
+
let buffer;
|
|
118
|
+
let mimeType = 'image/jpeg';
|
|
119
|
+
if (inputStr.startsWith('http://') || inputStr.startsWith('https://')) {
|
|
120
|
+
const response = await fetch(inputStr);
|
|
121
|
+
if (!response.ok) {
|
|
122
|
+
throw new Error(`Failed to fetch image from URL: ${response.statusText}`);
|
|
123
|
+
}
|
|
124
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
125
|
+
buffer = Buffer.from(arrayBuffer);
|
|
126
|
+
mimeType = response.headers.get('content-type') || 'image/jpeg';
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
// Remove data URL prefix if present
|
|
130
|
+
const base64Data = inputStr.replace(/^data:image\/\w+;base64,/, "");
|
|
131
|
+
// Buffer is a Node global, ensure it exists
|
|
132
|
+
if (typeof Buffer === 'undefined') {
|
|
133
|
+
throw new Error("Buffer is not defined");
|
|
134
|
+
}
|
|
135
|
+
buffer = Buffer.from(base64Data, 'base64');
|
|
136
|
+
mimeType = inputStr.match(/^data:(image\/\w+);base64,/)?.[1] || 'image/jpeg';
|
|
137
|
+
}
|
|
138
|
+
// Get image metadata
|
|
139
|
+
const metadata = await sharp(buffer).metadata();
|
|
140
|
+
if (metadata.width && metadata.height && (metadata.width > maxWidth || metadata.height > maxHeight)) {
|
|
141
|
+
const resizedBuffer = await sharp(buffer)
|
|
142
|
+
.resize({
|
|
143
|
+
width: maxWidth,
|
|
144
|
+
height: maxHeight,
|
|
145
|
+
fit: 'inside', // Maintain aspect ratio, fit inside dimensions
|
|
146
|
+
withoutEnlargement: true
|
|
147
|
+
})
|
|
148
|
+
.toBuffer();
|
|
149
|
+
return `data:${mimeType};base64,${resizedBuffer.toString('base64')}`;
|
|
150
|
+
}
|
|
151
|
+
// If input was a URL, return the fetched content as base64 to ensure downstream availability
|
|
152
|
+
if (inputStr.startsWith('http://') || inputStr.startsWith('https://')) {
|
|
153
|
+
return `data:${mimeType};base64,${buffer.toString('base64')}`;
|
|
154
|
+
}
|
|
155
|
+
return inputStr;
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
console.warn("Failed to resize image on server:", error);
|
|
159
|
+
return inputStr; // Fallback to original
|
|
160
|
+
}
|
|
161
|
+
}
|
package/dist/tag.d.ts
ADDED
package/dist/tag.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.tag = tag;
|
|
4
|
+
const resize_1 = require("./resize");
|
|
5
|
+
async function tag(image, options) {
|
|
6
|
+
try {
|
|
7
|
+
const resizedImage = await (0, resize_1.resize)(image);
|
|
8
|
+
const response = await fetch("https://lab.coreviz.io/api/ai/tag", {
|
|
9
|
+
method: 'POST',
|
|
10
|
+
headers: {
|
|
11
|
+
'x-api-key': process.env.COREVIZ_API_KEY || "",
|
|
12
|
+
'Content-Type': 'application/json',
|
|
13
|
+
},
|
|
14
|
+
body: JSON.stringify({
|
|
15
|
+
image: resizedImage,
|
|
16
|
+
prompt: options.prompt,
|
|
17
|
+
options: options.options && options.options.length > 0 ? options.options : undefined,
|
|
18
|
+
multiple: options.multiple ?? true,
|
|
19
|
+
}),
|
|
20
|
+
});
|
|
21
|
+
if (!response.ok) {
|
|
22
|
+
throw new Error(`Failed to tag image (${response.status})`);
|
|
23
|
+
}
|
|
24
|
+
const data = await response.json();
|
|
25
|
+
if (data.error) {
|
|
26
|
+
throw new Error(data.error);
|
|
27
|
+
}
|
|
28
|
+
const tags = Array.isArray(data.tags)
|
|
29
|
+
? data.tags
|
|
30
|
+
: Array.isArray(data.result)
|
|
31
|
+
? data.result
|
|
32
|
+
: typeof data.tag === 'string'
|
|
33
|
+
? [data.tag]
|
|
34
|
+
: [];
|
|
35
|
+
return {
|
|
36
|
+
tags,
|
|
37
|
+
raw: data,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
console.error('Error in tagImage:', err);
|
|
42
|
+
throw err instanceof Error ? err : new Error("An unexpected error occurred.");
|
|
43
|
+
}
|
|
44
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@coreviz/sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CoreViz SDK",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist",
|
|
9
|
+
"README.md"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc",
|
|
13
|
+
"prepublishOnly": "npm run build",
|
|
14
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/coreviz/sdk.git"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"api",
|
|
22
|
+
"coreviz"
|
|
23
|
+
],
|
|
24
|
+
"author": "CoreViz Team",
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/coreviz/sdk/issues"
|
|
28
|
+
},
|
|
29
|
+
"homepage": "https://github.com/coreviz/sdk#readme",
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/node": "^24.10.1",
|
|
32
|
+
"typescript": "^5.9.3"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"sharp": "^0.34.5"
|
|
36
|
+
}
|
|
37
|
+
}
|