@takuhon/core 0.3.0 → 0.5.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.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  var $schema = "https://json-schema.org/draft/2020-12/schema";
2
- var $id = "https://takuhon.example/schemas/0.2.0/takuhon.schema.json";
2
+ var $id = "https://takuhon.example/schemas/0.4.0/takuhon.schema.json";
3
3
  var title = "Takuhon Profile";
4
4
  var description = "Portable profile data format consumed by @takuhon/core. The canonical contract for profile content authored as takuhon.json.";
5
5
  var type = "object";
@@ -115,6 +115,20 @@ var properties = {
115
115
  $ref: "#/$defs/Patent"
116
116
  }
117
117
  },
118
+ testScores: {
119
+ type: "array",
120
+ maxItems: 30,
121
+ items: {
122
+ $ref: "#/$defs/TestScore"
123
+ }
124
+ },
125
+ recommendations: {
126
+ type: "array",
127
+ maxItems: 50,
128
+ items: {
129
+ $ref: "#/$defs/Recommendation"
130
+ }
131
+ },
118
132
  contact: {
119
133
  $ref: "#/$defs/Contact"
120
134
  },
@@ -599,7 +613,7 @@ var $defs = {
599
613
  MetaPrivacy: {
600
614
  type: "object",
601
615
  additionalProperties: true,
602
- description: "Opt-out flags that strip personally identifying fields from public API output (GET /api/profile, /api/jsonld, /takuhon.json). Admin endpoints (PUT /api/admin/*, GET /api/export) ignore these flags. Privacy-by-default: omitting the object or individual flags is equivalent to true.",
616
+ description: "Opt-out flags that strip personally identifying fields from public API output (GET /api/profile, /api/jsonld, /takuhon.json). Admin endpoints (PUT /api/admin/*, GET /api/admin/export) ignore these flags. Privacy-by-default: omitting the object or individual flags is equivalent to true.",
603
617
  properties: {
604
618
  hideCredentialIds: {
605
619
  type: "boolean",
@@ -1034,6 +1048,109 @@ var $defs = {
1034
1048
  minimum: 0
1035
1049
  }
1036
1050
  }
1051
+ },
1052
+ TestScore: {
1053
+ type: "object",
1054
+ additionalProperties: true,
1055
+ required: [
1056
+ "id",
1057
+ "title",
1058
+ "score",
1059
+ "date"
1060
+ ],
1061
+ properties: {
1062
+ id: {
1063
+ $ref: "#/$defs/Slug"
1064
+ },
1065
+ title: {
1066
+ $ref: "#/$defs/LocalizedTitle"
1067
+ },
1068
+ score: {
1069
+ type: "string",
1070
+ minLength: 1,
1071
+ maxLength: 50,
1072
+ description: "Free-form score string (e.g. '112 / 120', '330', 'N1 Pass', or a percentile). The validator does not interpret its contents."
1073
+ },
1074
+ date: {
1075
+ $ref: "#/$defs/YearMonth"
1076
+ },
1077
+ relatedEducationId: {
1078
+ $ref: "#/$defs/Slug",
1079
+ description: "Optional reference to an education[].id (e.g. for a university course exam)."
1080
+ },
1081
+ description: {
1082
+ $ref: "#/$defs/LocalizedBody"
1083
+ },
1084
+ url: {
1085
+ $ref: "#/$defs/Url"
1086
+ },
1087
+ order: {
1088
+ type: "integer",
1089
+ minimum: 0
1090
+ }
1091
+ }
1092
+ },
1093
+ Recommendation: {
1094
+ type: "object",
1095
+ additionalProperties: true,
1096
+ required: [
1097
+ "id",
1098
+ "body",
1099
+ "author"
1100
+ ],
1101
+ properties: {
1102
+ id: {
1103
+ $ref: "#/$defs/Slug"
1104
+ },
1105
+ body: {
1106
+ $ref: "#/$defs/LocalizedBody"
1107
+ },
1108
+ author: {
1109
+ $ref: "#/$defs/RecommendationAuthor"
1110
+ },
1111
+ relationship: {
1112
+ $ref: "#/$defs/LocalizedTitle",
1113
+ description: "How the recommender relates to the profile owner (e.g. 'managed directly', 'worked together')."
1114
+ },
1115
+ date: {
1116
+ $ref: "#/$defs/YearMonth"
1117
+ },
1118
+ relatedCareerId: {
1119
+ $ref: "#/$defs/Slug",
1120
+ description: "Optional reference to a careers[].id (the position the recommendation pertains to)."
1121
+ },
1122
+ relatedEducationId: {
1123
+ $ref: "#/$defs/Slug",
1124
+ description: "Optional reference to an education[].id (e.g. a recommendation from a professor)."
1125
+ },
1126
+ order: {
1127
+ type: "integer",
1128
+ minimum: 0
1129
+ }
1130
+ }
1131
+ },
1132
+ RecommendationAuthor: {
1133
+ type: "object",
1134
+ additionalProperties: true,
1135
+ required: [
1136
+ "name"
1137
+ ],
1138
+ properties: {
1139
+ name: {
1140
+ type: "string",
1141
+ minLength: 1,
1142
+ maxLength: 100,
1143
+ description: "Recommender's name, in its original script. Owner-curated; takuhon does not verify it."
1144
+ },
1145
+ headline: {
1146
+ $ref: "#/$defs/LocalizedTitle",
1147
+ description: "Recommender's title / role / organization at the time of the recommendation."
1148
+ },
1149
+ url: {
1150
+ $ref: "#/$defs/Url",
1151
+ description: "Link to the recommender's profile, for external verification by the reader."
1152
+ }
1153
+ }
1037
1154
  }
1038
1155
  };
1039
1156
  var schemaJson = {
@@ -1165,6 +1282,20 @@ declare const schema: {
1165
1282
  $ref: string;
1166
1283
  };
1167
1284
  };
1285
+ testScores: {
1286
+ type: string;
1287
+ maxItems: number;
1288
+ items: {
1289
+ $ref: string;
1290
+ };
1291
+ };
1292
+ recommendations: {
1293
+ type: string;
1294
+ maxItems: number;
1295
+ items: {
1296
+ $ref: string;
1297
+ };
1298
+ };
1168
1299
  contact: {
1169
1300
  $ref: string;
1170
1301
  };
@@ -1981,6 +2112,98 @@ declare const schema: {
1981
2112
  };
1982
2113
  };
1983
2114
  };
2115
+ TestScore: {
2116
+ type: string;
2117
+ additionalProperties: boolean;
2118
+ required: string[];
2119
+ properties: {
2120
+ id: {
2121
+ $ref: string;
2122
+ };
2123
+ title: {
2124
+ $ref: string;
2125
+ };
2126
+ score: {
2127
+ type: string;
2128
+ minLength: number;
2129
+ maxLength: number;
2130
+ description: string;
2131
+ };
2132
+ date: {
2133
+ $ref: string;
2134
+ };
2135
+ relatedEducationId: {
2136
+ $ref: string;
2137
+ description: string;
2138
+ };
2139
+ description: {
2140
+ $ref: string;
2141
+ };
2142
+ url: {
2143
+ $ref: string;
2144
+ };
2145
+ order: {
2146
+ type: string;
2147
+ minimum: number;
2148
+ };
2149
+ };
2150
+ };
2151
+ Recommendation: {
2152
+ type: string;
2153
+ additionalProperties: boolean;
2154
+ required: string[];
2155
+ properties: {
2156
+ id: {
2157
+ $ref: string;
2158
+ };
2159
+ body: {
2160
+ $ref: string;
2161
+ };
2162
+ author: {
2163
+ $ref: string;
2164
+ };
2165
+ relationship: {
2166
+ $ref: string;
2167
+ description: string;
2168
+ };
2169
+ date: {
2170
+ $ref: string;
2171
+ };
2172
+ relatedCareerId: {
2173
+ $ref: string;
2174
+ description: string;
2175
+ };
2176
+ relatedEducationId: {
2177
+ $ref: string;
2178
+ description: string;
2179
+ };
2180
+ order: {
2181
+ type: string;
2182
+ minimum: number;
2183
+ };
2184
+ };
2185
+ };
2186
+ RecommendationAuthor: {
2187
+ type: string;
2188
+ additionalProperties: boolean;
2189
+ required: string[];
2190
+ properties: {
2191
+ name: {
2192
+ type: string;
2193
+ minLength: number;
2194
+ maxLength: number;
2195
+ description: string;
2196
+ };
2197
+ headline: {
2198
+ $ref: string;
2199
+ description: string;
2200
+ };
2201
+ url: {
2202
+ $ref: string;
2203
+ description: string;
2204
+ };
2205
+ };
2206
+ };
1984
2207
  };
1985
2208
  };
1986
2209
  type Schema = typeof schemaJson;
@@ -2234,6 +2457,45 @@ interface Patent {
2234
2457
  coInventors?: string[];
2235
2458
  order?: number;
2236
2459
  }
2460
+ interface TestScore {
2461
+ id: Slug;
2462
+ title: LocalizedTitle;
2463
+ /**
2464
+ * Free-form score string (e.g. '112 / 120', '330', 'N1 Pass', a percentile).
2465
+ * Stored verbatim; the validator does not interpret its contents.
2466
+ */
2467
+ score: string;
2468
+ /** Test date (year-month). */
2469
+ date: YearMonth;
2470
+ /** Optional reference to an `education[].id` (e.g. for a university course exam). */
2471
+ relatedEducationId?: Slug;
2472
+ description?: LocalizedBody;
2473
+ url?: string;
2474
+ order?: number;
2475
+ }
2476
+ interface RecommendationAuthor {
2477
+ /** Recommender's name in its original script. Owner-curated; not verified by takuhon. */
2478
+ name: string;
2479
+ /** Recommender's title / role / organization at the time of the recommendation. */
2480
+ headline?: LocalizedTitle;
2481
+ /** Link to the recommender's profile, for external verification by the reader. */
2482
+ url?: string;
2483
+ }
2484
+ interface Recommendation {
2485
+ id: Slug;
2486
+ /** The recommendation text (testimonial body). */
2487
+ body: LocalizedBody;
2488
+ author: RecommendationAuthor;
2489
+ /** How the recommender relates to the profile owner (e.g. 'managed directly'). */
2490
+ relationship?: LocalizedTitle;
2491
+ /** When the recommendation was given (year-month). */
2492
+ date?: YearMonth;
2493
+ /** Optional reference to a `careers[].id` the recommendation pertains to. */
2494
+ relatedCareerId?: Slug;
2495
+ /** Optional reference to an `education[].id` the recommendation pertains to. */
2496
+ relatedEducationId?: Slug;
2497
+ order?: number;
2498
+ }
2237
2499
  interface Contact {
2238
2500
  email?: string;
2239
2501
  showEmail?: boolean;
@@ -2268,7 +2530,7 @@ interface ContentLicense {
2268
2530
  /**
2269
2531
  * Privacy opt-out flags that strip personally identifying fields from public
2270
2532
  * API output (`GET /api/profile`, `/api/jsonld`, `/takuhon.json`). Admin
2271
- * endpoints (`PUT /api/admin/*`, `GET /api/export`) ignore these flags.
2533
+ * endpoints (`PUT /api/admin/*`, `GET /api/admin/export`) ignore these flags.
2272
2534
  * Privacy-by-default: omitting the object or individual flags is equivalent
2273
2535
  * to `true`.
2274
2536
  */
@@ -2289,10 +2551,11 @@ interface Meta {
2289
2551
  /**
2290
2552
  * A complete takuhon profile document.
2291
2553
  *
2292
- * Schema-level, the nine new arrays from 0.2.0 (`certifications` through
2293
- * `patents`) are optional for 0.1.x back-compat. At the TypeScript layer they
2294
- * are typed as required because `validate()` and `normalize()` defensively
2295
- * coerce missing arrays to `[]` so downstream consumers never see `undefined`.
2554
+ * Schema-level, the nine arrays added in 0.2.0 (`certifications` through
2555
+ * `patents`), `testScores` (0.3.0), and `recommendations` (0.4.0) are optional
2556
+ * for back-compat with older documents. At the TypeScript layer they are typed
2557
+ * as required because `validate()` and `normalize()` defensively coerce missing
2558
+ * arrays to `[]` so downstream consumers never see `undefined`.
2296
2559
  */
2297
2560
  interface Takuhon {
2298
2561
  schemaVersion: string;
@@ -2310,6 +2573,8 @@ interface Takuhon {
2310
2573
  languages: Language[];
2311
2574
  courses: Course[];
2312
2575
  patents: Patent[];
2576
+ testScores: TestScore[];
2577
+ recommendations: Recommendation[];
2313
2578
  contact: Contact;
2314
2579
  settings: Settings;
2315
2580
  meta: Meta;
@@ -2496,6 +2761,34 @@ interface LocalizedPatent {
2496
2761
  coInventors?: string[];
2497
2762
  order?: number;
2498
2763
  }
2764
+ /** Test score with localized fields collapsed to single strings. */
2765
+ interface LocalizedTestScore {
2766
+ id: Slug;
2767
+ title: string;
2768
+ score: string;
2769
+ date: YearMonth;
2770
+ relatedEducationId?: Slug;
2771
+ description?: string;
2772
+ url?: string;
2773
+ order?: number;
2774
+ }
2775
+ /** Recommendation author with `headline` collapsed to a single string. */
2776
+ interface LocalizedRecommendationAuthor {
2777
+ name: string;
2778
+ headline?: string;
2779
+ url?: string;
2780
+ }
2781
+ /** Recommendation with localized fields collapsed to single strings. */
2782
+ interface LocalizedRecommendation {
2783
+ id: Slug;
2784
+ body: string;
2785
+ author: LocalizedRecommendationAuthor;
2786
+ relationship?: string;
2787
+ date?: YearMonth;
2788
+ relatedCareerId?: Slug;
2789
+ relatedEducationId?: Slug;
2790
+ order?: number;
2791
+ }
2499
2792
  /**
2500
2793
  * A takuhon document with every localized map flattened to a single string,
2501
2794
  * plus a `resolvedLocale` field recording which tag was actually used as the
@@ -2520,6 +2813,8 @@ interface LocalizedTakuhon {
2520
2813
  languages: LocalizedLanguage[];
2521
2814
  courses: LocalizedCourse[];
2522
2815
  patents: LocalizedPatent[];
2816
+ testScores: LocalizedTestScore[];
2817
+ recommendations: LocalizedRecommendation[];
2523
2818
  contact: Contact;
2524
2819
  settings: Settings;
2525
2820
  meta: Meta;
@@ -2561,7 +2856,7 @@ interface LocalizedTakuhon {
2561
2856
  * versions whose JSON Schema this package literally bundles, not the full
2562
2857
  * support window seen by end users.
2563
2858
  */
2564
- declare const SUPPORTED_SCHEMA_VERSIONS: readonly ["0.1.0", "0.2.0"];
2859
+ declare const SUPPORTED_SCHEMA_VERSIONS: readonly ["0.1.0", "0.2.0", "0.3.0", "0.4.0"];
2565
2860
  /**
2566
2861
  * A single validation failure.
2567
2862
  *
@@ -2760,7 +3055,7 @@ declare function generateJsonLd(data: LocalizedTakuhon): object[];
2760
3055
  * Structural alias of {@link Takuhon}: the transport form is the document
2761
3056
  * itself. A wrapping envelope (e.g. `{ format, version, data, hash }`) is
2762
3057
  * intentionally avoided in Phase 1 — adding one later would be a breaking
2763
- * change to the `GET /api/export` response shape and would require a major
3058
+ * change to the `GET /api/admin/export` response shape and would require a major
2764
3059
  * version bump of `@takuhon/core`.
2765
3060
  */
2766
3061
  type ExportedTakuhon = Takuhon;
@@ -2812,10 +3107,10 @@ declare function importTakuhon(data: ExportedTakuhon): Takuhon;
2812
3107
  * Forward migration entry point for takuhon documents.
2813
3108
  *
2814
3109
  * {@link migrateTakuhon} composes a chain of {@link Migration} entries from
2815
- * the registry (`./migrations`) and applies them in order. Phase 1 ships
2816
- * with an empty registry, so any non-identity migration currently throws
2817
- * {@link MigrationError}; the first concrete entry will land alongside
2818
- * the v0.2.0 schema bump.
3110
+ * the registry (`./migrations`) and applies them in order. The registry
3111
+ * currently ships the `0.1.0 0.2.0`, `0.2.0 0.3.0`, and `0.3.0 → 0.4.0`
3112
+ * forward migrations; a request whose source has no chain to the target
3113
+ * throws {@link MigrationError}.
2819
3114
  *
2820
3115
  * Scope (deliberately narrow, mirroring `export.ts`):
2821
3116
  * - Pure data transform — no I/O, no backup creation, no storage write.
@@ -3047,8 +3342,8 @@ declare class ConflictError extends StorageError {
3047
3342
  * {@link ExportedTakuhon} / {@link ImportError}: roundtrip-stable
3048
3343
  * serialisation for transport (file, API response, …).
3049
3344
  * - {@link migrateTakuhon} / {@link Migration} / {@link migrations} /
3050
- * {@link MigrationError}: forward-only migration registry. Empty in
3051
- * Phase 1; first entry lands with the v0.2.0 schema bump.
3345
+ * {@link MigrationError}: forward-only migration registry, chaining
3346
+ * `0.1.0 0.2.0 0.3.0 0.4.0`.
3052
3347
  * - Domain types: {@link Takuhon} and its constituent shapes (`Profile`,
3053
3348
  * `Settings`, `Career`, `Project`, `Link` discriminated union, etc.).
3054
3349
  */
@@ -3058,6 +3353,6 @@ declare class ConflictError extends StorageError {
3058
3353
  * A takuhon profile document's `schemaVersion` field must be migrate-compatible
3059
3354
  * with this version. See operational-lifecycle docs for the migration policy.
3060
3355
  */
3061
- declare const SCHEMA_VERSION = "0.2.0";
3356
+ declare const SCHEMA_VERSION = "0.4.0";
3062
3357
 
3063
- export { type Address, type AssetOptions, type AssetRecord, type Avatar, type Career, type Certification, ConflictError, type Contact, type ContentLicense, type ContentLicenseAttribution, type Course, type Education, type ExportOptions, type ExportedTakuhon, type Honor, ImportError, type Iso3166Alpha2, type IsoDateTime, type Language, type LanguageProficiency, type Link, type LinkBuiltin, type LinkCustom, type LinkType, type LocaleTag, type LocalizedAddress, type LocalizedAvatar, type LocalizedBody, type LocalizedCareer, type LocalizedCertification, type LocalizedCourse, type LocalizedEducation, type LocalizedHonor, type LocalizedLanguage, type LocalizedLink, type LocalizedLinkBuiltin, type LocalizedLinkCustom, type LocalizedMembership, type LocalizedPatent, type LocalizedProfile, type LocalizedProject, type LocalizedPublication, type LocalizedTakuhon, type LocalizedTitle, type LocalizedVolunteering, type Membership, type Meta, type MetaPrivacy, type Migration, MigrationError, type NormalizedTakuhon, NotFoundError, type Patent, type PatentStatus, type Profile, type Project, type Publication, SCHEMA_VERSION, SUPPORTED_SCHEMA_VERSIONS, type Schema, type Settings, type Skill, type Slug, StorageError, type Takuhon, type TakuhonAssetStorage, type TakuhonStorage, type ValidationError, type ValidationResult, type Volunteering, type YearMonth, exportTakuhon, generateJsonLd, generatePersonJsonLd, generateProfilePageJsonLd, importTakuhon, migrateTakuhon, migrations, normalize, resolveLocale, schema, validate };
3358
+ export { type Address, type AssetOptions, type AssetRecord, type Avatar, type Career, type Certification, ConflictError, type Contact, type ContentLicense, type ContentLicenseAttribution, type Course, type Education, type ExportOptions, type ExportedTakuhon, type Honor, ImportError, type Iso3166Alpha2, type IsoDateTime, type Language, type LanguageProficiency, type Link, type LinkBuiltin, type LinkCustom, type LinkType, type LocaleTag, type LocalizedAddress, type LocalizedAvatar, type LocalizedBody, type LocalizedCareer, type LocalizedCertification, type LocalizedCourse, type LocalizedEducation, type LocalizedHonor, type LocalizedLanguage, type LocalizedLink, type LocalizedLinkBuiltin, type LocalizedLinkCustom, type LocalizedMembership, type LocalizedPatent, type LocalizedProfile, type LocalizedProject, type LocalizedPublication, type LocalizedRecommendation, type LocalizedRecommendationAuthor, type LocalizedTakuhon, type LocalizedTestScore, type LocalizedTitle, type LocalizedVolunteering, type Membership, type Meta, type MetaPrivacy, type Migration, MigrationError, type NormalizedTakuhon, NotFoundError, type Patent, type PatentStatus, type Profile, type Project, type Publication, type Recommendation, type RecommendationAuthor, SCHEMA_VERSION, SUPPORTED_SCHEMA_VERSIONS, type Schema, type Settings, type Skill, type Slug, StorageError, type Takuhon, type TakuhonAssetStorage, type TakuhonStorage, type TestScore, type ValidationError, type ValidationResult, type Volunteering, type YearMonth, exportTakuhon, generateJsonLd, generatePersonJsonLd, generateProfilePageJsonLd, importTakuhon, migrateTakuhon, migrations, normalize, resolveLocale, schema, validate };