Image Service
This module provides high-level functions to store, retrieve, update, and delete encrypted images on the backend.
It operates on binary buffers, handles AES-GCM encryption internally, and manages image metadata via SQLite.
All functions are exported from the pixstore/backend entrypoint:
import {
getImageRecord,
saveImage,
saveImageFromFile,
updateImage,
updateImageFromFile,
deleteImage,
imageExists,
} from 'pixstore/backend'
Each function is described in detail below.
getImageRecord
Retrieves the metadata for an image previously saved to the backend.
Returns an ImageRecord object containing the image's id, token, and imageFormat, or null if the image does not exist in the database.
Description
export const getImageRecord = (id: string): ImageRecord | null
Parameters
| Name | Type | Description |
|---|---|---|
id | string | The unique ID of the image. |
Example
const imageRecord = getImageRecord(imageId)
if (!imageRecord) {
// Image not found
// For error details, use:
console.error(getLastPixstoreError())
}
// Send imageRecord to the frontend
const player: BasketballPlayer = {
...playerRecord,
imageRecord,
}
// Send imageRecord to the frontend for direct Pixstore usage
res.json(player)
How it works?
It is intended for contributors or users who want to understand the inner workings of Pixstore. Typical users do not need to modify or interact with this code directly.
Also, this code was last verified with Pixstore v3.2.1 and may change in future versions. For the latest implementation, always check the official repository at github.com/sDenizOzturk/pixstore.
/**
* Returns the image record (id, token, meta, statelessProof) from the database.
* Adds a statelessProof to the DB record for use in fetch/endpoint calls.
* Returns null if the record is not found.
*/
export const getImageRecord = (id: string): ImageRecord | null => {
return handleErrorSync(() => {
// Read the database image record (contains id, token, and meta fields)
const dbImageRecord = readImageRecord(id)
// Convert DB record to frontend-compatible ImageRecord (adds statelessProof)
return convertImageRecord(dbImageRecord)
})
}
saveImage
Creates and saves a new image using an in-memory Buffer.
The image is encrypted using AES-GCM, written to disk, and registered in the metadata database.
This function generates a unique id for the image, optionally namespaced by a dir.
Description
export const saveImage = (
buffer: Buffer,
dir?: string
): Promise<ImageRecord | null>
Parameters
| Name | Type | Description |
|---|---|---|
buffer | Buffer | Raw binary data of the image. Will be encrypted before storage. |
dir | string? | Optional namespace or folder scope for the image ID. |
Example
const imageRecord = await saveImage(imageBuffer, 'players')
if (!imageRecord) {
// Image could not be saved
// For error details, use:
console.error(getLastPixstoreError())
}
// Send this to the frontend.
// The Pixstore frontend needs imageRecord to fetch and decrypt the actual image.
const player: BasketballPlayer = {
...playerRecord,
imageRecord,
}
res.json(player)
How it works?
It is intended for contributors or users who want to understand the inner workings of Pixstore. Typical users do not need to modify or interact with this code directly.
Also, this code was last verified with Pixstore v3.2.1 and may change in future versions. For the latest implementation, always check the official repository at github.com/sDenizOzturk/pixstore.
/**
* Saves an image buffer to disk and creates a corresponding database record.
* If writing to the database fails, the saved file is deleted to maintain consistency.
*/
export const saveImage = async (
buffer: Buffer,
dir?: string,
): Promise<ImageRecord | null> => {
return handleErrorAsync(async () => {
// Generate a unique ID for this image, optionally scoped by dir
const id = createUniqueId(dir)
// Write the encrypted image and metadata
return await writeImage(id, buffer)
})
}
/**
* Writes an image buffer to disk and updates or creates its database record.
* If writing to the database fails, the file is deleted to maintain consistency.
*/
const writeImage = async (id: string, buffer: Buffer): Promise<ImageRecord> => {
// Encrypt the buffer using AES-GCM and get encryption metadata (key, iv, tag)
const { encrypted, meta } = encryptImage(buffer)
// Save the encrypted image buffer to disk
await saveImageFile(id, encrypted)
try {
// Write image metadata (token, key, iv, tag) to the database and get the DB record
const dbImageRecord = writeImageRecord(id, meta)
// Convert the DB image record into a frontend-compatible ImageRecord (adds statelessProof)
const imageRecord = convertImageRecord(dbImageRecord)
// If conversion fails (should not happen), delete the image file and throw error
if (!imageRecord) {
deleteImageFile(id)
throw new PixstoreError('Failed to convert image record: result is null')
}
// Return the completed ImageRecord (for frontend use)
return imageRecord
} catch (err) {
// If writing metadata fails, delete the saved image to avoid inconsistency
deleteImageFile(id)
throw err
}
}
saveImageFromFile
Reads an image file from disk and saves it as a new encrypted image.
This is a convenience wrapper around saveImage(). It lets you work directly with file paths instead of manually reading buffers.
Description
export const saveImageFromFile = (
filePath: string,
dir?: string
): Promise<ImageRecord | null>
Parameters
| Name | Type | Description |
|---|---|---|
filePath | string | Path to the image file on disk |
dir | string? | Optional namespace or folder scope for the generated image ID |
Example
const imageRecord = await saveImageFromFile('./assets/logo.png', 'system')
if (!imageRecord) {
// Image could not be saved
// For error details, use:
console.error(getLastPixstoreError())
}
How it works?
It is intended for contributors or users who want to understand the inner workings of Pixstore. Typical users do not need to modify or interact with this code directly.
Also, this code was last verified with Pixstore v3.2.1 and may change in future versions. For the latest implementation, always check the official repository at github.com/sDenizOzturk/pixstore.
/**
* Reads an image file from disk and saves it as a new image
* This is a convenience wrapper around saveImage()
*/
export const saveImageFromFile = async (
filePath: string,
dir?: string,
): Promise<ImageRecord | null> => {
return handleErrorAsync(async () => {
// Read file content into a Buffer
const buffer = await diskToBuffer(filePath)
// Save buffer as encrypted image
return await saveImage(buffer, dir)
})
}
updateImage
Overwrites an existing image with new binary content and refreshes the corresponding metadata.
This function expects the image ID to already exist in the database. If not, returns null.
Description
export const updateImage = (
id: string,
buffer: Buffer,
): Promise<ImageRecord | null>
Parameters
| Name | Type | Description |
|---|---|---|
id | string | The ID of the image to update |
buffer | Buffer | New binary content to replace the existing image |
Example
const updatedImageRecord = await updateImage(playerId, newBuffer)
if (!updatedImageRecord) {
// Image not found
// For error details, use:
console.error(getLastPixstoreError())
}
How it works?
It is intended for contributors or users who want to understand the inner workings of Pixstore. Typical users do not need to modify or interact with this code directly.
Also, this code was last verified with Pixstore v3.2.1 and may change in future versions. For the latest implementation, always check the official repository at github.com/sDenizOzturk/pixstore.
/**
* Updates an existing image by overwriting the file and refreshing the database record
*/
export const updateImage = async (
id: string,
buffer: Buffer,
): Promise<ImageRecord | null> => {
return handleErrorAsync(async () => {
// Check if image exists in the database
if (!imageRecordExists(id)) {
throw new PixstoreError(`Image not found: ${id}`)
}
// Overwrite image and update its metadata
return await writeImage(id, buffer)
})
}
/**
* Writes an image buffer to disk and updates or creates its database record.
* If writing to the database fails, the file is deleted to maintain consistency.
*/
const writeImage = async (id: string, buffer: Buffer): Promise<ImageRecord> => {
// Encrypt the buffer using AES-GCM and get encryption metadata (key, iv, tag)
const { encrypted, meta } = encryptImage(buffer)
// Save the encrypted image buffer to disk
await saveImageFile(id, encrypted)
try {
// Write image metadata (token, key, iv, tag) to the database and get the DB record
const dbImageRecord = writeImageRecord(id, meta)
// Convert the DB image record into a frontend-compatible ImageRecord (adds statelessProof)
const imageRecord = convertImageRecord(dbImageRecord)
// If conversion fails (should not happen), delete the image file and throw error
if (!imageRecord) {
deleteImageFile(id)
throw new PixstoreError('Failed to convert image record: result is null')
}
// Return the completed ImageRecord (for frontend use)
return imageRecord
} catch (err) {
// If writing metadata fails, delete the saved image to avoid inconsistency
deleteImageFile(id)
throw err
}
}
updateImageFromFile
Updates an existing image by reading new binary content from a file and replacing both the file and its metadata.
This function requires the image id to already exist in the database.
It is a convenience wrapper around updateImage() and lets you work directly with file paths.
Description
export const updateImageFromFile = (
id: string,
filePath: string
): Promise<ImageRecord | null>
Parameters
| Name | Type | Description |
|---|---|---|
id | string | The ID of the image to update |
filePath | string | Path to the new image file on disk |
Example
const updatedImageRecord = await updateImageFromFile(
imageId,
'./images/new-logo.png',
)
if (!updatedImageRecord) {
// Image not found
// For error details, use:
console.error(getLastPixstoreError())
}
How it works?
It is intended for contributors or users who want to understand the inner workings of Pixstore. Typical users do not need to modify or interact with this code directly.
Also, this code was last verified with Pixstore v3.2.1 and may change in future versions. For the latest implementation, always check the official repository at github.com/sDenizOzturk/pixstore.
/**
* Reads a buffer from a file and updates the image with the given ID
* Optionally, a directory prefix can be specified
*/
export const updateImageFromFile = async (
id: string,
filePath: string,
): Promise<ImageRecord | null> => {
return handleErrorAsync(async () => {
// Read file content into a Buffer
const buffer = await diskToBuffer(filePath)
// Overwrite existing image with new buffer
return await updateImage(id, buffer)
})
}
deleteImage
Deletes both the encrypted image file and its metadata record for the specified image id.
Returns true if at least one of them was successfully deleted.
Description
export const deleteImage = (
id: string
): Promise<boolean | null>
Parameters
| Name | Type | Description |
|---|---|---|
id | string | The unique ID of the image. |
Example
const result = await deleteImage(imageId)
if (result === null) {
// There was an error during deletion (use getLastPixstoreError() for details)
console.error(getLastPixstoreError())
} else if (result) {
console.log('Image deleted.')
} else {
console.log('Image not found.')
}
How it works?
It is intended for contributors or users who want to understand the inner workings of Pixstore. Typical users do not need to modify or interact with this code directly.
Also, this code was last verified with Pixstore v3.2.1 and may change in future versions. For the latest implementation, always check the official repository at github.com/sDenizOzturk/pixstore.
/**
* Deletes the image file and corresponding database record for the given ID
* Returns true if at least one of them was deleted
*/
export const deleteImage = (id: string): Promise<boolean | null> => {
return handleErrorAsync(async () => {
let deleted = false
// Delete the image file if it exists
if (await imageFileExists(id)) {
await deleteImageFile(id)
deleted = true
}
// Delete the metadata record if it exists
if (imageRecordExists(id)) {
deleteImageRecord(id)
deleted = true
}
return deleted
})
}
imageExists
Checks whether the image with the given id exists on disk or in the metadata database.
This can be used to verify if an image is still present in storage. Useful for debugging, logging, or conditional logic.
Description
export const imageExists = (
id: string
): Promise<boolean | null>
Parameters
| Name | Type | Description |
|---|---|---|
id | string | The unique ID of the image. |
Example
const exists = await imageExists(imageId)
if (exists === null) {
// There was an error during existence check (see last error for details)
console.error(getLastPixstoreError())
} else if (exists) {
console.log('Image is available')
} else {
console.log('Image not found')
}
How it works?
It is intended for contributors or users who want to understand the inner workings of Pixstore. Typical users do not need to modify or interact with this code directly.
Also, this code was last verified with Pixstore v3.2.1 and may change in future versions. For the latest implementation, always check the official repository at github.com/sDenizOzturk/pixstore.
/**
* Checks whether the image exists either on disk or in the database
*/
export const imageExists = async (id: string): Promise<boolean | null> => {
return handleErrorAsync(async () => {
// Returns true if image file or metadata record exists
return (await imageFileExists(id)) || imageRecordExists(id)
})
}
📄 Source: src/backend/image-service.ts