zone5 1.0.1 → 1.1.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.
@@ -6,7 +6,5 @@ export declare const ProcessorConfigSchema: z.ZodPrefault<z.ZodObject<{
6
6
  resize_gamma: z.ZodDefault<z.ZodNumber>;
7
7
  variants: z.ZodDefault<z.ZodArray<z.ZodNumber>>;
8
8
  }, z.core.$strip>>;
9
- export type ProcessorConfig = z.infer<typeof ProcessorConfigSchema> & {
10
- clear?: boolean;
11
- forceOverwrite?: boolean;
12
- };
9
+ export type ProcessorConfig = z.infer<typeof ProcessorConfigSchema>;
10
+ export declare const configHash: (config: ProcessorConfig) => string;
@@ -1,3 +1,4 @@
1
+ import { createHash } from 'crypto';
1
2
  import sharp from 'sharp';
2
3
  import z from 'zod';
3
4
  export const ProcessorConfigSchema = z
@@ -7,3 +8,9 @@ export const ProcessorConfigSchema = z
7
8
  variants: z.array(z.number().int().min(1)).default([640, 768, 1280, 1920, 2560]),
8
9
  })
9
10
  .prefault({});
11
+ export const configHash = (config) => {
12
+ // Generate SHAKE256 hash with length 4 for config
13
+ const hash = createHash('shake256', { outputLength: 4 });
14
+ hash.update(JSON.stringify(config));
15
+ return hash.digest('hex');
16
+ };
@@ -1,6 +1,6 @@
1
1
  import type { BaseConfigType } from '../config.js';
2
2
  import { type DominantColor } from './color.js';
3
- import type { ProcessorConfig } from './config.js';
3
+ import { type ProcessorConfig } from './config.js';
4
4
  import type { ExifItem } from './exif/exif.js';
5
5
  import type { GeojsonPoint } from './exif/types.js';
6
6
  export interface ItemFeature {
@@ -4,6 +4,7 @@ import { join, parse, relative } from 'path';
4
4
  import sharp from 'sharp';
5
5
  import { generateBlurhash } from './blurhash.js';
6
6
  import { getDominantColors } from './color.js';
7
+ import { configHash } from './config.js';
7
8
  import exifFromFilePath from './exif/index.js';
8
9
  import { fileExists, sourceFileHash } from './file.js';
9
10
  import { generateImageVariants } from './variants.js';
@@ -11,14 +12,18 @@ const tracer = trace.getTracer('zone5-processor');
11
12
  const processor = async (options) => {
12
13
  return tracer.startActiveSpan('zone5.processor', async (span) => {
13
14
  try {
14
- const { base, sourceFile, clear = false, forceOverwrite = false } = options;
15
+ const { base, processor: processorConfig, sourceFile, clear = false, forceOverwrite = false } = options;
15
16
  const { name: fileBasename } = parse(sourceFile);
16
17
  const sourceHash = sourceFileHash(base.root, sourceFile);
17
- const featureFile = join(base.cache, `${fileBasename}-${sourceHash}`, 'index.json');
18
+ const procConfigHash = configHash(processorConfig);
19
+ const cacheDir = join(base.cache, `${procConfigHash}-${fileBasename}-${sourceHash}`);
20
+ const featureFile = join(cacheDir, 'index.json');
18
21
  span.setAttributes({
19
22
  'zone5.sourceFile': sourceFile,
20
23
  'zone5.fileBasename': fileBasename,
21
24
  'zone5.sourceHash': sourceHash,
25
+ 'zone5.configHash': procConfigHash,
26
+ 'zone5.cacheDir': cacheDir,
22
27
  'zone5.clear': clear,
23
28
  'zone5.forceOverwrite': forceOverwrite,
24
29
  });
@@ -27,7 +32,7 @@ const processor = async (options) => {
27
32
  exifFromFilePath(sourceFile),
28
33
  generateBlurhash(sourceFile),
29
34
  getDominantColors(sourceFile),
30
- generateImageVariants(options),
35
+ generateImageVariants({ sourceFile, processor: processorConfig, cacheDir, clear, forceOverwrite }),
31
36
  sharp(sourceFile).metadata(),
32
37
  ]);
33
38
  const feature = {
@@ -1,13 +1,12 @@
1
- import type { BaseConfigType } from '../config.js';
2
1
  import type { ProcessorConfig } from './config.js';
3
2
  export interface GeneratedVariant {
4
3
  width: number;
5
4
  path: string;
6
5
  }
7
6
  export declare function generateImageVariants(options: {
8
- base: BaseConfigType;
9
7
  processor: ProcessorConfig;
10
8
  sourceFile: string;
9
+ cacheDir: string;
11
10
  clear?: boolean;
12
11
  forceOverwrite?: boolean;
13
12
  }): Promise<GeneratedVariant[]>;
@@ -2,7 +2,7 @@ import { SpanStatusCode, trace } from '@opentelemetry/api';
2
2
  import { rm } from 'fs/promises';
3
3
  import { join, parse } from 'path';
4
4
  import sharp from 'sharp';
5
- import { ensureDirectoryExists, fileExists, sourceFileHash } from './file.js';
5
+ import { ensureDirectoryExists, fileExists } from './file.js';
6
6
  const tracer = trace.getTracer('zone5-processor-variants');
7
7
  const addDebugText = async (img, width, height) => {
8
8
  const svg = `<svg height="100" width="300">
@@ -13,7 +13,7 @@ const addDebugText = async (img, width, height) => {
13
13
  export async function generateImageVariants(options) {
14
14
  return tracer.startActiveSpan('zone5.generateImageVariants', async (span) => {
15
15
  try {
16
- const { base, processor, sourceFile, clear = false, forceOverwrite = false } = options;
16
+ const { processor, sourceFile, cacheDir, clear = false, forceOverwrite = false } = options;
17
17
  // Parse file path components
18
18
  const { name: fileBasename, ext: fileExtension } = parse(sourceFile);
19
19
  // Get source image metadata to check dimensions
@@ -25,22 +25,21 @@ export async function generateImageVariants(options) {
25
25
  'zone5.sourceFile': sourceFile,
26
26
  'zone5.sourceWidth': sourceWidth,
27
27
  'zone5.validWidthsCount': validWidths.length,
28
+ 'zone5.cacheDir': cacheDir,
28
29
  'zone5.clear': clear,
29
30
  'zone5.forceOverwrite': forceOverwrite,
30
31
  });
31
- // Create cache subdirectory
32
- const sourceHash = sourceFileHash(base.root, sourceFile);
33
- const cacheSubDir = join(base.cache, `${fileBasename}-${sourceHash}`);
32
+ // Prepare cache directory
34
33
  if (clear) {
35
- await rm(cacheSubDir, { recursive: true, force: true });
34
+ await rm(cacheDir, { recursive: true, force: true });
36
35
  }
37
- await ensureDirectoryExists(cacheSubDir);
36
+ await ensureDirectoryExists(cacheDir);
38
37
  // Generate variants for each valid width
39
38
  const variants = [];
40
39
  let generatedCount = 0;
41
40
  for (const width of validWidths) {
42
41
  const variantFilename = `${fileBasename}-${width}${fileExtension}`;
43
- const variantPath = join(cacheSubDir, variantFilename);
42
+ const variantPath = join(cacheDir, variantFilename);
44
43
  // Check if variant already exists and should be overwritten
45
44
  const variantExists = await fileExists(variantPath);
46
45
  if (!variantExists || forceOverwrite) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zone5",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "repository": {
5
5
  "url": "https://github.com/cwygoda/zone5"
6
6
  },