@seedprotocol/sdk 0.2.43 → 0.2.44
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/dist/{ArweaveClient-BXD_aTsx.js → ArweaveClient-CA1Vsnow.js} +2 -2
- package/dist/{ArweaveClient-BXD_aTsx.js.map → ArweaveClient-CA1Vsnow.js.map} +1 -1
- package/dist/{ArweaveClient-CkcZD_QE.js → ArweaveClient-MgJXScYG.js} +2 -2
- package/dist/{ArweaveClient-CkcZD_QE.js.map → ArweaveClient-MgJXScYG.js.map} +1 -1
- package/dist/{Db-Bug4efsE.js → Db-BEoczaGe.js} +156 -165
- package/dist/{Db-Bug4efsE.js.map → Db-BEoczaGe.js.map} +1 -1
- package/dist/{Db-B4XyOmGy.js → Db-Y1GWsyNL.js} +34 -43
- package/dist/{Db-B4XyOmGy.js.map → Db-Y1GWsyNL.js.map} +1 -1
- package/dist/{EasClient-BNwSwDTO.js → EasClient-BjlbuffX.js} +2 -2
- package/dist/{EasClient-BNwSwDTO.js.map → EasClient-BjlbuffX.js.map} +1 -1
- package/dist/{EasClient-epqE9aWI.js → EasClient-Cg1q8lBu.js} +2 -2
- package/dist/{EasClient-epqE9aWI.js.map → EasClient-Cg1q8lBu.js.map} +1 -1
- package/dist/FileManager-D53H3aUS.js +781 -0
- package/dist/FileManager-D53H3aUS.js.map +1 -0
- package/dist/FileManager-t4zcT3NL.js +38 -0
- package/dist/FileManager-t4zcT3NL.js.map +1 -0
- package/dist/{Item-vjJTzf1d.js → Item-BleJyiA2.js} +9 -12
- package/dist/{Item-vjJTzf1d.js.map → Item-BleJyiA2.js.map} +1 -1
- package/dist/{ItemProperty-DJpbernm.js → ItemProperty-CH7JmVg-.js} +9 -12
- package/dist/{ItemProperty-DJpbernm.js.map → ItemProperty-CH7JmVg-.js.map} +1 -1
- package/dist/{QueryClient-Do0C7Jnt.js → QueryClient-BKjgZnSt.js} +2 -2
- package/dist/{QueryClient-Do0C7Jnt.js.map → QueryClient-BKjgZnSt.js.map} +1 -1
- package/dist/{QueryClient-Ckl99FYC.js → QueryClient-CDsEencG.js} +2 -2
- package/dist/{QueryClient-Ckl99FYC.js.map → QueryClient-CDsEencG.js.map} +1 -1
- package/dist/bin.js +28 -27
- package/dist/bin.js.map +1 -1
- package/dist/{constants-BakHTrB9.js → constants-BIdH8wc3.js} +66 -41
- package/dist/constants-BIdH8wc3.js.map +1 -0
- package/dist/{index-DcPIAiHD.js → index-DanGFTTF.js} +1263 -1536
- package/dist/index-DanGFTTF.js.map +1 -0
- package/dist/{index-BWIn7kWN.js → index-Dk6K4W4n.js} +9 -12
- package/dist/index-Dk6K4W4n.js.map +1 -0
- package/dist/main.js +7 -10
- package/dist/main.js.map +1 -1
- package/dist/node/codegen/templates/index.njk +0 -4
- package/dist/{seed.schema.config-DGcg6TCS.js → seed.schema.config-DdCq87m_.js} +9 -11
- package/dist/seed.schema.config-DdCq87m_.js.map +1 -0
- package/dist/seedSchema/index.ts +0 -2
- package/dist/src/BaseFileManager.ts +22 -2
- package/dist/src/BaseItem.ts +4 -3
- package/dist/src/BaseItemProperty.ts +2 -2
- package/dist/src/FileDownloader.ts +63 -0
- package/dist/src/FileManager.ts +37 -6
- package/dist/src/ImageResizer.ts +84 -0
- package/dist/src/analyzeInput.ts +22 -2
- package/dist/src/constants.ts +67 -60
- package/dist/src/createMetadata.ts +27 -2
- package/dist/src/download.ts +45 -202
- package/dist/src/filesDownload.ts +326 -0
- package/dist/src/getItem.ts +5 -0
- package/dist/src/getPublishPayload.ts +15 -8
- package/dist/src/helpers.ts +0 -14
- package/dist/src/imageResize.ts +507 -0
- package/dist/src/model.ts +6 -5
- package/dist/src/saveImageSrc.ts +15 -1
- package/dist/src/syncDbWithEas.ts +0 -90
- package/dist/src/updateItemPropertyValue.ts +16 -3
- package/dist/src/waitForDb.ts +18 -17
- package/dist/types/src/Item/BaseItem.d.ts +2 -2
- package/dist/types/src/Item/BaseItem.d.ts.map +1 -1
- package/dist/types/src/ItemProperty/BaseItemProperty.d.ts +2 -2
- package/dist/types/src/ItemProperty/BaseItemProperty.d.ts.map +1 -1
- package/dist/types/src/ItemProperty/service/actors/saveValueToDb/analyzeInput.d.ts.map +1 -1
- package/dist/types/src/ItemProperty/service/actors/saveValueToDb/saveImageSrc.d.ts.map +1 -1
- package/dist/types/src/browser/helpers/FileManager.d.ts +5 -1
- package/dist/types/src/browser/helpers/FileManager.d.ts.map +1 -1
- package/dist/types/src/browser/workers/FileDownloader.d.ts +8 -0
- package/dist/types/src/browser/workers/FileDownloader.d.ts.map +1 -0
- package/dist/types/src/browser/workers/ImageResizer.d.ts +9 -0
- package/dist/types/src/browser/workers/ImageResizer.d.ts.map +1 -0
- package/dist/types/src/browser/workers/content-hash.d.ts.map +1 -0
- package/dist/types/src/browser/workers/filesDownload.d.ts +3 -0
- package/dist/types/src/browser/workers/filesDownload.d.ts.map +1 -0
- package/dist/types/src/browser/workers/imageResize.d.ts +3 -0
- package/dist/types/src/browser/workers/imageResize.d.ts.map +1 -0
- package/dist/types/src/db/read/getItem.d.ts.map +1 -1
- package/dist/types/src/db/read/getPublishPayload.d.ts.map +1 -1
- package/dist/types/src/db/write/createMetadata.d.ts.map +1 -1
- package/dist/types/src/db/write/updateItemPropertyValue.d.ts +5 -1
- package/dist/types/src/db/write/updateItemPropertyValue.d.ts.map +1 -1
- package/dist/types/src/events/files/download.d.ts.map +1 -1
- package/dist/types/src/events/files/index.d.ts.map +1 -1
- package/dist/types/src/events/item/syncDbWithEas.d.ts.map +1 -1
- package/dist/types/src/helpers/FileManager/BaseFileManager.d.ts +4 -0
- package/dist/types/src/helpers/FileManager/BaseFileManager.d.ts.map +1 -1
- package/dist/types/src/helpers/constants.d.ts +7 -0
- package/dist/types/src/helpers/constants.d.ts.map +1 -1
- package/dist/types/src/helpers/files.d.ts +1 -1
- package/dist/types/src/helpers/files.d.ts.map +1 -1
- package/dist/types/src/node/helpers/FileManager.d.ts +5 -0
- package/dist/types/src/node/helpers/FileManager.d.ts.map +1 -1
- package/dist/types/src/schema/model/index.d.ts +2 -2
- package/dist/types/src/schema/model/index.d.ts.map +1 -1
- package/dist/types/src/seedSchema/index.d.ts +0 -2
- package/dist/types/src/seedSchema/index.d.ts.map +1 -1
- package/dist/types/src/services/allItems/actors/initialize.d.ts.map +1 -1
- package/dist/types/src/services/internal/constants.d.ts +2 -2
- package/dist/types/src/services/internal/constants.d.ts.map +1 -1
- package/dist/types/src/services/internal/helpers.d.ts.map +1 -1
- package/dist/types/src/types/fileManager.d.ts +15 -0
- package/dist/types/src/types/fileManager.d.ts.map +1 -0
- package/dist/types/src/types/model.d.ts +6 -5
- package/dist/types/src/types/model.d.ts.map +1 -1
- package/package.json +5 -3
- package/dist/FileManager-CXk83EW5.js +0 -16
- package/dist/FileManager-CXk83EW5.js.map +0 -1
- package/dist/FileManager-DXi-X7r5.js +0 -28
- package/dist/FileManager-DXi-X7r5.js.map +0 -1
- package/dist/constants-BakHTrB9.js.map +0 -1
- package/dist/content-hash.js +0 -27
- package/dist/content-hash.js.map +0 -1
- package/dist/index-BWIn7kWN.js.map +0 -1
- package/dist/index-DcPIAiHD.js.map +0 -1
- package/dist/seed.schema.config-DGcg6TCS.js.map +0 -1
- package/dist/types/__tests__/__mocks__/browser/project/schema.d.ts +0 -52
- package/dist/types/__tests__/__mocks__/browser/project/schema.d.ts.map +0 -1
- package/dist/types/__tests__/__mocks__/node/schema.d.ts +0 -52
- package/dist/types/__tests__/__mocks__/node/schema.d.ts.map +0 -1
- package/dist/types/__tests__/browser/db/drizzle.test.d.ts +0 -2
- package/dist/types/__tests__/browser/db/drizzle.test.d.ts.map +0 -1
- package/dist/types/__tests__/browser/property/propertyMachine.test.d.ts +0 -2
- package/dist/types/__tests__/browser/property/propertyMachine.test.d.ts.map +0 -1
- package/dist/types/__tests__/browser/react/index.test.d.ts +0 -2
- package/dist/types/__tests__/browser/react/index.test.d.ts.map +0 -1
- package/dist/types/__tests__/dist/exports.test.d.ts +0 -2
- package/dist/types/__tests__/dist/exports.test.d.ts.map +0 -1
- package/dist/types/__tests__/fs/index.test.d.ts +0 -2
- package/dist/types/__tests__/fs/index.test.d.ts.map +0 -1
- package/dist/types/__tests__/index.test.d.ts +0 -2
- package/dist/types/__tests__/index.test.d.ts.map +0 -1
- package/dist/types/__tests__/node/Item/Item.test.d.ts +0 -2
- package/dist/types/__tests__/node/Item/Item.test.d.ts.map +0 -1
- package/dist/types/__tests__/node/setup.d.ts +0 -2
- package/dist/types/__tests__/node/setup.d.ts.map +0 -1
- package/dist/types/__tests__/scripts/bin.test.d.ts +0 -2
- package/dist/types/__tests__/scripts/bin.test.d.ts.map +0 -1
- package/dist/types/__tests__/setup.d.ts +0 -2
- package/dist/types/__tests__/setup.d.ts.map +0 -1
- package/dist/types/src/workers/content-hash.d.ts.map +0 -1
- /package/dist/types/src/{workers → browser/workers}/content-hash.d.ts +0 -0
|
@@ -145,7 +145,12 @@ const processRelationProperty = async (
|
|
|
145
145
|
seedSchemaUid,
|
|
146
146
|
versionUid,
|
|
147
147
|
listOfAttestations: [],
|
|
148
|
-
propertiesToUpdate: [
|
|
148
|
+
propertiesToUpdate: [
|
|
149
|
+
{
|
|
150
|
+
publishLocalId: relationProperty.localId,
|
|
151
|
+
propertySchemaUid: relationProperty.schemaUid,
|
|
152
|
+
},
|
|
153
|
+
],
|
|
149
154
|
}
|
|
150
155
|
|
|
151
156
|
const { itemBasicProperties, itemUploadProperties } =
|
|
@@ -315,20 +320,22 @@ export const getPublishPayload = async (
|
|
|
315
320
|
}
|
|
316
321
|
}
|
|
317
322
|
|
|
318
|
-
itemPublishData = await processBasicProperties(
|
|
319
|
-
itemBasicProperties,
|
|
320
|
-
itemPublishData,
|
|
321
|
-
)
|
|
322
|
-
|
|
323
|
-
multiPublishPayload.push(itemPublishData)
|
|
324
|
-
|
|
325
323
|
for (const relationProperty of itemRelationProperties) {
|
|
326
324
|
multiPublishPayload = await processRelationProperty(
|
|
327
325
|
relationProperty,
|
|
328
326
|
multiPublishPayload,
|
|
329
327
|
uploadedTransactions,
|
|
330
328
|
)
|
|
329
|
+
itemBasicProperties.push(relationProperty)
|
|
331
330
|
}
|
|
331
|
+
|
|
332
|
+
itemPublishData = await processBasicProperties(
|
|
333
|
+
itemBasicProperties,
|
|
334
|
+
itemPublishData,
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
multiPublishPayload.push(itemPublishData)
|
|
338
|
+
|
|
332
339
|
|
|
333
340
|
for (const listProperty of itemListProperties) {
|
|
334
341
|
multiPublishPayload = await processListProperty(
|
package/dist/src/helpers.ts
CHANGED
|
@@ -80,22 +80,8 @@ export const downloadFile = async (url: string, localFilePath: string) => {
|
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
// if (filename === '_journal.json') {
|
|
84
|
-
// const exists = await fs.promises.exists(localFilePath)
|
|
85
|
-
// if (exists) {
|
|
86
|
-
// await fs.promises.rm(localFilePath)
|
|
87
|
-
// }
|
|
88
|
-
// await fs.promises.writeFile(localFilePath, fileData)
|
|
89
|
-
// }
|
|
90
|
-
//
|
|
91
|
-
// if (filename !== '_journal.json') {
|
|
92
|
-
// await fs.promises.writeFile(localFilePath, fileData)
|
|
93
|
-
// }
|
|
94
83
|
await fs.promises.writeFile(localFilePath, fileData)
|
|
95
84
|
} catch (error) {
|
|
96
|
-
if (JSON.stringify(error).includes('File exists')) {
|
|
97
|
-
const fileData = await fs.promises.readFile(localFilePath, 'utf-8')
|
|
98
|
-
}
|
|
99
85
|
logger(`[Error] Failed to download file from ${url}:`, error)
|
|
100
86
|
}
|
|
101
87
|
|
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
|
|
3
|
+
type BrowserImageResizerConfigBase = {
|
|
4
|
+
/**
|
|
5
|
+
* Algorithm used for downscaling
|
|
6
|
+
*
|
|
7
|
+
* * `null`: Just resize with `drawImage()`. The best quality and fastest.
|
|
8
|
+
* * `bilinear`: Better quality, slower. Comes from upstream (ericnogralesbrowser-image-resizer).
|
|
9
|
+
* * `hermite`: Worse quality, faster. Comes from [viliusle/Hermite-resize](https://github.com/viliusle/Hermite-resize). Will dispatch workers for better performance.
|
|
10
|
+
* * `hermite_single`: Worse quality, faster. Single-threaded.
|
|
11
|
+
*
|
|
12
|
+
* default: null
|
|
13
|
+
*/
|
|
14
|
+
algorithm: 'bilinear' | 'hermite' | 'hermite_single' | 'null' | null;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Whether to process downscaling by `drawImage(source, 0, 0, source.width / 2, source.height / 2)`
|
|
18
|
+
* until the size is smaller than twice the target size.
|
|
19
|
+
*
|
|
20
|
+
* There seems to be no situation where it is necessary to change to false.
|
|
21
|
+
*
|
|
22
|
+
* default: true
|
|
23
|
+
*/
|
|
24
|
+
processByHalf: boolean;
|
|
25
|
+
|
|
26
|
+
maxWidth: number;
|
|
27
|
+
maxHeight: number;
|
|
28
|
+
maxSize?: number; // ???
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Scale ratio. Strictly limited to maxWidth.
|
|
32
|
+
*/
|
|
33
|
+
scaleRatio?: number;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Output logs to console
|
|
37
|
+
*/
|
|
38
|
+
debug: boolean;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
type BrowserImageResizerConfigWithConvertedOutput = BrowserImageResizerConfigBase & {
|
|
43
|
+
quality: number;
|
|
44
|
+
mimeType: string;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
type BrowserImageResizerConfigWithOffscreenCanvasOutput = BrowserImageResizerConfigBase & {
|
|
48
|
+
mimeType: null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
type BrowserImageResizerConfig = BrowserImageResizerConfigWithConvertedOutput | BrowserImageResizerConfigWithOffscreenCanvasOutput;
|
|
52
|
+
|
|
53
|
+
type WorkerSouceData = {
|
|
54
|
+
source: ImageData;
|
|
55
|
+
startY: number;
|
|
56
|
+
height: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export default `(
|
|
60
|
+
${
|
|
61
|
+
function () {
|
|
62
|
+
|
|
63
|
+
async function listFilesInDirectory(directoryHandle: FileSystemDirectoryHandle) {
|
|
64
|
+
const entries: { name: string; kind: FileSystemHandleKind }[] = [];
|
|
65
|
+
|
|
66
|
+
for await (const [name, handle] of directoryHandle.entries()) {
|
|
67
|
+
entries.push({
|
|
68
|
+
name,
|
|
69
|
+
kind: handle.kind,
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return entries;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const getFileHandle = async (path: string, rootHandle: FileSystemDirectoryHandle | null = null): Promise<FileSystemFileHandle> => {
|
|
77
|
+
// Split the path into segments
|
|
78
|
+
const segments = path.split('/').filter(Boolean);
|
|
79
|
+
|
|
80
|
+
// Start from the root directory if not provided
|
|
81
|
+
if (!rootHandle) {
|
|
82
|
+
rootHandle = await navigator.storage.getDirectory();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
let currentHandle = rootHandle;
|
|
86
|
+
|
|
87
|
+
// Traverse the path segments
|
|
88
|
+
for (let i = 0; i < segments.length; i++) {
|
|
89
|
+
const segment = segments[i];
|
|
90
|
+
const isLastSegment = i === segments.length - 1;
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
|
|
94
|
+
for await (const [name, handle] of currentHandle.entries()) {
|
|
95
|
+
if (name !== segment) {
|
|
96
|
+
continue
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (isLastSegment) {
|
|
100
|
+
if (handle.kind === 'file') {
|
|
101
|
+
return handle as FileSystemFileHandle; // Return the file handle if found
|
|
102
|
+
} else {
|
|
103
|
+
throw new Error(`Path '${path}' refers to a directory, not a file.`);
|
|
104
|
+
}
|
|
105
|
+
} else if (handle.kind === 'directory') {
|
|
106
|
+
currentHandle = handle as FileSystemDirectoryHandle; // Traverse into the directory
|
|
107
|
+
} else {
|
|
108
|
+
throw new Error(`Invalid path segment '${segment}'`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
} catch (err) {
|
|
112
|
+
if (err instanceof Error && err.name === 'NotFoundError') {
|
|
113
|
+
throw new Error(`Path '${path}' does not exist.`);
|
|
114
|
+
} else {
|
|
115
|
+
throw err;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
throw new Error(`Path '${path}' could not be resolved.`);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async function getFileFromOPFS(path: string): Promise<File> {
|
|
124
|
+
|
|
125
|
+
const fileHandleAsync = await getFileHandle(path);
|
|
126
|
+
const file = await fileHandleAsync.getFile();
|
|
127
|
+
return file;
|
|
128
|
+
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const DEFAULT_CONFIG = {
|
|
132
|
+
argorithm: 'null',
|
|
133
|
+
processByHalf: true,
|
|
134
|
+
quality: 0.5,
|
|
135
|
+
maxWidth: 800,
|
|
136
|
+
maxHeight: 600,
|
|
137
|
+
debug: false,
|
|
138
|
+
mimeType: 'image/jpeg',
|
|
139
|
+
} as const;
|
|
140
|
+
|
|
141
|
+
function isIos() {
|
|
142
|
+
if (typeof navigator === 'undefined') return false;
|
|
143
|
+
if (!navigator.userAgent) return false;
|
|
144
|
+
return /iPad|iPhone|iPod/.test(navigator.userAgent);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const getTargetHeight = (srcHeight: number, scale: number, config: BrowserImageResizerConfig) => {
|
|
148
|
+
return Math.min(Math.floor(srcHeight * scale), config.maxHeight);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const findMaxWidth = (config: BrowserImageResizerConfig, canvas: { width: number; height: number }) => {
|
|
152
|
+
//Let's find the max available width for scaled image
|
|
153
|
+
const ratio = canvas.width / canvas.height;
|
|
154
|
+
let mWidth = Math.min(
|
|
155
|
+
canvas.width,
|
|
156
|
+
config.maxWidth,
|
|
157
|
+
ratio * config.maxHeight
|
|
158
|
+
);
|
|
159
|
+
if (
|
|
160
|
+
config.maxSize &&
|
|
161
|
+
config.maxSize > 0 &&
|
|
162
|
+
config.maxSize < (canvas.width * canvas.height) / 1000
|
|
163
|
+
)
|
|
164
|
+
mWidth = Math.min(
|
|
165
|
+
mWidth,
|
|
166
|
+
Math.floor((config.maxSize * 1000) / canvas.height)
|
|
167
|
+
);
|
|
168
|
+
if (!!config.scaleRatio)
|
|
169
|
+
mWidth = Math.min(mWidth, Math.floor(config.scaleRatio * canvas.width));
|
|
170
|
+
|
|
171
|
+
const rHeight = getTargetHeight(canvas.height, mWidth / canvas.width, config);
|
|
172
|
+
|
|
173
|
+
// console.log(
|
|
174
|
+
// 'browser-image-resizer: original image size = ' +
|
|
175
|
+
// canvas.width +
|
|
176
|
+
// ' px (width) X ' +
|
|
177
|
+
// canvas.height +
|
|
178
|
+
// ' px (height)'
|
|
179
|
+
// );
|
|
180
|
+
// console.log(
|
|
181
|
+
// 'browser-image-resizer: scaled image size = ' +
|
|
182
|
+
// mWidth +
|
|
183
|
+
// ' px (width) X ' +
|
|
184
|
+
// rHeight +
|
|
185
|
+
// ' px (height)'
|
|
186
|
+
// );
|
|
187
|
+
if (mWidth <= 0) {
|
|
188
|
+
mWidth = 1;
|
|
189
|
+
console.warn("browser-image-resizer: image size is too small");
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (isIos() && mWidth * rHeight > 167777216) {
|
|
193
|
+
console.error("browser-image-resizer: image size is too large for iOS WebKit.", mWidth, rHeight);
|
|
194
|
+
throw new Error("browser-image-resizer: image size is too large for iOS WebKit.");
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return mWidth;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Hermite resize, multicore version - fast image resize/resample using Hermite filter.
|
|
202
|
+
*/
|
|
203
|
+
const resample = (srcCanvas: OffscreenCanvas, destCanvas: OffscreenCanvas, config: { debug?: boolean }) => {
|
|
204
|
+
return new Promise<void>((resolve, reject) => {
|
|
205
|
+
|
|
206
|
+
const ratio_h = srcCanvas.height / destCanvas.height;
|
|
207
|
+
const cores = Math.min(navigator.hardwareConcurrency || 4, 4)
|
|
208
|
+
|
|
209
|
+
//prepare source and target data for workers
|
|
210
|
+
const ctx = srcCanvas.getContext('2d');
|
|
211
|
+
if (!ctx) return reject('Canvas is empty (resample)');
|
|
212
|
+
|
|
213
|
+
const data_part: WorkerSouceData[] = [];
|
|
214
|
+
const block_height = Math.ceil(srcCanvas.height / cores / 2) * 2;
|
|
215
|
+
let end_y = -1;
|
|
216
|
+
for (let c = 0; c < cores; c++) {
|
|
217
|
+
//source
|
|
218
|
+
const offset_y = end_y + 1;
|
|
219
|
+
if (offset_y >= srcCanvas.height) {
|
|
220
|
+
//size too small, nothing left for this core
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
end_y = Math.min(offset_y + block_height - 1, srcCanvas.height - 1);
|
|
225
|
+
|
|
226
|
+
const current_block_height = Math.min(block_height, srcCanvas.height - offset_y);
|
|
227
|
+
|
|
228
|
+
console.log('browser-image-resizer: source split: ', '#' + c, offset_y, end_y, 'height: ' + current_block_height);
|
|
229
|
+
|
|
230
|
+
data_part.push({
|
|
231
|
+
source: ctx.getImageData(0, offset_y, srcCanvas.width, block_height),
|
|
232
|
+
startY: Math.ceil(offset_y / ratio_h),
|
|
233
|
+
height: current_block_height
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
//start
|
|
238
|
+
const destCtx = destCanvas.getContext('2d');
|
|
239
|
+
if (!destCtx) return reject('Canvas is empty (resample dest)');
|
|
240
|
+
let workers_in_use = data_part.length;
|
|
241
|
+
for (let c = 0; c < data_part.length; c++) {
|
|
242
|
+
|
|
243
|
+
//draw
|
|
244
|
+
const height_part = Math.ceil(data_part[c].height / ratio_h);
|
|
245
|
+
const target = destCtx.createImageData(destCanvas.width, height_part);
|
|
246
|
+
// target.data.set(event.data.target);
|
|
247
|
+
destCtx.putImageData(target, 0, data_part[c].startY);
|
|
248
|
+
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Hermite resize - fast image resize/resample using Hermite filter. 1 cpu version!
|
|
255
|
+
*/
|
|
256
|
+
const resampleSingle = (srcCanvasData: ImageData, destCanvasData: ImageData,) => {
|
|
257
|
+
const ratio_w = srcCanvasData.width / destCanvasData.width;
|
|
258
|
+
const ratio_h = srcCanvasData.height / destCanvasData.height;
|
|
259
|
+
const ratio_w_half = Math.ceil(ratio_w / 2);
|
|
260
|
+
const ratio_h_half = Math.ceil(ratio_h / 2);
|
|
261
|
+
|
|
262
|
+
const data = srcCanvasData.data;
|
|
263
|
+
const data2 = destCanvasData.data;
|
|
264
|
+
|
|
265
|
+
for (let j = 0; j < destCanvasData.height; j++) {
|
|
266
|
+
for (let i = 0; i < destCanvasData.width; i++) {
|
|
267
|
+
const x2 = (i + j * destCanvasData.width) * 4;
|
|
268
|
+
let weight = 0;
|
|
269
|
+
let weights = 0;
|
|
270
|
+
let weights_alpha = 0;
|
|
271
|
+
let gx_r = 0;
|
|
272
|
+
let gx_g = 0;
|
|
273
|
+
let gx_b = 0;
|
|
274
|
+
let gx_a = 0;
|
|
275
|
+
const center_y = j * ratio_h;
|
|
276
|
+
|
|
277
|
+
const xx_start = Math.floor(i * ratio_w);
|
|
278
|
+
const xx_stop = Math.min(Math.ceil((i + 1) * ratio_w), srcCanvasData.width);
|
|
279
|
+
const yy_start = Math.floor(j * ratio_h);
|
|
280
|
+
const yy_stop = Math.min(Math.ceil((j + 1) * ratio_h), srcCanvasData.height);
|
|
281
|
+
|
|
282
|
+
for (let yy = yy_start; yy < yy_stop; yy++) {
|
|
283
|
+
let dy = Math.abs(center_y - yy) / ratio_h_half;
|
|
284
|
+
let center_x = i * ratio_w;
|
|
285
|
+
let w0 = dy * dy; //pre-calc part of w
|
|
286
|
+
for (let xx = xx_start; xx < xx_stop; xx++) {
|
|
287
|
+
let dx = Math.abs(center_x - xx) / ratio_w_half;
|
|
288
|
+
let w = Math.sqrt(w0 + dx * dx);
|
|
289
|
+
if (w >= 1) {
|
|
290
|
+
//pixel too far
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
//hermite filter
|
|
294
|
+
weight = 2 * w * w * w - 3 * w * w + 1;
|
|
295
|
+
let pos_x = 4 * (xx + yy * srcCanvasData.width);
|
|
296
|
+
//alpha
|
|
297
|
+
gx_a += weight * data[pos_x + 3];
|
|
298
|
+
weights_alpha += weight;
|
|
299
|
+
//colors
|
|
300
|
+
if (data[pos_x + 3] < 255)
|
|
301
|
+
weight = weight * data[pos_x + 3] / 250;
|
|
302
|
+
gx_r += weight * data[pos_x];
|
|
303
|
+
gx_g += weight * data[pos_x + 1];
|
|
304
|
+
gx_b += weight * data[pos_x + 2];
|
|
305
|
+
weights += weight;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
data2[x2] = gx_r / weights;
|
|
309
|
+
data2[x2 + 1] = gx_g / weights;
|
|
310
|
+
data2[x2 + 2] = gx_b / weights;
|
|
311
|
+
data2[x2 + 3] = gx_a / weights_alpha;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Hermite resize. Detect cpu count and use best option for user.
|
|
318
|
+
*/
|
|
319
|
+
const resampleAuto = (srcCanvas: OffscreenCanvas, destCanvas: OffscreenCanvas, config: { debug?: boolean, argorithm?: string }) => {
|
|
320
|
+
if (!!globalThis.Worker && navigator.hardwareConcurrency > 1 && config?.argorithm !== 'hermite_single') {
|
|
321
|
+
//workers supported and we have at least 2 cpu cores - using multithreading
|
|
322
|
+
return resample(srcCanvas, destCanvas, config);
|
|
323
|
+
} else {
|
|
324
|
+
//1 cpu version
|
|
325
|
+
const { srcImgData, destImgData } = getImageData(srcCanvas, destCanvas);
|
|
326
|
+
resampleSingle(srcImgData, destImgData, config);
|
|
327
|
+
destCanvas.getContext('2d')!.putImageData(destImgData, 0, 0);
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
async function scaleCanvasWithAlgorithm(canvas: OffscreenCanvas, config: BrowserImageResizerConfig & { outputWidth: number }) {
|
|
334
|
+
const scale = config.outputWidth / canvas.width;
|
|
335
|
+
|
|
336
|
+
const scaled = new OffscreenCanvas(Math.floor(config.outputWidth), getTargetHeight(canvas.height, scale, config));
|
|
337
|
+
|
|
338
|
+
switch (config.algorithm) {
|
|
339
|
+
case 'hermite': {
|
|
340
|
+
await resampleAuto(canvas, scaled, config as BrowserImageResizerConfig & { algorithm: 'hermite' | 'hermite_single' });
|
|
341
|
+
break;
|
|
342
|
+
} case 'hermite_single': {
|
|
343
|
+
const { srcImgData, destImgData } = getImageData(canvas, scaled);
|
|
344
|
+
resampleSingle(srcImgData, destImgData,);
|
|
345
|
+
scaled?.getContext('2d')?.putImageData(destImgData, 0, 0);
|
|
346
|
+
break;
|
|
347
|
+
} case 'bilinear': {
|
|
348
|
+
// const { srcImgData, destImgData } = getImageData(canvas, scaled);
|
|
349
|
+
// bilinear(srcImgData, destImgData, scale);
|
|
350
|
+
// scaled?.getContext('2d')?.putImageData(destImgData, 0, 0);
|
|
351
|
+
break;
|
|
352
|
+
} default: {
|
|
353
|
+
scaled.getContext('2d')?.drawImage(canvas, 0, 0, scaled.width, scaled.height);
|
|
354
|
+
break;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
return scaled;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
const getHalfScaleCanvas = (src: OffscreenCanvas | HTMLCanvasElement) => {
|
|
362
|
+
const half = new OffscreenCanvas(src.width / 2, src.height / 2);
|
|
363
|
+
|
|
364
|
+
half
|
|
365
|
+
?.getContext('2d')
|
|
366
|
+
?.drawImage(src, 0, 0, half.width, half.height);
|
|
367
|
+
|
|
368
|
+
return half;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
const getImageData = (canvas: OffscreenCanvas, scaled: OffscreenCanvas) => {
|
|
372
|
+
const srcImgData = canvas
|
|
373
|
+
?.getContext('2d')
|
|
374
|
+
?.getImageData(0, 0, canvas.width, canvas.height);
|
|
375
|
+
const destImgData = scaled
|
|
376
|
+
?.getContext('2d')
|
|
377
|
+
?.createImageData(scaled.width, scaled.height);
|
|
378
|
+
|
|
379
|
+
if (!srcImgData || !destImgData) throw Error('Canvas is empty (scaleCanvasWithAlgorithm). You should run this script after the document is ready.');
|
|
380
|
+
|
|
381
|
+
return { srcImgData, destImgData };
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
async function saveBlobToOPFS(filePath: string, blob: Blob): Promise<void> {
|
|
385
|
+
// Access the OPFS root directory
|
|
386
|
+
const rootHandle = await navigator.storage.getDirectory();
|
|
387
|
+
|
|
388
|
+
// Split the filePath into directory segments and file name
|
|
389
|
+
const segments = filePath.split('/').filter(Boolean);
|
|
390
|
+
const fileName = segments.pop(); // Extract the file name
|
|
391
|
+
if (!fileName) {
|
|
392
|
+
throw new Error('Invalid file path: No file name provided.');
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// Traverse or create directories as needed
|
|
396
|
+
let currentDirHandle = rootHandle;
|
|
397
|
+
for (const segment of segments) {
|
|
398
|
+
currentDirHandle = await currentDirHandle.getDirectoryHandle(segment, { create: true });
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// Create or open the file in OPFS
|
|
402
|
+
const fileHandle = await currentDirHandle.getFileHandle(fileName, { create: true });
|
|
403
|
+
|
|
404
|
+
// Write the Blob to the file
|
|
405
|
+
const writableStream = await fileHandle.createWritable();
|
|
406
|
+
await writableStream.write(blob);
|
|
407
|
+
await writableStream.close();
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
const imageResize = async (filePath: string, width: number, height: number) => {
|
|
412
|
+
|
|
413
|
+
console.log({filePath, width, height})
|
|
414
|
+
|
|
415
|
+
const config = {
|
|
416
|
+
...DEFAULT_CONFIG,
|
|
417
|
+
algorithm: 'hermite_single',
|
|
418
|
+
mimeType: 'image/webp',
|
|
419
|
+
maxWidth: width,
|
|
420
|
+
maxHeight: height,
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
const rootHandle = await navigator.storage.getDirectory();
|
|
424
|
+
|
|
425
|
+
// List files in the root directory
|
|
426
|
+
const files = await listFilesInDirectory(rootHandle);
|
|
427
|
+
console.log({
|
|
428
|
+
message: 'listFilesInDirectory',
|
|
429
|
+
files
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
const file = await getFileFromOPFS(filePath);
|
|
433
|
+
|
|
434
|
+
const imageBitmap = await createImageBitmap(file);
|
|
435
|
+
|
|
436
|
+
let converting: OffscreenCanvas
|
|
437
|
+
|
|
438
|
+
if (isIos() && imageBitmap.width * imageBitmap.height > 16777216) {
|
|
439
|
+
const scale = Math.sqrt(16777216 / (imageBitmap.width * imageBitmap.height));
|
|
440
|
+
console.log(`browser-image-resizer: scale: Image is too large in iOS WebKit`);
|
|
441
|
+
converting = new OffscreenCanvas(Math.floor(imageBitmap.width * scale), Math.floor(imageBitmap.height * scale));
|
|
442
|
+
converting.getContext('2d')?.drawImage(imageBitmap, 0, 0, converting.width, converting.height);
|
|
443
|
+
} else {
|
|
444
|
+
converting = new OffscreenCanvas(imageBitmap.width, imageBitmap.height);
|
|
445
|
+
converting.getContext('2d')?.drawImage(imageBitmap, 0, 0);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
if (!converting?.getContext('2d')) {
|
|
449
|
+
console.log('browser-image-resizer: Canvas Context is empty.')
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
const maxWidth = findMaxWidth(config, converting);
|
|
453
|
+
|
|
454
|
+
if (!maxWidth){
|
|
455
|
+
throw Error(`browser-image-resizer: maxWidth is ${maxWidth}!!`)
|
|
456
|
+
};
|
|
457
|
+
|
|
458
|
+
while (config.processByHalf && converting.width >= 2 * maxWidth) {
|
|
459
|
+
if (config.debug) console.log(`browser-image-resizer: scale: Scaling canvas by half from ${converting.width}`);
|
|
460
|
+
converting = getHalfScaleCanvas(converting);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
if (converting.width > maxWidth) {
|
|
464
|
+
if (config.debug) console.log(`browser-image-resizer: scale: Scaling canvas by ${config.argorithm} from ${converting.width} to ${maxWidth}`);
|
|
465
|
+
converting = await scaleCanvasWithAlgorithm(
|
|
466
|
+
converting,
|
|
467
|
+
Object.assign(config, { outputWidth: maxWidth }),
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
if (config.mimeType === null) {
|
|
472
|
+
return converting;
|
|
473
|
+
}
|
|
474
|
+
const resizedBlob = await converting.convertToBlob({ type: config.mimeType, quality: config.quality });
|
|
475
|
+
|
|
476
|
+
const pathSegments = filePath.split('/');
|
|
477
|
+
const fileName = pathSegments.pop();
|
|
478
|
+
if (!fileName) {
|
|
479
|
+
throw Error('Invalid file path: No file name provided.');
|
|
480
|
+
}
|
|
481
|
+
const newSegments = [
|
|
482
|
+
...pathSegments,
|
|
483
|
+
width,
|
|
484
|
+
]
|
|
485
|
+
const fileNameParts = fileName.split('.')
|
|
486
|
+
const newFileName = `${fileNameParts[0]}.webp`
|
|
487
|
+
const newDirPath = newSegments.join('/');
|
|
488
|
+
const newFilePath = `${newDirPath}/${newFileName}`;
|
|
489
|
+
|
|
490
|
+
// Save resized image to OPFS with new name
|
|
491
|
+
await saveBlobToOPFS(newFilePath, resizedBlob)
|
|
492
|
+
globalThis.postMessage({
|
|
493
|
+
done: true,
|
|
494
|
+
filePath: newFilePath,
|
|
495
|
+
})
|
|
496
|
+
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
onmessage = async (e) => {
|
|
500
|
+
console.log('[imageResize] onmessage', e.data)
|
|
501
|
+
const { filePath, width, height } = e.data
|
|
502
|
+
await imageResize(filePath, width, height)
|
|
503
|
+
console.log(`[imageResize] Done`, filePath)
|
|
504
|
+
}
|
|
505
|
+
}.toString()
|
|
506
|
+
}
|
|
507
|
+
)()`
|
package/dist/src/model.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { PropertyStates, PropertyValue } from './property'
|
|
2
|
-
import { Actor } from 'xstate'
|
|
2
|
+
import { Actor, AnyActorLogic } from 'xstate'
|
|
3
3
|
import { Static } from '@sinclair/typebox'
|
|
4
|
-
import { IModelClass,
|
|
4
|
+
import { IModelClass, TModelSchema } from '@/schema'
|
|
5
|
+
import { BaseItem } from '@/Item/BaseItem'
|
|
5
6
|
|
|
6
7
|
export type ModelDefinitions = {
|
|
7
8
|
[modelName: string]: ModelClassType
|
|
@@ -19,16 +20,16 @@ export type ModelClassType = {
|
|
|
19
20
|
originalConstructor: () => void
|
|
20
21
|
schema: ModelSchema
|
|
21
22
|
schemaUid?: string
|
|
22
|
-
create:
|
|
23
|
+
create: (values: ModelValues<any>) => Promise<BaseItem<any>>
|
|
23
24
|
}
|
|
24
25
|
|
|
25
|
-
export type ModelValues<T
|
|
26
|
+
export type ModelValues<T extends Record<string, any>> = BaseItem<any> & {
|
|
26
27
|
schema: ModelSchema
|
|
27
28
|
ModelClass?: ModelClassType
|
|
28
29
|
[key: string & keyof T]: PropertyValue
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
export type StatesMap<T> = Map<string, Actor<T>>
|
|
32
|
+
export type StatesMap<T> = Map<string, Actor<T extends AnyActorLogic ? T : never>>
|
|
32
33
|
|
|
33
34
|
// export type ModelSchema = {
|
|
34
35
|
// [key: string]: TObject
|
package/dist/src/saveImageSrc.ts
CHANGED
|
@@ -15,6 +15,7 @@ import { getSchemaUidForSchemaDefinition } from '@/stores/eas'
|
|
|
15
15
|
import { getSchemaUidForModel } from '@/db/read/getSchemaUidForModel'
|
|
16
16
|
import { BaseFileManager } from '@/helpers/FileManager/BaseFileManager'
|
|
17
17
|
import { eventEmitter } from '@/eventBus'
|
|
18
|
+
import { ImageSize } from '@/helpers/constants'
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
|
|
@@ -165,14 +166,23 @@ export const saveImageSrc = fromCallback<
|
|
|
165
166
|
}
|
|
166
167
|
}
|
|
167
168
|
|
|
169
|
+
|
|
170
|
+
await BaseFileManager.resizeImage({filePath, width: ImageSize.EXTRA_SMALL, height: ImageSize.EXTRA_SMALL})
|
|
171
|
+
await BaseFileManager.resizeImage({filePath, width: ImageSize.SMALL, height: ImageSize.SMALL})
|
|
172
|
+
await BaseFileManager.resizeImage({filePath, width: ImageSize.MEDIUM, height: ImageSize.MEDIUM})
|
|
173
|
+
await BaseFileManager.resizeImage({filePath, width: ImageSize.LARGE, height: ImageSize.LARGE})
|
|
174
|
+
await BaseFileManager.resizeImage({filePath, width: ImageSize.EXTRA_LARGE, height: ImageSize.EXTRA_LARGE})
|
|
175
|
+
|
|
168
176
|
const refResolvedDisplayValue = await BaseFileManager.getContentUrlFromPath(filePath)
|
|
169
177
|
|
|
170
178
|
if (!schemaUid) {
|
|
171
179
|
schemaUid = getSchemaUidForSchemaDefinition(propertyName)
|
|
172
180
|
}
|
|
173
181
|
|
|
182
|
+
let newLocalId
|
|
183
|
+
|
|
174
184
|
if (!localId) {
|
|
175
|
-
await createMetadata(
|
|
185
|
+
const result = await createMetadata(
|
|
176
186
|
{
|
|
177
187
|
propertyName,
|
|
178
188
|
propertyValue: newImageSeedLocalId,
|
|
@@ -192,6 +202,8 @@ export const saveImageSrc = fromCallback<
|
|
|
192
202
|
},
|
|
193
203
|
propertyRecordSchema,
|
|
194
204
|
)
|
|
205
|
+
|
|
206
|
+
newLocalId = result[0].localId
|
|
195
207
|
}
|
|
196
208
|
|
|
197
209
|
if (localId) {
|
|
@@ -215,6 +227,7 @@ export const saveImageSrc = fromCallback<
|
|
|
215
227
|
|
|
216
228
|
sendBack({
|
|
217
229
|
type: 'updateContext',
|
|
230
|
+
localId: newLocalId || localId,
|
|
218
231
|
propertyValue: newImageSeedLocalId,
|
|
219
232
|
refSeedType: 'image',
|
|
220
233
|
refSchemaUid: imageSchemaUid,
|
|
@@ -223,6 +236,7 @@ export const saveImageSrc = fromCallback<
|
|
|
223
236
|
refResolvedValue: fileName,
|
|
224
237
|
localStorageDir: '/images',
|
|
225
238
|
easDataType: 'bytes32',
|
|
239
|
+
schemaUid,
|
|
226
240
|
})
|
|
227
241
|
}
|
|
228
242
|
|