The recipes.blue monorepo recipes.blue
recipes appview atproto
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: serves parameter

+195
+3
apps/api/src/xrpc/index.ts
··· 21 21 title: recipeTable.title, 22 22 description: recipeTable.description, 23 23 time: recipeTable.time, 24 + serves: recipeTable.serves, 24 25 ingredientsCount: sql`json_array_length(${recipeTable.ingredients})`, 25 26 stepsCount: sql`json_array_length(${recipeTable.steps})`, 26 27 createdAt: recipeTable.createdAt, ··· 49 50 rkey: r.rkey, 50 51 title: r.title, 51 52 time: r.time, 53 + serves: r.serves, 52 54 description: r.description || undefined, 53 55 ingredients: r.ingredientsCount as number, 54 56 steps: r.stepsCount as number, ··· 111 113 author: authorInfo, 112 114 title: recipe.title, 113 115 time: recipe.time, 116 + serves: recipe.serves, 114 117 description: recipe.description, 115 118 ingredients: recipe.ingredients, 116 119 steps: recipe.steps,
+2
apps/ingester/src/index.ts
··· 30 30 rkey: event.commit.rkey, 31 31 title: record.title, 32 32 time: record.time, 33 + serves: record.serves, 33 34 description: record.description, 34 35 ingredients: record.ingredients, 35 36 steps: record.steps, ··· 42 43 set: { 43 44 title: record.title, 44 45 time: record.time, 46 + serves: record.serves, 45 47 description: record.description, 46 48 ingredients: record.ingredients, 47 49 steps: record.steps,
+1
lexicons/blue/recipes/feed/getRecipe.json
··· 40 40 "title": { "type": "string" }, 41 41 "description": { "type": "string" }, 42 42 "time": { "type": "integer" }, 43 + "serves": { "type": "integer" }, 43 44 "imageUrl": { "type": "string" }, 44 45 "ingredients": { 45 46 "type": "array",
+1
lexicons/blue/recipes/feed/getRecipes.json
··· 49 49 "imageUrl": { "type": "string" }, 50 50 "title": { "type": "string" }, 51 51 "time": { "type": "integer" }, 52 + "serves": { "type": "integer" }, 52 53 "description": { "type": "string" }, 53 54 "ingredients": { "type": "integer" }, 54 55 "steps": { "type": "integer" }
+4
lexicons/blue/recipes/feed/recipes.json
··· 32 32 "type": "integer", 33 33 "description": "The amount of time (in minutes) the recipe takes to complete." 34 34 }, 35 + "serves": { 36 + "type": "integer", 37 + "description": "The amount of people the recipe will make servings for." 38 + }, 35 39 "ingredients": { 36 40 "type": "array", 37 41 "items": {
+1
libs/database/migrations/0004_left_sersi.sql
··· 1 + ALTER TABLE `recipes` ADD `serves` integer;
+170
libs/database/migrations/meta/0004_snapshot.json
··· 1 + { 2 + "version": "6", 3 + "dialect": "sqlite", 4 + "id": "d6e34451-dba5-4458-8471-ac988decffec", 5 + "prevId": "fa77a98d-2ae1-49d5-ab93-81492dcbdebd", 6 + "tables": { 7 + "auth_session": { 8 + "name": "auth_session", 9 + "columns": { 10 + "key": { 11 + "name": "key", 12 + "type": "text", 13 + "primaryKey": true, 14 + "notNull": true, 15 + "autoincrement": false 16 + }, 17 + "session": { 18 + "name": "session", 19 + "type": "text", 20 + "primaryKey": false, 21 + "notNull": true, 22 + "autoincrement": false 23 + } 24 + }, 25 + "indexes": {}, 26 + "foreignKeys": {}, 27 + "compositePrimaryKeys": {}, 28 + "uniqueConstraints": {}, 29 + "checkConstraints": {} 30 + }, 31 + "auth_state": { 32 + "name": "auth_state", 33 + "columns": { 34 + "key": { 35 + "name": "key", 36 + "type": "text", 37 + "primaryKey": true, 38 + "notNull": true, 39 + "autoincrement": false 40 + }, 41 + "state": { 42 + "name": "state", 43 + "type": "text", 44 + "primaryKey": false, 45 + "notNull": true, 46 + "autoincrement": false 47 + } 48 + }, 49 + "indexes": {}, 50 + "foreignKeys": {}, 51 + "compositePrimaryKeys": {}, 52 + "uniqueConstraints": {}, 53 + "checkConstraints": {} 54 + }, 55 + "recipes": { 56 + "name": "recipes", 57 + "columns": { 58 + "id": { 59 + "name": "id", 60 + "type": "integer", 61 + "primaryKey": true, 62 + "notNull": true, 63 + "autoincrement": false 64 + }, 65 + "rkey": { 66 + "name": "rkey", 67 + "type": "text", 68 + "primaryKey": false, 69 + "notNull": true, 70 + "autoincrement": false 71 + }, 72 + "title": { 73 + "name": "title", 74 + "type": "text", 75 + "primaryKey": false, 76 + "notNull": true, 77 + "autoincrement": false 78 + }, 79 + "image_ref": { 80 + "name": "image_ref", 81 + "type": "text", 82 + "primaryKey": false, 83 + "notNull": false, 84 + "autoincrement": false 85 + }, 86 + "time": { 87 + "name": "time", 88 + "type": "integer", 89 + "primaryKey": false, 90 + "notNull": true, 91 + "autoincrement": false, 92 + "default": 0 93 + }, 94 + "serves": { 95 + "name": "serves", 96 + "type": "integer", 97 + "primaryKey": false, 98 + "notNull": false, 99 + "autoincrement": false 100 + }, 101 + "description": { 102 + "name": "description", 103 + "type": "text", 104 + "primaryKey": false, 105 + "notNull": false, 106 + "autoincrement": false 107 + }, 108 + "ingredients": { 109 + "name": "ingredients", 110 + "type": "text", 111 + "primaryKey": false, 112 + "notNull": true, 113 + "autoincrement": false 114 + }, 115 + "steps": { 116 + "name": "steps", 117 + "type": "text", 118 + "primaryKey": false, 119 + "notNull": true, 120 + "autoincrement": false 121 + }, 122 + "created_at": { 123 + "name": "created_at", 124 + "type": "text", 125 + "primaryKey": false, 126 + "notNull": true, 127 + "autoincrement": false 128 + }, 129 + "author_did": { 130 + "name": "author_did", 131 + "type": "text", 132 + "primaryKey": false, 133 + "notNull": true, 134 + "autoincrement": false 135 + } 136 + }, 137 + "indexes": { 138 + "recipes_id_unique": { 139 + "name": "recipes_id_unique", 140 + "columns": [ 141 + "id" 142 + ], 143 + "isUnique": true 144 + }, 145 + "recipes_rkey_author_did_unique": { 146 + "name": "recipes_rkey_author_did_unique", 147 + "columns": [ 148 + "rkey", 149 + "author_did" 150 + ], 151 + "isUnique": true 152 + } 153 + }, 154 + "foreignKeys": {}, 155 + "compositePrimaryKeys": {}, 156 + "uniqueConstraints": {}, 157 + "checkConstraints": {} 158 + } 159 + }, 160 + "views": {}, 161 + "enums": {}, 162 + "_meta": { 163 + "schemas": {}, 164 + "tables": {}, 165 + "columns": {} 166 + }, 167 + "internal": { 168 + "indexes": {} 169 + } 170 + }
+7
libs/database/migrations/meta/_journal.json
··· 29 29 "when": 1734643156502, 30 30 "tag": "0003_fixed_peter_parker", 31 31 "breakpoints": true 32 + }, 33 + { 34 + "idx": 4, 35 + "version": "6", 36 + "when": 1735493787990, 37 + "tag": "0004_left_sersi", 38 + "breakpoints": true 32 39 } 33 40 ] 34 41 }
+1
libs/database/src/schema.ts
··· 23 23 title: text('title').notNull(), 24 24 imageRef: text('image_ref'), 25 25 time: int('time').notNull().default(0), 26 + serves: int('serves'), 26 27 description: text('description'), 27 28 ingredients: text('ingredients', { mode: 'json' }).$type<Partial<Ingredient>[]>().notNull(), 28 29 steps: text('steps', { mode: 'json' }).$type<Partial<Step>[]>().notNull(),
+4
libs/lexicons/src/atcute.ts
··· 57 57 title: string; 58 58 description?: string; 59 59 imageUrl?: string; 60 + serves?: number; 60 61 time?: number; 61 62 } 62 63 } ··· 82 83 title: string; 83 84 description?: string; 84 85 imageUrl?: string; 86 + serves?: number; 85 87 type?: string; 86 88 } 87 89 } ··· 106 108 description?: string; 107 109 /** The recipe's cover image. */ 108 110 image?: At.Blob; 111 + /** The amount of people the recipe will make servings for. */ 112 + serves?: number; 109 113 /** The amount of time (in minutes) the recipe takes to complete. */ 110 114 time?: number; 111 115 }
+1
libs/lexicons/src/recipe.ts
··· 7 7 title: z.string().max(3000, 'Recipe titles must be under 3000 characters.'), 8 8 description: z.string().max(3000, 'Recipe descriptions must be under 3000 characters.').nullable(), 9 9 time: z.number({ message: 'Time must be a number.' }), 10 + serves: z.number({ message: 'Serves must be a number.' }), 10 11 ingredients: z.array(IngredientObject), 11 12 steps: z.array(StepObject), 12 13 });