@krizaka/org 0.4.0 → 0.6.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.
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // package.json
2
2
  var package_default = {
3
3
  name: "@krizaka/org",
4
- version: "0.4.0",
4
+ version: "0.6.0",
5
5
  description: "The public facts about Krizaka, in one validated JSON that every footer, site and app reads: legal name, NEQ, \xAB Fait \xE0 Montr\xE9al \xBB in French and English, brand marks, default avatars and banners, the live products and sites, the public contact, the footer line and the mobile apps' public runtime config. Typed data, JSON Schema, and the files published on the CDN.",
6
6
  keywords: [
7
7
  "krizaka",
@@ -43,7 +43,7 @@ var package_default = {
43
43
  build: `node -e "require('node:fs').rmSync('dist',{recursive:true,force:true})" && tsup && node scripts/emit.mjs`,
44
44
  lint: "eslint . --max-warnings 0 && tsc --noEmit",
45
45
  typecheck: "tsc --noEmit",
46
- test: "vitest run",
46
+ test: 'vitest run --coverage --coverage.provider=v8 --coverage.reporter=lcov --coverage.reporter=text-summary "--coverage.include=src/**/*.ts"',
47
47
  check: "pnpm run lint && pnpm run test && pnpm run build",
48
48
  "publish:cdn": "node scripts/publish.mjs",
49
49
  prepublishOnly: "pnpm run build"
@@ -64,8 +64,20 @@ var package_default = {
64
64
 
65
65
  // src/defaults.ts
66
66
  var BASE = "https://krizaka-assets.b-cdn.net/defaults/v1";
67
- var DEFAULT_KINDS = ["person", "folder", "organisation", "shop", "banner"];
68
- var SIZES = { person: [256, 512, 1024], folder: [256, 512, 1024], organisation: [256, 512, 1024], shop: [256, 512, 1024], banner: [960, 1920] };
67
+ var DEFAULT_KINDS = [
68
+ "person",
69
+ "folder",
70
+ "organisation",
71
+ "shop",
72
+ "banner"
73
+ ];
74
+ var SIZES = {
75
+ person: [256, 512, 1024],
76
+ folder: [256, 512, 1024],
77
+ organisation: [256, 512, 1024],
78
+ shop: [256, 512, 1024],
79
+ banner: [960, 1920]
80
+ };
69
81
  var DISABLED_DEFAULTS = /* @__PURE__ */ new Set(["banner/the-neon-flamingo"]);
70
82
  var item = (kind, id, alt, drawn) => ({
71
83
  id,
@@ -78,38 +90,194 @@ var item = (kind, id, alt, drawn) => ({
78
90
  });
79
91
  var tones = (kind, id, alt) => Array.from({ length: 6 }, (_, i) => item(kind, `${id}-${i + 1}`, alt(i + 1), true));
80
92
  var PEOPLE = [
81
- ["boom-bap", { en: "Illustration: a rapper in a denim jacket and beanie, microphone in hand, in a rainy Montr\xE9al alley at night", fr: "Illustration : un rappeur en veste de jean et tuque, micro \xE0 la main, dans une ruelle de Montr\xE9al sous la pluie, la nuit" }],
82
- ["rasta-creative", { en: "A smiling man with long dreadlocks in a paint-stained denim jacket, in an artist's workshop", fr: "Un homme souriant aux longues dreadlocks, en veste de jean tach\xE9e de peinture, dans un atelier d'artiste" }],
83
- ["mile-end-hipster", { en: "A smiling person with round glasses and an orange beanie at a leatherworking bench, in a brick workshop", fr: "Une personne souriante \xE0 lunettes rondes et tuque orange, \xE0 son \xE9tabli de cuir, dans un atelier de briques" }],
84
- ["tech-architect", { en: "A person in a dark hoodie typing at a keyboard, between screens of code and a server rack", fr: "Une personne en chandail \xE0 capuchon sombre qui tape au clavier, entre des \xE9crans de code et une baie de serveurs" }],
85
- ["electronic-dj", { en: "A DJ with headphones behind synthesizers and a mixing desk, in a club with violet lights", fr: "Un DJ casque aux oreilles derri\xE8re des synth\xE9tiseurs et une table de mixage, dans un club aux lumi\xE8res violettes" }],
86
- ["visual-artist", { en: "A smiling painter with violet hair and big glasses, palette in hand, in a studio full of canvases", fr: "Une peintre souriante aux cheveux violets et aux grosses lunettes, palette \xE0 la main, dans un atelier plein de toiles" }],
87
- ["salon-tattoo-maker", { en: "A tattoo artist with tattooed arms working on a client in a warm shop with wooden shelves", fr: "Une tatoueuse aux bras tatou\xE9s au travail sur un client, dans un salon chaleureux aux \xE9tag\xE8res de bois" }],
88
- ["wise-auditor", { en: "A grey-haired person with glasses at a desk of old books and a lamp, a pen over open notes", fr: "Une personne aux cheveux gris et \xE0 lunettes \xE0 un bureau de vieux livres et de lampe, un stylo sur des notes ouvertes" }],
89
- ["digital-creator", { en: "A laughing streamer with a microphone in a purple-lit studio under a neon \xAB Creator Zone \xBB sign", fr: "Une diffuseuse qui rit devant un micro, dans un studio violet sous une enseigne n\xE9on \xAB Creator Zone \xBB" }],
90
- ["studio-maker", { en: "A potter in a linen apron holding a clay bowl, in a bright ceramics studio with plants", fr: "Une poti\xE8re en tablier de lin tenant un bol d'argile, dans un atelier de c\xE9ramique lumineux et plein de plantes" }],
91
- ["community-lead", { en: "A smiling person with curly hair and a grey coat at a wooden table, a community space behind them", fr: "Une personne souriante aux cheveux boucl\xE9s et au manteau gris, \xE0 une table de bois, devant un espace communautaire" }],
92
- ["ai-builder", { en: "A thoughtful person with blue-tinted glasses at a desk, screens of a neural network and code behind", fr: "Une personne pensive aux lunettes teint\xE9es de bleu \xE0 son bureau, devant des \xE9crans de r\xE9seau neuronal et de code" }]
93
+ [
94
+ "boom-bap",
95
+ {
96
+ en: "Illustration: a rapper in a denim jacket and beanie, microphone in hand, in a rainy Montr\xE9al alley at night",
97
+ fr: "Illustration : un rappeur en veste de jean et tuque, micro \xE0 la main, dans une ruelle de Montr\xE9al sous la pluie, la nuit"
98
+ }
99
+ ],
100
+ [
101
+ "rasta-creative",
102
+ {
103
+ en: "A smiling man with long dreadlocks in a paint-stained denim jacket, in an artist's workshop",
104
+ fr: "Un homme souriant aux longues dreadlocks, en veste de jean tach\xE9e de peinture, dans un atelier d'artiste"
105
+ }
106
+ ],
107
+ [
108
+ "mile-end-hipster",
109
+ {
110
+ en: "A smiling person with round glasses and an orange beanie at a leatherworking bench, in a brick workshop",
111
+ fr: "Une personne souriante \xE0 lunettes rondes et tuque orange, \xE0 son \xE9tabli de cuir, dans un atelier de briques"
112
+ }
113
+ ],
114
+ [
115
+ "tech-architect",
116
+ {
117
+ en: "A person in a dark hoodie typing at a keyboard, between screens of code and a server rack",
118
+ fr: "Une personne en chandail \xE0 capuchon sombre qui tape au clavier, entre des \xE9crans de code et une baie de serveurs"
119
+ }
120
+ ],
121
+ [
122
+ "electronic-dj",
123
+ {
124
+ en: "A DJ with headphones behind synthesizers and a mixing desk, in a club with violet lights",
125
+ fr: "Un DJ casque aux oreilles derri\xE8re des synth\xE9tiseurs et une table de mixage, dans un club aux lumi\xE8res violettes"
126
+ }
127
+ ],
128
+ [
129
+ "visual-artist",
130
+ {
131
+ en: "A smiling painter with violet hair and big glasses, palette in hand, in a studio full of canvases",
132
+ fr: "Une peintre souriante aux cheveux violets et aux grosses lunettes, palette \xE0 la main, dans un atelier plein de toiles"
133
+ }
134
+ ],
135
+ [
136
+ "salon-tattoo-maker",
137
+ {
138
+ en: "A tattoo artist with tattooed arms working on a client in a warm shop with wooden shelves",
139
+ fr: "Une tatoueuse aux bras tatou\xE9s au travail sur un client, dans un salon chaleureux aux \xE9tag\xE8res de bois"
140
+ }
141
+ ],
142
+ [
143
+ "wise-auditor",
144
+ {
145
+ en: "A grey-haired person with glasses at a desk of old books and a lamp, a pen over open notes",
146
+ fr: "Une personne aux cheveux gris et \xE0 lunettes \xE0 un bureau de vieux livres et de lampe, un stylo sur des notes ouvertes"
147
+ }
148
+ ],
149
+ [
150
+ "digital-creator",
151
+ {
152
+ en: "A laughing streamer with a microphone in a purple-lit studio under a neon \xAB Creator Zone \xBB sign",
153
+ fr: "Une diffuseuse qui rit devant un micro, dans un studio violet sous une enseigne n\xE9on \xAB Creator Zone \xBB"
154
+ }
155
+ ],
156
+ [
157
+ "studio-maker",
158
+ {
159
+ en: "A potter in a linen apron holding a clay bowl, in a bright ceramics studio with plants",
160
+ fr: "Une poti\xE8re en tablier de lin tenant un bol d'argile, dans un atelier de c\xE9ramique lumineux et plein de plantes"
161
+ }
162
+ ],
163
+ [
164
+ "community-lead",
165
+ {
166
+ en: "A smiling person with curly hair and a grey coat at a wooden table, a community space behind them",
167
+ fr: "Une personne souriante aux cheveux boucl\xE9s et au manteau gris, \xE0 une table de bois, devant un espace communautaire"
168
+ }
169
+ ],
170
+ [
171
+ "ai-builder",
172
+ {
173
+ en: "A thoughtful person with blue-tinted glasses at a desk, screens of a neural network and code behind",
174
+ fr: "Une personne pensive aux lunettes teint\xE9es de bleu \xE0 son bureau, devant des \xE9crans de r\xE9seau neuronal et de code"
175
+ }
176
+ ]
93
177
  ];
94
178
  var BANNERS = [
95
- ["montreal-winter-night", { en: "Illustration: a snowy night in downtown Montr\xE9al, lit shop fronts and walkers", fr: "Illustration : une nuit de neige au centre-ville de Montr\xE9al, devantures \xE9clair\xE9es et passants" }],
96
- ["industrial-heritage", { en: "Dark blue skyline of old brick buildings with lit orange windows under a full moon", fr: "Silhouette bleu nuit de vieux immeubles de briques aux fen\xEAtres orang\xE9es, sous la pleine lune" }],
97
- ["creator-loft-studio", { en: "A dark loft desk with a plant, a code window and a mixing board", fr: "Un bureau de loft sombre avec une plante, une fen\xEAtre de code et une table de mixage" }],
98
- ["abstract-digital-flow", { en: "Flowing teal, violet and orange lines linking glowing points on a dark background", fr: "Des lignes ondulantes turquoise, violettes et orange reliant des points lumineux sur fond sombre" }],
99
- ["paperwork-and-ink", { en: "Two dark document cards with colored stamps on a night-blue grid", fr: "Deux cartes de documents sombres tamponn\xE9es de couleur sur une grille bleu nuit" }],
100
- ["nightlife-music-visual", { en: "A large glowing vinyl record with a pink label beside a small level meter, in violet light", fr: "Un grand disque vinyle lumineux \xE0 l'\xE9tiquette rose pr\xE8s d'un petit indicateur de niveau, en lumi\xE8re violette" }],
101
- ["the-mascot-flock", { en: "The Krizaka mascots \u2014 an owl, a beaver and a flamingo \u2014 standing on a shelf in the dark", fr: "Les mascottes de Krizaka \u2014 un hibou, un castor et un flamant \u2014 debout sur une \xE9tag\xE8re dans le noir" }],
102
- ["abstract-stripes", { en: "Diagonal teal, indigo, violet and orange stripes with a white star and \xAB Montr\xE9al // 514 \xBB", fr: "Des bandes diagonales turquoise, indigo, violettes et orange avec une \xE9toile blanche et \xAB Montr\xE9al // 514 \xBB" }],
103
- ["open-source-horizon", { en: "A dark terminal window on a grid, a faint horizon behind", fr: "Une fen\xEAtre de terminal sombre sur une grille, un horizon p\xE2le derri\xE8re" }],
104
- ["cafe-maker-studio", { en: "A warm dark brown scene with a card reading \xAB Fabriqu\xE9 \xE0 Montr\xE9al \xBB", fr: "Une sc\xE8ne brun fonc\xE9 chaleureuse avec une carte \xAB Fabriqu\xE9 \xE0 Montr\xE9al \xBB" }],
105
- ["the-neon-flamingo", { en: "A pink neon flamingo outline on black, with a violet halo", fr: "Le contour d'un flamant rose en n\xE9on sur fond noir, avec un halo violet" }],
106
- ["cooperative-network", { en: "Small linked glowing points over a dark hill at dusk", fr: "De petits points lumineux reli\xE9s au-dessus d'une colline sombre au cr\xE9puscule" }]
179
+ [
180
+ "montreal-winter-night",
181
+ {
182
+ en: "Illustration: a snowy night in downtown Montr\xE9al, lit shop fronts and walkers",
183
+ fr: "Illustration : une nuit de neige au centre-ville de Montr\xE9al, devantures \xE9clair\xE9es et passants"
184
+ }
185
+ ],
186
+ [
187
+ "industrial-heritage",
188
+ {
189
+ en: "Dark blue skyline of old brick buildings with lit orange windows under a full moon",
190
+ fr: "Silhouette bleu nuit de vieux immeubles de briques aux fen\xEAtres orang\xE9es, sous la pleine lune"
191
+ }
192
+ ],
193
+ [
194
+ "creator-loft-studio",
195
+ {
196
+ en: "A dark loft desk with a plant, a code window and a mixing board",
197
+ fr: "Un bureau de loft sombre avec une plante, une fen\xEAtre de code et une table de mixage"
198
+ }
199
+ ],
200
+ [
201
+ "abstract-digital-flow",
202
+ {
203
+ en: "Flowing teal, violet and orange lines linking glowing points on a dark background",
204
+ fr: "Des lignes ondulantes turquoise, violettes et orange reliant des points lumineux sur fond sombre"
205
+ }
206
+ ],
207
+ [
208
+ "paperwork-and-ink",
209
+ {
210
+ en: "Two dark document cards with colored stamps on a night-blue grid",
211
+ fr: "Deux cartes de documents sombres tamponn\xE9es de couleur sur une grille bleu nuit"
212
+ }
213
+ ],
214
+ [
215
+ "nightlife-music-visual",
216
+ {
217
+ en: "A large glowing vinyl record with a pink label beside a small level meter, in violet light",
218
+ fr: "Un grand disque vinyle lumineux \xE0 l'\xE9tiquette rose pr\xE8s d'un petit indicateur de niveau, en lumi\xE8re violette"
219
+ }
220
+ ],
221
+ [
222
+ "the-mascot-flock",
223
+ {
224
+ en: "The Krizaka mascots \u2014 an owl, a beaver and a flamingo \u2014 standing on a shelf in the dark",
225
+ fr: "Les mascottes de Krizaka \u2014 un hibou, un castor et un flamant \u2014 debout sur une \xE9tag\xE8re dans le noir"
226
+ }
227
+ ],
228
+ [
229
+ "abstract-stripes",
230
+ {
231
+ en: "Diagonal teal, indigo, violet and orange stripes with a white star and \xAB Montr\xE9al // 514 \xBB",
232
+ fr: "Des bandes diagonales turquoise, indigo, violettes et orange avec une \xE9toile blanche et \xAB Montr\xE9al // 514 \xBB"
233
+ }
234
+ ],
235
+ [
236
+ "open-source-horizon",
237
+ {
238
+ en: "A dark terminal window on a grid, a faint horizon behind",
239
+ fr: "Une fen\xEAtre de terminal sombre sur une grille, un horizon p\xE2le derri\xE8re"
240
+ }
241
+ ],
242
+ [
243
+ "cafe-maker-studio",
244
+ {
245
+ en: "A warm dark brown scene with a card reading \xAB Fabriqu\xE9 \xE0 Montr\xE9al \xBB",
246
+ fr: "Une sc\xE8ne brun fonc\xE9 chaleureuse avec une carte \xAB Fabriqu\xE9 \xE0 Montr\xE9al \xBB"
247
+ }
248
+ ],
249
+ [
250
+ "the-neon-flamingo",
251
+ {
252
+ en: "A pink neon flamingo outline on black, with a violet halo",
253
+ fr: "Le contour d'un flamant rose en n\xE9on sur fond noir, avec un halo violet"
254
+ }
255
+ ],
256
+ [
257
+ "cooperative-network",
258
+ {
259
+ en: "Small linked glowing points over a dark hill at dusk",
260
+ fr: "De petits points lumineux reli\xE9s au-dessus d'une colline sombre au cr\xE9puscule"
261
+ }
262
+ ]
107
263
  ];
108
264
  var GLYPH_ALT = {
109
- person: (n) => ({ en: `Default profile picture: a silhouette, tone ${n}`, fr: `Photo de profil par d\xE9faut : une silhouette, teinte ${n}` }),
110
- folder: (n) => ({ en: `Default folder picture: a folder, tone ${n}`, fr: `Image de dossier par d\xE9faut : un dossier, teinte ${n}` }),
111
- organisation: (n) => ({ en: `Default organisation picture: a building, tone ${n}`, fr: `Image d'organisation par d\xE9faut : un immeuble, teinte ${n}` }),
112
- shop: (n) => ({ en: `Default shop picture: a storefront, tone ${n}`, fr: `Image de boutique par d\xE9faut : une devanture, teinte ${n}` })
265
+ person: (n) => ({
266
+ en: `Default profile picture: a silhouette, tone ${n}`,
267
+ fr: `Photo de profil par d\xE9faut : une silhouette, teinte ${n}`
268
+ }),
269
+ folder: (n) => ({
270
+ en: `Default folder picture: a folder, tone ${n}`,
271
+ fr: `Image de dossier par d\xE9faut : un dossier, teinte ${n}`
272
+ }),
273
+ organisation: (n) => ({
274
+ en: `Default organisation picture: a building, tone ${n}`,
275
+ fr: `Image d'organisation par d\xE9faut : un immeuble, teinte ${n}`
276
+ }),
277
+ shop: (n) => ({
278
+ en: `Default shop picture: a storefront, tone ${n}`,
279
+ fr: `Image de boutique par d\xE9faut : une devanture, teinte ${n}`
280
+ })
113
281
  };
114
282
  var defaults = {
115
283
  version: "v1",
@@ -119,7 +287,10 @@ var defaults = {
119
287
  description: "defaultFor(kind, seed) = items[fnv1a32(String(seed)) mod items.length] of the kind's list, in the order of the JSON; the same seed always gives the same item, in every app."
120
288
  },
121
289
  kinds: {
122
- person: [...tones("person", "silhouette", GLYPH_ALT.person), ...PEOPLE.map(([id, alt]) => item("person", id, alt, false))],
290
+ person: [
291
+ ...tones("person", "silhouette", GLYPH_ALT.person),
292
+ ...PEOPLE.map(([id, alt]) => item("person", id, alt, false))
293
+ ],
123
294
  folder: tones("folder", "folder", GLYPH_ALT.folder),
124
295
  organisation: tones("organisation", "organisation", GLYPH_ALT.organisation),
125
296
  shop: tones("shop", "shop", GLYPH_ALT.shop),
@@ -168,7 +339,13 @@ var mark = (kind, theme) => ({
168
339
  png1024: cdn(`brand/krizaka/${kind}-${theme}-1024.png`)
169
340
  });
170
341
  var TONES = [1, 2, 3, 4, 5, 6];
171
- var avatarAlt = (kind, n) => kind === "person" ? { fr: `Photo de profil par d\xE9faut : silhouette, teinte ${n}`, en: `Default profile picture: silhouette, tone ${n}` } : { fr: `Photo de profil par d\xE9faut : disque uni, teinte ${n}`, en: `Default profile picture: plain disc, tone ${n}` };
342
+ var avatarAlt = (kind, n) => kind === "person" ? {
343
+ fr: `Photo de profil par d\xE9faut : silhouette, teinte ${n}`,
344
+ en: `Default profile picture: silhouette, tone ${n}`
345
+ } : {
346
+ fr: `Photo de profil par d\xE9faut : disque uni, teinte ${n}`,
347
+ en: `Default profile picture: plain disc, tone ${n}`
348
+ };
172
349
  var defaults2 = ["person", "plain"].flatMap(
173
350
  (kind) => TONES.map((n) => ({
174
351
  id: `${kind}-${n}`,
@@ -179,11 +356,35 @@ var defaults2 = ["person", "plain"].flatMap(
179
356
  alt: avatarAlt(kind, n)
180
357
  }))
181
358
  );
359
+ var GITHUB = "https://github.com/krizaka";
360
+ var gh = (repo) => `${GITHUB}/${repo}`;
361
+ var FAMILY_ROWS = [
362
+ ["krizaka", "Krizaka", "Krizaka", "krizaka", "released", "https://www.krizaka.com", gh("krizaka-com")],
363
+ ["blog", "Blog", "Blog", "krizaka", "released", "https://blog.krizaka.com", gh("krizaka-blog")],
364
+ ["orazaka", "Orazaka", "Orazaka", "products", "development", "https://www.orazaka.com", gh("orazaka")],
365
+ ["yomizaka", "Yomizaka", "Yomizaka", "products", "development", "https://www.yomizaka.com", gh("yomizaka")],
366
+ ["akinaza", "Akinaza", "Akinaza", "products", "development", "https://www.akinaza.com", gh("akinaza")],
367
+ ["ui", "Krizaka UI", "UI", "open-source", "released", "https://ui.krizaka.com", gh("krizaka-ui")],
368
+ ["java", "Krizaka Java", "Java", "open-source", "released", "https://java.krizaka.com", gh("krizaka-build")],
369
+ ["ts", "Krizaka TypeScript", "TypeScript", "open-source", "released", "https://ts.krizaka.com", gh("krizaka-ts")],
370
+ ["lab", "Krizaka Lab", "Lab", "open-source", "development", "https://lab.krizaka.com", gh("krizaka-lab")],
371
+ ["skills", "Krizaka Skills", "Skills", "open-source", "released", gh("krizaka-skills"), gh("krizaka-skills")],
372
+ ["github", "GitHub", "GitHub", "github", "released", GITHUB, null]
373
+ ];
374
+ var family = FAMILY_ROWS.map(([id, name, short, group, status, url, repo]) => ({
375
+ id,
376
+ name,
377
+ short,
378
+ group,
379
+ status,
380
+ url,
381
+ repo
382
+ }));
182
383
  var org = {
183
384
  $schema: ORG_SCHEMA_URL,
184
385
  schemaVersion: 2,
185
386
  version: package_default.version,
186
- updatedAt: "2026-10-26",
387
+ updatedAt: "2026-10-30",
187
388
  company: {
188
389
  legalName: "Technologies Krizaka Inc.",
189
390
  tradeName: "Krizaka",
@@ -210,27 +411,57 @@ var org = {
210
411
  },
211
412
  defaults,
212
413
  products: [
213
- { id: "orazaka", name: "Orazaka", status: "devPreview", url: "https://dev.orazaka.com", repo: "https://github.com/krizaka/orazaka" },
214
- { id: "yomizaka", name: "Yomizaka", status: "development", url: "https://dev.yomizaka.com", repo: "https://github.com/krizaka/yomizaka" },
215
- { id: "akinaza", name: "Akinaza", status: "development", url: "https://dev.akinaza.com", repo: "https://github.com/krizaka/akinaza" }
414
+ {
415
+ id: "orazaka",
416
+ name: "Orazaka",
417
+ status: "development",
418
+ url: "https://www.orazaka.com",
419
+ repo: "https://github.com/krizaka/orazaka"
420
+ },
421
+ {
422
+ id: "yomizaka",
423
+ name: "Yomizaka",
424
+ status: "development",
425
+ url: "https://www.yomizaka.com",
426
+ repo: "https://github.com/krizaka/yomizaka"
427
+ },
428
+ {
429
+ id: "akinaza",
430
+ name: "Akinaza",
431
+ status: "development",
432
+ url: "https://www.akinaza.com",
433
+ repo: "https://github.com/krizaka/akinaza"
434
+ }
216
435
  ],
217
436
  sites: [
218
437
  { id: "www", name: "krizaka.com", url: "https://www.krizaka.com" },
219
438
  { id: "ui", name: "Krizaka UI", url: "https://ui.krizaka.com" },
220
439
  { id: "java", name: "Krizaka Java", url: "https://java.krizaka.com" },
221
- { id: "ts", name: "Krizaka TS", url: "https://ts.krizaka.com" },
222
- { id: "motion", name: "Krizaka Motion", url: "https://motion.krizaka.com" },
440
+ { id: "ts", name: "Krizaka TypeScript", url: "https://ts.krizaka.com" },
441
+ { id: "motion", name: "Krizaka Lab", url: "https://lab.krizaka.com" },
223
442
  { id: "blog", name: "Blog", url: "https://blog.krizaka.com" }
224
443
  ],
444
+ family,
225
445
  contact: {
226
446
  page: { fr: "https://www.krizaka.com/fr/contact", en: "https://www.krizaka.com/en/contact" },
227
447
  email: null
228
448
  },
229
449
  footer: {
230
- line: { fr: "Une entreprise de Technologies Krizaka \xB7 Fait \xE0 Montr\xE9al", en: "A Technologies Krizaka company \xB7 Made in Montr\xE9al" },
450
+ line: {
451
+ fr: "Une entreprise de Technologies Krizaka \xB7 Fait \xE0 Montr\xE9al",
452
+ en: "A Technologies Krizaka company \xB7 Made in Montr\xE9al"
453
+ },
231
454
  legal: [
232
- { id: "privacy", label: { fr: "Confidentialit\xE9", en: "Privacy" }, url: { fr: "https://www.krizaka.com/fr/privacy", en: "https://www.krizaka.com/en/privacy" } },
233
- { id: "terms", label: { fr: "Conditions", en: "Terms" }, url: { fr: "https://www.krizaka.com/fr/terms", en: "https://www.krizaka.com/en/terms" } }
455
+ {
456
+ id: "privacy",
457
+ label: { fr: "Confidentialit\xE9", en: "Privacy" },
458
+ url: { fr: "https://www.krizaka.com/fr/privacy", en: "https://www.krizaka.com/en/privacy" }
459
+ },
460
+ {
461
+ id: "terms",
462
+ label: { fr: "Conditions", en: "Terms" },
463
+ url: { fr: "https://www.krizaka.com/fr/terms", en: "https://www.krizaka.com/en/terms" }
464
+ }
234
465
  ]
235
466
  }
236
467
  };
@@ -258,28 +489,159 @@ var apps = {
258
489
  var CAST_VERSION = 1;
259
490
  var CAST = [
260
491
  // The same three people as the deployed QA accounts (Eric, Mira, Camille) in each product, so a laptop and the dev deployment hold the same names.
261
- { id: "eric", product: "yomizaka", firstName: "\xC9ric", displayName: "\xC9ric Tremblay", role: "member", locale: "fr", avatar: "community-lead", workspace: "rosemont-villeray" },
262
- { id: "mira", product: "yomizaka", firstName: "Mira", displayName: "Mira Haddad", role: "admin", locale: "fr", avatar: "ai-builder", workspace: "administration" },
263
- { id: "camille", product: "yomizaka", firstName: "Camille", displayName: "Camille Tremblay", role: "member", locale: "fr", avatar: "visual-artist", workspace: "rosemont-villeray" },
492
+ {
493
+ id: "eric",
494
+ product: "yomizaka",
495
+ firstName: "\xC9ric",
496
+ displayName: "\xC9ric Tremblay",
497
+ role: "member",
498
+ locale: "fr",
499
+ avatar: "community-lead",
500
+ workspace: "rosemont-villeray"
501
+ },
502
+ {
503
+ id: "mira",
504
+ product: "yomizaka",
505
+ firstName: "Mira",
506
+ displayName: "Mira Haddad",
507
+ role: "admin",
508
+ locale: "fr",
509
+ avatar: "ai-builder",
510
+ workspace: "administration"
511
+ },
512
+ {
513
+ id: "camille",
514
+ product: "yomizaka",
515
+ firstName: "Camille",
516
+ displayName: "Camille Tremblay",
517
+ role: "member",
518
+ locale: "fr",
519
+ avatar: "visual-artist",
520
+ workspace: "rosemont-villeray"
521
+ },
264
522
  // Orazaka: the accounts already deployed on dev. Éric is the user (ORAZAKA_USER_*, APP_QA_ORAZAKA_PERSONA_*), Mira the administrator
265
523
  // (ORAZAKA_ADMIN_*, APP_QA_ORAZAKA_MIRA_*), Krizaka the company as an SME customer (APP_QA_ORAZAKA_KRIZAKA_*). The greeting reads the name: never « qa_user ».
266
- { id: "eric", product: "orazaka", firstName: "\xC9ric", displayName: "\xC9ric Tremblay", role: "member", locale: "fr", avatar: "community-lead", workspace: "demo" },
267
- { id: "mira", product: "orazaka", firstName: "Mira", displayName: "Mira Haddad", role: "admin", locale: "fr", avatar: "ai-builder", workspace: "administration" },
268
- { id: "krizaka", product: "orazaka", firstName: "Krizaka", displayName: "Krizaka", role: "member", locale: "fr", avatar: "tech-architect", workspace: "demo" },
524
+ {
525
+ id: "eric",
526
+ product: "orazaka",
527
+ firstName: "\xC9ric",
528
+ displayName: "\xC9ric Tremblay",
529
+ role: "member",
530
+ locale: "fr",
531
+ avatar: "community-lead",
532
+ workspace: "demo"
533
+ },
534
+ {
535
+ id: "mira",
536
+ product: "orazaka",
537
+ firstName: "Mira",
538
+ displayName: "Mira Haddad",
539
+ role: "admin",
540
+ locale: "fr",
541
+ avatar: "ai-builder",
542
+ workspace: "administration"
543
+ },
544
+ {
545
+ id: "krizaka",
546
+ product: "orazaka",
547
+ firstName: "Krizaka",
548
+ displayName: "Krizaka",
549
+ role: "member",
550
+ locale: "fr",
551
+ avatar: "tech-architect",
552
+ workspace: "demo"
553
+ },
269
554
  // Akinaza: Éric owns the Krizaka studio, Léa is the Saint-Henri walker, Camille is her first client, Mira administers.
270
- { id: "eric", product: "akinaza", firstName: "\xC9ric", displayName: "\xC9ric Tremblay", role: "owner", locale: "fr", avatar: "community-lead", banner: "creator-loft-studio", workspace: "krizaka-studio" },
271
- { id: "mira", product: "akinaza", firstName: "Mira", displayName: "Mira Haddad", role: "admin", locale: "fr", avatar: "ai-builder", workspace: "administration" },
272
- { id: "lea", product: "akinaza", firstName: "L\xE9a", displayName: "L\xE9a Beaulieu", role: "owner", locale: "fr", avatar: "studio-maker", banner: "cafe-maker-studio", workspace: "saint-henri" },
273
- { id: "camille", product: "akinaza", firstName: "Camille", displayName: "Camille Tremblay", role: "client", locale: "fr", avatar: "visual-artist", workspace: "saint-henri" },
274
- { id: "jordan", product: "akinaza", firstName: "Jordan", displayName: "Jordan Lee", role: "client", locale: "en", avatar: "tech-architect", workspace: "saint-henri" },
275
- { id: "nadia", product: "akinaza", firstName: "Nadia", displayName: "Nadia Benali", role: "client", locale: "fr", avatar: "digital-creator", workspace: "saint-henri" },
276
- { id: "etienne", product: "akinaza", firstName: "\xC9tienne", displayName: "\xC9tienne Gagnon", role: "client", locale: "fr", avatar: "boom-bap", workspace: "saint-henri" },
277
- { id: "sofia", product: "akinaza", firstName: "Sofia", displayName: "Sofia Rossi", role: "client", locale: "en", avatar: "salon-tattoo-maker", workspace: "saint-henri" }
555
+ {
556
+ id: "eric",
557
+ product: "akinaza",
558
+ firstName: "\xC9ric",
559
+ displayName: "\xC9ric Tremblay",
560
+ role: "owner",
561
+ locale: "fr",
562
+ avatar: "community-lead",
563
+ banner: "creator-loft-studio",
564
+ workspace: "krizaka-studio"
565
+ },
566
+ {
567
+ id: "mira",
568
+ product: "akinaza",
569
+ firstName: "Mira",
570
+ displayName: "Mira Haddad",
571
+ role: "admin",
572
+ locale: "fr",
573
+ avatar: "ai-builder",
574
+ workspace: "administration"
575
+ },
576
+ {
577
+ id: "lea",
578
+ product: "akinaza",
579
+ firstName: "L\xE9a",
580
+ displayName: "L\xE9a Beaulieu",
581
+ role: "owner",
582
+ locale: "fr",
583
+ avatar: "studio-maker",
584
+ banner: "cafe-maker-studio",
585
+ workspace: "saint-henri"
586
+ },
587
+ {
588
+ id: "camille",
589
+ product: "akinaza",
590
+ firstName: "Camille",
591
+ displayName: "Camille Tremblay",
592
+ role: "client",
593
+ locale: "fr",
594
+ avatar: "visual-artist",
595
+ workspace: "saint-henri"
596
+ },
597
+ {
598
+ id: "jordan",
599
+ product: "akinaza",
600
+ firstName: "Jordan",
601
+ displayName: "Jordan Lee",
602
+ role: "client",
603
+ locale: "en",
604
+ avatar: "tech-architect",
605
+ workspace: "saint-henri"
606
+ },
607
+ {
608
+ id: "nadia",
609
+ product: "akinaza",
610
+ firstName: "Nadia",
611
+ displayName: "Nadia Benali",
612
+ role: "client",
613
+ locale: "fr",
614
+ avatar: "digital-creator",
615
+ workspace: "saint-henri"
616
+ },
617
+ {
618
+ id: "etienne",
619
+ product: "akinaza",
620
+ firstName: "\xC9tienne",
621
+ displayName: "\xC9tienne Gagnon",
622
+ role: "client",
623
+ locale: "fr",
624
+ avatar: "boom-bap",
625
+ workspace: "saint-henri"
626
+ },
627
+ {
628
+ id: "sofia",
629
+ product: "akinaza",
630
+ firstName: "Sofia",
631
+ displayName: "Sofia Rossi",
632
+ role: "client",
633
+ locale: "en",
634
+ avatar: "salon-tattoo-maker",
635
+ workspace: "saint-henri"
636
+ }
278
637
  ];
279
638
  var castOf = (product) => CAST.filter((p) => p.product === product);
280
639
  function persona(product, id) {
281
640
  const found = CAST.find((p) => p.product === product && p.id === id);
282
- if (!found) throw new Error(`cast: no persona "${id}" in ${product} (known: ${castOf(product).map((p) => p.id).join(", ")})`);
641
+ if (!found)
642
+ throw new Error(
643
+ `cast: no persona "${id}" in ${product} (known: ${castOf(product).map((p) => p.id).join(", ")})`
644
+ );
283
645
  return found;
284
646
  }
285
647
  function personaByRole(product, role) {
@@ -314,7 +676,12 @@ var mark2 = {
314
676
  properties: { svg: httpsUrl, png64: httpsUrl, png256: httpsUrl, png512: httpsUrl, png1024: httpsUrl }
315
677
  };
316
678
  var slug = { type: "string", pattern: "^[a-z0-9]+(-[a-z0-9]+)*$" };
317
- var themed = { type: "object", additionalProperties: false, required: ["dark", "light"], properties: { dark: mark2, light: mark2 } };
679
+ var themed = {
680
+ type: "object",
681
+ additionalProperties: false,
682
+ required: ["dark", "light"],
683
+ properties: { dark: mark2, light: mark2 }
684
+ };
318
685
  var date = { type: "string", pattern: "^\\d{4}-\\d{2}-\\d{2}$" };
319
686
  var semver = { type: "string", pattern: "^\\d+\\.\\d+\\.\\d+$" };
320
687
  var defaultItems = {
@@ -333,7 +700,15 @@ var defaultItems = {
333
700
  type: "object",
334
701
  additionalProperties: false,
335
702
  required: ["webp"],
336
- properties: { svg: httpsUrl, webp: { type: "object", minProperties: 1, propertyNames: { pattern: "^\\d+$" }, additionalProperties: httpsUrl } }
703
+ properties: {
704
+ svg: httpsUrl,
705
+ webp: {
706
+ type: "object",
707
+ minProperties: 1,
708
+ propertyNames: { pattern: "^\\d+$" },
709
+ additionalProperties: httpsUrl
710
+ }
711
+ }
337
712
  }
338
713
  }
339
714
  }
@@ -344,7 +719,21 @@ var orgSchema = {
344
719
  title: "Krizaka organisation \u2014 public facts",
345
720
  type: "object",
346
721
  additionalProperties: false,
347
- required: ["$schema", "schemaVersion", "version", "updatedAt", "company", "brand", "people", "defaults", "products", "sites", "contact", "footer"],
722
+ required: [
723
+ "$schema",
724
+ "schemaVersion",
725
+ "version",
726
+ "updatedAt",
727
+ "company",
728
+ "brand",
729
+ "people",
730
+ "defaults",
731
+ "products",
732
+ "sites",
733
+ "family",
734
+ "contact",
735
+ "footer"
736
+ ],
348
737
  properties: {
349
738
  $schema: { type: "string" },
350
739
  schemaVersion: { enum: [1, 2] },
@@ -369,7 +758,15 @@ var orgSchema = {
369
758
  type: "object",
370
759
  additionalProperties: false,
371
760
  required: ["name", "logo", "mark", "favicon", "appleTouchIcon", "socialPreview", "manifest"],
372
- properties: { name: { type: "string", minLength: 1 }, logo: themed, mark: themed, favicon: httpsUrl, appleTouchIcon: httpsUrl, socialPreview: httpsUrl, manifest: httpsUrl }
761
+ properties: {
762
+ name: { type: "string", minLength: 1 },
763
+ logo: themed,
764
+ mark: themed,
765
+ favicon: httpsUrl,
766
+ appleTouchIcon: httpsUrl,
767
+ socialPreview: httpsUrl,
768
+ manifest: httpsUrl
769
+ }
373
770
  },
374
771
  people: {
375
772
  type: "object",
@@ -382,12 +779,24 @@ var orgSchema = {
382
779
  type: "object",
383
780
  additionalProperties: false,
384
781
  required: ["id", "kind", "svg", "webp256", "webp512", "alt"],
385
- properties: { id: slug, kind: { enum: ["person", "plain"] }, svg: httpsUrl, webp256: httpsUrl, webp512: httpsUrl, alt: localized }
782
+ properties: {
783
+ id: slug,
784
+ kind: { enum: ["person", "plain"] },
785
+ svg: httpsUrl,
786
+ webp256: httpsUrl,
787
+ webp512: httpsUrl,
788
+ alt: localized
789
+ }
386
790
  }
387
791
  },
388
792
  banners: {
389
793
  type: "array",
390
- items: { type: "object", additionalProperties: false, required: ["id", "url", "alt"], properties: { id: slug, url: httpsUrl, alt: localized } }
794
+ items: {
795
+ type: "object",
796
+ additionalProperties: false,
797
+ required: ["id", "url", "alt"],
798
+ properties: { id: slug, url: httpsUrl, alt: localized }
799
+ }
391
800
  }
392
801
  }
393
802
  },
@@ -398,12 +807,19 @@ var orgSchema = {
398
807
  properties: {
399
808
  version: { type: "string", pattern: "^v\\d+$" },
400
809
  base: httpsUrl,
401
- rule: { type: "object", additionalProperties: false, required: ["pick", "description"], properties: { pick: { const: "fnv1a32-modulo" }, description: { type: "string", minLength: 1 } } },
810
+ rule: {
811
+ type: "object",
812
+ additionalProperties: false,
813
+ required: ["pick", "description"],
814
+ properties: { pick: { const: "fnv1a32-modulo" }, description: { type: "string", minLength: 1 } }
815
+ },
402
816
  kinds: {
403
817
  type: "object",
404
818
  additionalProperties: false,
405
819
  required: ["person", "folder", "organisation", "shop", "banner"],
406
- properties: Object.fromEntries(["person", "folder", "organisation", "shop", "banner"].map((kind) => [kind, defaultItems]))
820
+ properties: Object.fromEntries(
821
+ ["person", "folder", "organisation", "shop", "banner"].map((kind) => [kind, defaultItems])
822
+ )
407
823
  }
408
824
  }
409
825
  },
@@ -414,20 +830,54 @@ var orgSchema = {
414
830
  type: "object",
415
831
  additionalProperties: false,
416
832
  required: ["id", "name", "status", "url", "repo"],
417
- properties: { id: slug, name: { type: "string", minLength: 1 }, status: { enum: ["development", "devPreview"] }, url: httpsUrl, repo: httpsUrl }
833
+ properties: {
834
+ id: slug,
835
+ name: { type: "string", minLength: 1 },
836
+ status: { enum: ["development", "devPreview"] },
837
+ url: httpsUrl,
838
+ repo: httpsUrl
839
+ }
418
840
  }
419
841
  },
420
842
  sites: {
421
843
  type: "array",
422
844
  minItems: 1,
423
- items: { type: "object", additionalProperties: false, required: ["id", "name", "url"], properties: { id: slug, name: { type: "string", minLength: 1 }, url: httpsUrl } }
845
+ items: {
846
+ type: "object",
847
+ additionalProperties: false,
848
+ required: ["id", "name", "url"],
849
+ properties: { id: slug, name: { type: "string", minLength: 1 }, url: httpsUrl }
850
+ }
851
+ },
852
+ family: {
853
+ type: "array",
854
+ minItems: 1,
855
+ items: {
856
+ type: "object",
857
+ additionalProperties: false,
858
+ required: ["id", "name", "short", "group", "status", "url", "repo"],
859
+ properties: {
860
+ id: slug,
861
+ name: { type: "string", minLength: 1 },
862
+ short: { type: "string", minLength: 1 },
863
+ group: { enum: ["krizaka", "products", "open-source", "github"] },
864
+ status: { enum: ["released", "development"] },
865
+ url: httpsUrl,
866
+ repo: { anyOf: [httpsUrl, { type: "null" }] }
867
+ }
868
+ }
424
869
  },
425
870
  contact: {
426
871
  type: "object",
427
872
  additionalProperties: false,
428
873
  required: ["page", "email"],
429
874
  properties: {
430
- page: { type: "object", additionalProperties: false, required: ["fr", "en"], properties: { fr: httpsUrl, en: httpsUrl } },
875
+ page: {
876
+ type: "object",
877
+ additionalProperties: false,
878
+ required: ["fr", "en"],
879
+ properties: { fr: httpsUrl, en: httpsUrl }
880
+ },
431
881
  email: { type: ["string", "null"], format: "email" }
432
882
  }
433
883
  },
@@ -444,7 +894,16 @@ var orgSchema = {
444
894
  type: "object",
445
895
  additionalProperties: false,
446
896
  required: ["id", "label", "url"],
447
- properties: { id: { enum: ["privacy", "terms"] }, label: localized, url: { type: "object", additionalProperties: false, required: ["fr", "en"], properties: { fr: httpsUrl, en: httpsUrl } } }
897
+ properties: {
898
+ id: { enum: ["privacy", "terms"] },
899
+ label: localized,
900
+ url: {
901
+ type: "object",
902
+ additionalProperties: false,
903
+ required: ["fr", "en"],
904
+ properties: { fr: httpsUrl, en: httpsUrl }
905
+ }
906
+ }
448
907
  }
449
908
  }
450
909
  }
@@ -477,6 +936,12 @@ var appSchema = {
477
936
  // src/index.ts
478
937
  var localized2 = (text, locale) => locale === "fr" ? text.fr : text.en;
479
938
  var footerLine = (locale) => localized2(org.footer.line, locale);
939
+ var familyEntry = (id) => {
940
+ const entry = org.family.find((e) => e.id === id);
941
+ if (!entry) throw new Error(`Unknown Krizaka family entry "${id}".`);
942
+ return entry;
943
+ };
944
+ var familyName = (id) => familyEntry(id).name;
480
945
  export {
481
946
  APP_SCHEMA_URL,
482
947
  CAST,
@@ -492,6 +957,8 @@ export {
492
957
  defaultFor,
493
958
  defaultUrl,
494
959
  defaults,
960
+ familyEntry,
961
+ familyName,
495
962
  fetchDefaults,
496
963
  footerLine,
497
964
  listDefaults,