@zodic/shared 0.0.116 → 0.0.118

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/app/api/index.ts CHANGED
@@ -16,9 +16,7 @@ import {
16
16
  HouseCuspsReport,
17
17
  LeonardoGenerateImageParams,
18
18
  LeonardoGenerateImageResponse,
19
- LeonardoGeneratePresignedUrlParams,
20
19
  LeonardoRequestBody,
21
- LeonardoUploadImageParams,
22
20
  NatalHouseCuspReport,
23
21
  TimezoneResponse,
24
22
  } from '../../types/scopes/legacy';
@@ -236,13 +234,24 @@ export const Api = (env: BackendBindings) => ({
236
234
  num_images: quantity,
237
235
  };
238
236
 
237
+ // ✅ Dynamically add `controlNets` based on available settings
239
238
  if (controlNets.length > 0) {
240
- body['controlnets'] = controlNets.map((net) => ({
241
- initImageId: net.initImageId,
242
- initImageType: net.initImageType,
243
- preprocessorId: net.preprocessorId,
244
- strengthType: net.strengthType,
245
- }));
239
+ // @ts-expect-error
240
+ body['controlnets'] = controlNets.map((net) => {
241
+ const baseNet = {
242
+ initImageId: net.initImageId,
243
+ initImageType: net.initImageType,
244
+ preprocessorId: net.preprocessorId,
245
+ };
246
+
247
+ if (net.preprocessorId === 100) {
248
+ return { ...baseNet, strengthType: net.strengthType };
249
+ } else if (net.preprocessorId === 19) {
250
+ return { ...baseNet, weight: net.weight };
251
+ }
252
+
253
+ return baseNet;
254
+ });
246
255
  }
247
256
 
248
257
  if (initImageId) {
@@ -259,123 +268,18 @@ export const Api = (env: BackendBindings) => ({
259
268
 
260
269
  if (!response.ok) {
261
270
  const error = await response.json();
262
- console.error('Error from Leonardo API:', error);
271
+ console.error('Error from Leonardo API:', error);
263
272
  throw new Error(`Leonardo API Error: ${response.status}`);
264
273
  }
265
274
 
266
275
  const data = (await response.json()) as LeonardoGenerateImageResponse;
267
276
  return data;
268
277
  } catch (err: any) {
269
- console.error('Error calling Leonardo API:', err.message);
278
+ console.error('Error calling Leonardo API:', err.message);
270
279
  throw err;
271
280
  }
272
281
  },
273
- generatePresignedUrl: async ({
274
- extension,
275
- }: LeonardoGeneratePresignedUrlParams): Promise<{
276
- url: string;
277
- fields: string;
278
- id: string;
279
- key: string;
280
- }> => {
281
- console.log('Generating presigned URL with extension:', extension);
282
-
283
- const endpoint = 'https://cloud.leonardo.ai/api/rest/v1/init-image';
284
- const headers = {
285
- Authorization: `Bearer ${env.LEONARDO_API_KEY}`,
286
- 'Content-Type': 'application/json',
287
- };
288
-
289
- if (!extension) {
290
- throw new Error('Invalid MIME type');
291
- }
292
-
293
- const body = JSON.stringify({
294
- extension,
295
- });
296
-
297
- try {
298
- const response = await fetch(endpoint, {
299
- method: 'POST',
300
- headers,
301
- body,
302
- });
303
-
304
- if (!response.ok) {
305
- const error = await response.text();
306
- console.error('Leonardo API error:', error);
307
- throw new Error(
308
- `Presigned URL generation failed: ${response.status}`
309
- );
310
- }
311
-
312
- const rawResponse = (await response.json()) as any;
313
- console.log('Presigned URL response:', rawResponse);
314
-
315
- if (
316
- !rawResponse.uploadInitImage ||
317
- !rawResponse.uploadInitImage.url ||
318
- !rawResponse.uploadInitImage.fields
319
- ) {
320
- throw new Error('Invalid presigned URL response');
321
- }
322
-
323
- return rawResponse.uploadInitImage;
324
- } catch (error: any) {
325
- console.error('Error generating presigned URL:', error.message);
326
- throw error;
327
- }
328
- },
329
- uploadImage: async ({
330
- presignedUrl,
331
- fields,
332
- file,
333
- }: LeonardoUploadImageParams) => {
334
- console.log('Starting image upload to:', presignedUrl);
335
-
336
- if (!(file instanceof Blob)) {
337
- throw new Error('Invalid file type for upload');
338
- }
339
-
340
- try {
341
- console.log('Parsing fields...');
342
- const parsedFields = JSON.parse(fields);
343
-
344
- if (!parsedFields || typeof parsedFields !== 'object') {
345
- throw new Error('Invalid fields format');
346
- }
347
-
348
- console.log('Parsed fields:', parsedFields);
349
-
350
- const formData = new FormData();
351
-
352
- Object.entries(parsedFields).forEach(([key, value]) => {
353
- formData.append(key, value as string);
354
- });
355
-
356
- formData.append('file', file);
357
-
358
- console.log('Uploading with FormData:', Array.from(formData.entries()));
359
-
360
- const response = await fetch(presignedUrl, {
361
- method: 'POST',
362
- body: formData,
363
- });
364
-
365
- if (!response.ok) {
366
- const errorDetails = await response.text();
367
- console.error('Upload failed:', errorDetails);
368
- throw new Error(`Image upload failed: ${response.status}`);
369
- }
370
-
371
- console.log('Image uploaded successfully');
372
- } catch (error: any) {
373
- console.error('Error during uploadImage:', error.message);
374
- throw error;
375
- }
376
- },
377
282
  },
378
-
379
283
  callImageDescriber: async (imageUrl: string): Promise<string> => {
380
284
  const mimeType = 'image/png';
381
285
  const endpoint =
@@ -168,19 +168,19 @@ export class ConceptService {
168
168
  const drizzle = this.context.drizzle();
169
169
  const { width, height } = sizes['alchemy']['post4:5'];
170
170
  const { generations, conceptCombinations, concepts } = schema;
171
-
171
+
172
172
  const kvKey = buildConceptKVKey(language, conceptSlug, combinationString);
173
173
  console.log(
174
174
  `🚀 Queuing image generation for concept: ${conceptSlug}, combination: ${combinationString}, language: ${language}`
175
175
  );
176
-
176
+
177
177
  const concept = await this.getKVConcept(kvKey);
178
178
  if (!concept.leonardoPrompt) {
179
179
  throw new Error(
180
180
  `❌ Leonardo prompt must be populated before generating images for concept: ${conceptSlug}`
181
181
  );
182
182
  }
183
-
183
+
184
184
  const conceptRecord = await drizzle
185
185
  .select({
186
186
  id: concepts.id,
@@ -191,29 +191,29 @@ export class ConceptService {
191
191
  .from(concepts)
192
192
  .where(eq(concepts.slug, conceptSlug))
193
193
  .limit(1);
194
-
194
+
195
195
  if (conceptRecord.length === 0) {
196
196
  throw new Error(`❌ No concept found for slug: ${conceptSlug}`);
197
197
  }
198
-
198
+
199
199
  const { id: conceptId, planet1, planet2, planet3 } = conceptRecord[0];
200
200
  console.log(
201
201
  `✅ Retrieved conceptId: ${conceptId} for slug: ${conceptSlug}`
202
202
  );
203
-
203
+
204
204
  const [planet1Sign, planet2Sign, planet3Sign] =
205
205
  combinationString.split('-');
206
-
206
+
207
207
  if (!planet1Sign || !planet2Sign || !planet3Sign) {
208
208
  throw new Error(
209
209
  `❌ Invalid combinationString: ${combinationString} (Expected format: sign1-sign2-[sign3])`
210
210
  );
211
211
  }
212
-
212
+
213
213
  console.log(
214
214
  `🔹 Extracted planet signs: ${planet1} -> ${planet1Sign}, ${planet2} -> ${planet2Sign}, ${planet3} -> ${planet3Sign}`
215
215
  );
216
-
216
+
217
217
  let [conceptCombination] = await drizzle
218
218
  .select({ id: conceptCombinations.id })
219
219
  .from(conceptCombinations)
@@ -224,12 +224,12 @@ export class ConceptService {
224
224
  )
225
225
  )
226
226
  .limit(1);
227
-
227
+
228
228
  if (!conceptCombination) {
229
229
  console.log(
230
230
  `🔍 No existing conceptCombination found. Creating new entry for ${conceptSlug}:${combinationString}`
231
231
  );
232
-
232
+
233
233
  const [insertedCombination] = await drizzle
234
234
  .insert(conceptCombinations)
235
235
  .values({
@@ -241,31 +241,36 @@ export class ConceptService {
241
241
  planet3Sign,
242
242
  })
243
243
  .returning({ id: conceptCombinations.id });
244
-
244
+
245
245
  conceptCombination = insertedCombination;
246
246
  }
247
-
247
+
248
248
  const conceptCombinationId = conceptCombination.id;
249
249
  console.log(
250
250
  `✅ Using conceptCombinationId: ${conceptCombinationId} for ${conceptSlug}:${combinationString}`
251
251
  );
252
-
252
+
253
253
  console.log(`🎨 Requesting Leonardo AI image generation...`);
254
-
254
+
255
255
  const initImage = leonardoInitImages.concepts[conceptSlug];
256
- const controlNets = initImage.imageId
256
+ const controlNets: ControlNetConfig[] = initImage.imageId
257
257
  ? [
258
- {
259
- initImageId: initImage.imageId,
260
- initImageType: 'UPLOADED',
261
- preprocessorId: initImage.preprocessorId!,
262
- ...(initImage.preprocessorId === 100
263
- ? { strengthType: initImage.strengthType! }
264
- : { weight: initImage.weight! }),
265
- },
258
+ initImage.preprocessorId === 100
259
+ ? {
260
+ initImageId: initImage.imageId,
261
+ initImageType: 'UPLOADED',
262
+ preprocessorId: 100,
263
+ strengthType: initImage.strengthType!,
264
+ }
265
+ : {
266
+ initImageId: initImage.imageId,
267
+ initImageType: 'UPLOADED',
268
+ preprocessorId: 19,
269
+ weight: initImage.weight!,
270
+ },
266
271
  ]
267
272
  : [];
268
-
273
+
269
274
  const leonardoResponse = await this.context
270
275
  .api()
271
276
  .callLeonardo.generateImage({
@@ -275,16 +280,16 @@ export class ConceptService {
275
280
  ...(controlNets.length > 0 ? { controlNets } : {}),
276
281
  negPrompt: 'person, hands, face, body parts, people, animals, fingers',
277
282
  });
278
-
283
+
279
284
  const generationId = leonardoResponse?.sdGenerationJob?.generationId;
280
285
  if (!generationId) {
281
286
  throw new Error(
282
287
  `❌ Failed to retrieve generationId from Leonardo response`
283
288
  );
284
289
  }
285
-
290
+
286
291
  console.log(`✅ Leonardo Generation ID received: ${generationId}`);
287
-
292
+
288
293
  await drizzle.insert(generations).values({
289
294
  id: generationId,
290
295
  conceptCombinationId,
@@ -292,11 +297,11 @@ export class ConceptService {
292
297
  status: 'pending',
293
298
  createdAt: new Date(),
294
299
  });
295
-
300
+
296
301
  console.log(
297
302
  `📝 Generation record created: ${generationId} for ${conceptSlug}:${combinationString}`
298
303
  );
299
-
304
+
300
305
  console.log(
301
306
  `🎨 Leonardo AI image generation triggered for ${conceptSlug}:${combinationString}, tracking ID: ${generationId}`
302
307
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zodic/shared",
3
- "version": "0.0.116",
3
+ "version": "0.0.118",
4
4
  "module": "index.ts",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -313,5 +313,5 @@ export type ControlNetConfig =
313
313
  initImageId: string;
314
314
  initImageType: 'UPLOADED' | 'GENERATED';
315
315
  preprocessorId: 19; // Edge to Image
316
- weight: string;
316
+ weight: number;
317
317
  };
@@ -157,12 +157,7 @@ export interface LeonardoRequestBody {
157
157
  modelId: string;
158
158
  presetStyle: string;
159
159
  alchemy: boolean;
160
- controlnets?: Array<{
161
- initImageId: string;
162
- initImageType: string;
163
- preprocessorId: number;
164
- strengthType: string;
165
- }>;
160
+ controlnets?: Array<ControlNetConfig>;
166
161
  init_generation_image_id?: string;
167
162
  init_strength?: number;
168
163
  }
@@ -29,7 +29,7 @@ export const leonardoInitImages: LeonardoInitImages = {
29
29
  imageUrl:
30
30
  'https://cdn.leonardo.ai/users/b117a933-e5c9-45b2-96aa-4b619c2d74ba/initImages/c489e496-00c4-4958-8bcd-4460a43a43bf.jpg',
31
31
  preprocessorId: 19,
32
- weight: '0.3',
32
+ weight: 0.3,
33
33
  },
34
34
  ring: {
35
35
  imageId: null,
@@ -52,7 +52,7 @@ type ControlNetSettings =
52
52
  imageId: string;
53
53
  imageUrl: string;
54
54
  preprocessorId: 19;
55
- weight: string;
55
+ weight: number;
56
56
  strengthType?: null;
57
57
  }
58
58
  | {