@coffer-org/plugin-kitchen 1.1.0 → 1.2.2

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.
@@ -1,3 +1,2 @@
1
1
  declare const _default: import("@coffer-org/sdk/module").ModuleDef;
2
2
  export default _default;
3
- //# sourceMappingURL=index.d.ts.map
@@ -11,18 +11,17 @@ export default defineModule({
11
11
  fields: [
12
12
  field.title({ key: 'name', label: 'core.fields.name' }),
13
13
  field.image({ key: 'logo', label: 'kitchen.food_item.fields.logo' }),
14
- field.text({ key: 'description', label: 'kitchen.food_item.fields.description', max: 1000 }),
15
- field.string({ key: 'subcategory', label: 'kitchen.food_item.fields.subcategory', config: { max: 100 } }),
14
+ field.text({ key: 'description', label: 'kitchen.food_item.fields.description', rules: { max: 1000 } }),
15
+ field.string({ key: 'subcategory', label: 'kitchen.food_item.fields.subcategory', rules: { max: 100 } }),
16
16
  field.measured({
17
17
  key: 'quantity',
18
18
  label: 'kitchen.food_item.fields.quantity',
19
19
  options: 'cooking',
20
- config: { min: 0 },
20
+ rules: { min: 0 },
21
21
  }),
22
- field.int({ key: 'minQuantity', label: 'kitchen.food_item.fields.minQuantity', config: { min: 0 } }),
23
- field.date({ key: 'expires', label: 'kitchen.food_item.fields.expires' }),
24
- field.string({ key: 'brand', label: 'kitchen.food_item.fields.brand', config: { max: 100 } }),
22
+ field.measured({ key: 'minQuantity', label: 'kitchen.food_item.fields.minQuantity', options: 'cooking', rules: { min: 0 } }),
23
+ field.reminder({ key: 'expires', label: 'kitchen.food_item.fields.expires', rules: { lead: 14 } }),
24
+ field.string({ key: 'brand', label: 'kitchen.food_item.fields.brand', rules: { max: 100 } }),
25
25
  field.tags({ key: 'tags', label: 'kitchen.food_item.fields.tags' }),
26
26
  ],
27
27
  });
28
- //# sourceMappingURL=index.js.map
@@ -1,3 +1,2 @@
1
1
  declare const _default: import("@coffer-org/sdk/module").ModuleDef;
2
2
  export default _default;
3
- //# sourceMappingURL=index.d.ts.map
@@ -11,8 +11,8 @@ export default defineModule({
11
11
  fields: [
12
12
  field.title({ key: 'name', label: 'core.fields.name' }),
13
13
  field.image({ key: 'images', label: 'kitchen.food_recipe.fields.images', multiple: true }),
14
- field.text({ key: 'description', label: 'kitchen.food_recipe.fields.description', max: 500 }),
15
- field.int({ key: 'servings', label: 'kitchen.food_recipe.fields.servings', config: { min: 1, max: 100 } }),
14
+ field.text({ key: 'description', label: 'kitchen.food_recipe.fields.description', rules: { max: 500 } }),
15
+ field.int({ key: 'servings', label: 'kitchen.food_recipe.fields.servings', rules: { min: 1, max: 100 } }),
16
16
  field.select({
17
17
  key: 'difficulty',
18
18
  label: 'kitchen.food_recipe.fields.difficulty',
@@ -40,31 +40,27 @@ export default defineModule({
40
40
  field.tags({ key: 'tags', label: 'kitchen.food_recipe.fields.tags' }),
41
41
  field.duration({ key: 'prep_time', label: 'kitchen.food_recipe.fields.prep_time' }),
42
42
  field.duration({ key: 'cook_time', label: 'kitchen.food_recipe.fields.cook_time' }),
43
- field.group({
43
+ field.table({
44
44
  key: 'ingredients',
45
45
  label: 'kitchen.food_recipe.fields.ingredients',
46
- multiple: true,
47
- unique: ['product'],
46
+ rules: { unique: ['product'] },
48
47
  fields: [
49
48
  field.relation({
50
49
  key: 'product',
51
50
  label: 'kitchen.food_recipe.ingredient.product',
52
- vault: 'kitchen',
53
- module: 'food_item',
51
+ options: { vault: 'kitchen', module: 'food_item' },
54
52
  }),
55
- // Просте число: одиниця вимірювання з пов'язаного продукту (lookup)
56
- field.real({ key: 'amount', label: 'kitchen.food_recipe.ingredient.amount', config: { min: 0 } }),
53
+ field.real({ key: 'amount', label: 'kitchen.food_recipe.ingredient.amount', rules: { min: 0 } }),
57
54
  field.lookup({
58
55
  key: 'stock',
59
56
  label: 'kitchen.food_recipe.ingredient.stock',
60
57
  from: 'product',
61
58
  pick: ['quantity'],
62
- compareWith: 'amount',
59
+ view: { compareWith: 'amount' },
63
60
  }),
64
61
  ],
65
62
  }),
66
- field.markdown({ key: 'steps', label: 'kitchen.food_recipe.fields.steps', config: { max: 5000 } }),
67
- field.text({ key: 'comment', label: 'kitchen.food_recipe.fields.comment', max: 1000 }),
63
+ field.markdown({ key: 'steps', label: 'kitchen.food_recipe.fields.steps', rules: { max: 5000 } }),
64
+ field.text({ key: 'comment', label: 'kitchen.food_recipe.fields.comment', rules: { max: 1000 } }),
68
65
  ],
69
66
  });
70
- //# sourceMappingURL=index.js.map
package/dist/index.d.ts CHANGED
@@ -1,3 +1,2 @@
1
1
  declare const _default: import("@coffer-org/sdk/plugin").PluginManifest;
2
2
  export default _default;
3
- //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { defineVault } from '@coffer-org/sdk/vault';
2
2
  import { definePlugin } from '@coffer-org/sdk/plugin';
3
- import food_item from './food_item/index.js';
4
- import food_recipe from './food_recipe/index.js';
3
+ import food_item from "./food_item/index.js";
4
+ import food_recipe from "./food_recipe/index.js";
5
5
  export default definePlugin({
6
6
  id: 'kitchen',
7
7
  version: '1.0.0',
@@ -13,4 +13,3 @@ export default definePlugin({
13
13
  },
14
14
  ],
15
15
  });
16
- //# sourceMappingURL=index.js.map
@@ -0,0 +1,2 @@
1
+ import type { PluginHooks } from '@coffer-org/server/plugin-hooks';
2
+ export declare const serverHooks: PluginHooks;
@@ -0,0 +1,146 @@
1
+ import { fileURLToPath } from 'node:url';
2
+ import { z } from 'zod';
3
+ import { localPost } from '@coffer-org/server/local-api';
4
+ import { seedAsset } from '@coffer-org/server/uploads';
5
+ const intToMeasured = (old) => old == null || old === '' ? null : JSON.stringify({ value: Number(old), unit: 'g' });
6
+ const asset = (rel) => fileURLToPath(new URL(`../../seed/assets/${rel}`, import.meta.url));
7
+ export const serverHooks = {
8
+ migrations: [
9
+ {
10
+ version: 1,
11
+ up: async ({ table }) => {
12
+ await table('kitchen__food_item').changeType('minQuantity', 'text', { transform: intToMeasured });
13
+ },
14
+ },
15
+ ],
16
+ seed: [
17
+ {
18
+ name: 'demo-food-items',
19
+ run: async () => {
20
+ const logo = seedAsset(asset('food.svg'));
21
+ await localPost('kitchen', 'food_item', {
22
+ name: 'Flour',
23
+ logo,
24
+ description: 'Premium wheat flour for baking.',
25
+ subcategory: 'Pantry',
26
+ quantity: { value: 1500, unit: 'g' },
27
+ minQuantity: { value: 500, unit: 'g' },
28
+ expires: '2026-12-31',
29
+ brand: 'Farmstead',
30
+ tags: ['pantry', 'baking'],
31
+ });
32
+ await localPost('kitchen', 'food_item', {
33
+ name: 'Milk',
34
+ logo,
35
+ description: 'Pasteurized milk 2.5%.',
36
+ subcategory: 'Dairy',
37
+ quantity: { value: 2000, unit: 'ml' },
38
+ minQuantity: { value: 1000, unit: 'ml' },
39
+ expires: '2026-07-05',
40
+ brand: 'Meadowbrook',
41
+ tags: ['dairy', 'fridge'],
42
+ });
43
+ await localPost('kitchen', 'food_item', {
44
+ name: 'Eggs',
45
+ logo,
46
+ description: 'Large chicken eggs.',
47
+ subcategory: 'Eggs',
48
+ quantity: { value: 10, unit: 'pcs' },
49
+ minQuantity: { value: 3, unit: 'pcs' },
50
+ expires: '2026-07-20',
51
+ brand: 'Sunrise Farm',
52
+ tags: ['fridge', 'protein'],
53
+ });
54
+ },
55
+ },
56
+ {
57
+ name: 'demo-recipes',
58
+ run: async () => {
59
+ const logo = seedAsset(asset('food.svg'));
60
+ const flour = await localPost('kitchen', 'food_item', {
61
+ name: 'Flour (for recipes)',
62
+ logo,
63
+ subcategory: 'Pantry',
64
+ quantity: { value: 1000, unit: 'g' },
65
+ minQuantity: { value: 500, unit: 'g' },
66
+ tags: ['pantry'],
67
+ });
68
+ const milk = await localPost('kitchen', 'food_item', {
69
+ name: 'Milk (for recipes)',
70
+ logo,
71
+ subcategory: 'Dairy',
72
+ quantity: { value: 1000, unit: 'ml' },
73
+ minQuantity: { value: 500, unit: 'ml' },
74
+ tags: ['dairy'],
75
+ });
76
+ const eggs = await localPost('kitchen', 'food_item', {
77
+ name: 'Eggs (for recipes)',
78
+ logo,
79
+ subcategory: 'Eggs',
80
+ quantity: { value: 12, unit: 'pcs' },
81
+ minQuantity: { value: 4, unit: 'pcs' },
82
+ tags: ['protein'],
83
+ });
84
+ await localPost('kitchen', 'food_recipe', {
85
+ name: 'Pancakes',
86
+ images: [logo],
87
+ description: 'Thin classic pancakes made with milk.',
88
+ servings: 4,
89
+ difficulty: 'easy',
90
+ category: ['main', 'dessert'],
91
+ tags: ['breakfast', 'classic'],
92
+ prep_time: 600,
93
+ cook_time: 1200,
94
+ ingredients: [
95
+ { product: flour.id, amount: 250 },
96
+ { product: milk.id, amount: 500 },
97
+ { product: eggs.id, amount: 2 },
98
+ ],
99
+ steps: '1. Whisk the eggs with the milk.\n2. Gradually add the flour, stirring until smooth.\n3. Cook on a heated pan on both sides.',
100
+ comment: 'Serve with jam or sour cream.',
101
+ });
102
+ await localPost('kitchen', 'food_recipe', {
103
+ name: 'Omelette',
104
+ images: [logo],
105
+ description: 'Fluffy omelette made with milk.',
106
+ servings: 2,
107
+ difficulty: 'easy',
108
+ category: ['main'],
109
+ tags: ['breakfast', 'quick'],
110
+ prep_time: 300,
111
+ cook_time: 480,
112
+ ingredients: [
113
+ { product: eggs.id, amount: 4 },
114
+ { product: milk.id, amount: 100 },
115
+ ],
116
+ steps: '1. Whisk the eggs with the milk and a pinch of salt.\n2. Pour onto a heated pan.\n3. Cook covered until set.',
117
+ comment: 'You can add herbs or cheese.',
118
+ });
119
+ },
120
+ },
121
+ ],
122
+ agent: {
123
+ instructions: 'Vault kitchen stores food products (food_item) and recipes (food_recipe). ' +
124
+ 'Quantity is the quantity {value,unit} field; shelf life is expires (ISO date). ' +
125
+ 'To write off a used product — delete_record on kitchen/food_item, do not set quantity to 0.' +
126
+ ' When a product is bought/used — update quantity (and expires on purchase) via update_record.',
127
+ tools: [
128
+ {
129
+ name: 'expiring_soon',
130
+ description: 'kitchen products expiring within N days (including already expired).',
131
+ inputSchema: { days: z.number().int().positive() },
132
+ handler: async (args, { em }) => {
133
+ const days = Number(args.days);
134
+ const cutoff = Date.now() + days * 86_400_000;
135
+ const rows = (await em.fork().find('kitchen__food_item', {}));
136
+ return rows
137
+ .filter((r) => {
138
+ const t = Date.parse(String(r.expires ?? ''));
139
+ return !Number.isNaN(t) && t <= cutoff;
140
+ })
141
+ .map((r) => ({ id: r.id, name: r.name, expires: r.expires }));
142
+ },
143
+ },
144
+ ],
145
+ },
146
+ };
package/package.json CHANGED
@@ -1,14 +1,22 @@
1
1
  {
2
2
  "name": "@coffer-org/plugin-kitchen",
3
- "version": "1.1.0",
3
+ "version": "1.2.2",
4
4
  "type": "module",
5
+ "engines": {
6
+ "node": ">=24"
7
+ },
5
8
  "files": [
6
- "dist"
9
+ "dist",
10
+ "seed"
7
11
  ],
8
12
  "exports": {
9
13
  ".": {
10
14
  "types": "./dist/index.d.ts",
11
15
  "default": "./dist/index.js"
16
+ },
17
+ "./runtime": {
18
+ "types": "./dist/runtime/index.d.ts",
19
+ "default": "./dist/runtime/index.js"
12
20
  }
13
21
  },
14
22
  "scripts": {
@@ -17,6 +25,8 @@
17
25
  "postpack": "node ../../scripts/swap-exports.mjs src"
18
26
  },
19
27
  "dependencies": {
20
- "@coffer-org/sdk": "^1.1.0"
28
+ "@coffer-org/sdk": "^1.2.2",
29
+ "@coffer-org/server": "^1.2.2",
30
+ "zod": "^4.4.3"
21
31
  }
22
32
  }
@@ -0,0 +1,5 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="160" height="160" viewBox="0 0 160 160" role="img" aria-label="demo food">
2
+ <rect width="160" height="160" rx="16" fill="#fef3c7"/>
3
+ <circle cx="80" cy="80" r="44" fill="#f59e0b"/>
4
+ <path d="M80 40v80M40 80h80" stroke="#fff" stroke-width="8" stroke-linecap="round"/>
5
+ </svg>
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/food_item/index.ts"],"names":[],"mappings":";AAGA,wBAwBG"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/food_item/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAE/C,eAAe,YAAY,CAAC;IAC1B,MAAM,EAAE,WAAW;IACnB,KAAK,EAAE,SAAS;IAChB,KAAK,EAAE,yBAAyB;IAChC,IAAI,EAAE,aAAa;IACnB,KAAK,EAAE;QACL,KAAK,EAAE,CAAC,aAAa,EAAE,UAAU,EAAE,SAAS,CAAC;KAC9C;IACD,MAAM,EAAE;QACN,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC;QACvD,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,+BAA+B,EAAE,CAAC;QACpE,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,sCAAsC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;QAC5F,KAAK,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,sCAAsC,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC;QACzG,KAAK,CAAC,QAAQ,CAAC;YACb,GAAG,EAAE,UAAU;YACf,KAAK,EAAE,mCAAmC;YAC1C,OAAO,EAAE,SAAS;YAClB,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE;SACnB,CAAC;QACF,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,sCAAsC,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACpG,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,kCAAkC,EAAE,CAAC;QACzE,KAAK,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,gCAAgC,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC;QAC7F,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,+BAA+B,EAAE,CAAC;KACpE;CACF,CAAC,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/food_recipe/index.ts"],"names":[],"mappings":";AAGA,wBAkEG"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/food_recipe/index.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAKA,wBAUG"}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,SAAS,MAAM,sBAAsB,CAAC;AAC7C,OAAO,WAAW,MAAM,wBAAwB,CAAC;AAEjD,eAAe,YAAY,CAAC;IAC1B,EAAE,EAAE,SAAS;IACb,OAAO,EAAE,OAAO;IAChB,SAAS,EAAE,EAAE;IACb,MAAM,EAAE;QACN;YACE,IAAI,EAAE,WAAW,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,qBAAqB,EAAE,IAAI,EAAE,oBAAoB,EAAE,CAAC;YAC9F,OAAO,EAAE,CAAC,SAAS,EAAE,WAAW,CAAC;SAClC;KACF;CACF,CAAC,CAAC"}