22/**
33 * Informational check – never fails.
44 *
5- * Compares the sample keys in the local .code-samples.meilisearch.yaml with
6- * each SDK's .code-samples.meilisearch.yaml (fetched from GitHub).
5+ * Collects code sample keys from doc imports that start with "CodeSamples"
6+ * (e.g. "import CodeSamplesTenantTokenGuideSearchSdk1 from '...'"), then
7+ * compares with each SDK's .code-samples.meilisearch.yaml (fetched from GitHub).
78 *
8- * Lists, per SDK, which local sample keys are missing on the SDK side.
9+ * Lists, per SDK, which imported sample keys are missing on the SDK side.
910 */
1011
1112import fs from 'fs' ;
@@ -26,14 +27,79 @@ const SDK = [
2627 { label : 'Dart' , project : 'meilisearch-dart' } ,
2728] ;
2829
29- const LOCAL_YAML = path . join (
30- process . cwd ( ) ,
31- '.code-samples.meilisearch.yaml'
32- ) ;
30+ /** Keys that are not expected in SDKs (e.g. no-SDK / curl-only samples). Never reported as missing. */
31+ const NOT_MISSING_IN_SDK = new Set ( [ 'tenant_token_guide_search_no_sdk_1' ] ) ;
32+
33+ /**
34+ * Convert a CodeSamples* component name to the YAML key (snake_case).
35+ * e.g. CodeSamplesTenantTokenGuideSearchSdk1 → tenant_token_guide_search_sdk_1
36+ * CodeSamplesCreateAKey1 → create_a_key_1
37+ */
38+ function componentNameToKey ( name ) {
39+ if ( ! name . startsWith ( 'CodeSamples' ) || name . length <= 'CodeSamples' . length ) {
40+ return null ;
41+ }
42+ const rest = name . slice ( 'CodeSamples' . length ) ;
43+ let out = '' ;
44+ for ( let i = 0 ; i < rest . length ; i ++ ) {
45+ const c = rest [ i ] ;
46+ const prev = i > 0 ? rest [ i - 1 ] : '' ;
47+ const prevLetter = ( prev >= 'a' && prev <= 'z' ) || ( prev >= 'A' && prev <= 'Z' ) ;
48+ const currUpper = c >= 'A' && c <= 'Z' ;
49+ const currDigit = c >= '0' && c <= '9' ;
50+ if ( i > 0 ) {
51+ if ( currUpper ) out += '_' ; // _ before every uppercase (e.g. CreateAKey → create_a_key)
52+ else if ( currDigit && prevLetter ) out += '_' ; // _ before digit after letter (e.g. Sdk1 → sdk_1)
53+ }
54+ out += c . toLowerCase ( ) ;
55+ }
56+ return out ;
57+ }
58+
59+ /**
60+ * Collect code sample keys from doc imports starting with "CodeSamples".
61+ * Scans .mdx and .md files for import lines and extracts component names.
62+ */
63+ function getCodeSampleKeysFromDocImports ( ) {
64+ const keys = new Set ( ) ;
65+ const componentRe = / C o d e S a m p l e s [ A - Z a - z 0 - 9 ] + / g;
66+ const root = process . cwd ( ) ;
67+ const skipDirs = new Set ( [ 'node_modules' , 'generated-code-samples' , '.git' ] ) ;
68+
69+ function walk ( dir ) {
70+ const entries = fs . readdirSync ( dir , { withFileTypes : true } ) ;
71+ for ( const e of entries ) {
72+ const full = path . join ( dir , e . name ) ;
73+ if ( e . isDirectory ( ) ) {
74+ if ( ! skipDirs . has ( e . name ) ) walk ( full ) ;
75+ continue ;
76+ }
77+ if ( ! e . name . endsWith ( '.mdx' ) && ! e . name . endsWith ( '.md' ) ) continue ;
78+ const content = fs . readFileSync ( full , 'utf-8' ) ;
79+ const lines = content . split ( '\n' ) ;
80+ for ( const line of lines ) {
81+ if ( ! line . includes ( 'import' ) || ! line . includes ( 'from' ) ) continue ;
82+ let m ;
83+ while ( ( m = componentRe . exec ( line ) ) !== null ) {
84+ const key = componentNameToKey ( m [ 0 ] ) ;
85+ if ( key ) keys . add ( key ) ;
86+ }
87+ }
88+ }
89+ }
3390
34- // Load local sample keys
35- const localSamples = yaml . load ( fs . readFileSync ( LOCAL_YAML , 'utf-8' ) ) ;
36- const localKeys = Object . keys ( localSamples ) . sort ( ) ;
91+ walk ( root ) ;
92+ return [ ...keys ] . sort ( ) ;
93+ }
94+
95+ const expectedKeys = getCodeSampleKeysFromDocImports ( ) ;
96+
97+ if ( expectedKeys . length === 0 ) {
98+ console . warn (
99+ '⚠ No "CodeSamples*" imports found in the documentation.'
100+ ) ;
101+ process . exit ( 0 ) ;
102+ }
37103
38104async function fetchYaml ( url ) {
39105 const res = await fetch ( url ) ;
@@ -42,7 +108,7 @@ async function fetchYaml(url) {
42108}
43109
44110console . log (
45- `Local .code-samples.meilisearch.yaml contains ${ localKeys . length } sample(s).\n`
111+ `Doc imports (CodeSamples*) reference ${ expectedKeys . length } code sample key (s).\n`
46112) ;
47113
48114// Per-sample tracking: which SDKs are missing each sample
@@ -62,7 +128,9 @@ for (const sdk of SDK) {
62128 }
63129
64130 const remoteKeys = new Set ( Object . keys ( remoteSamples ) ) ;
65- const missing = localKeys . filter ( ( key ) => ! remoteKeys . has ( key ) ) ;
131+ const missing = expectedKeys . filter (
132+ ( key ) => ! NOT_MISSING_IN_SDK . has ( key ) && ! remoteKeys . has ( key )
133+ ) ;
66134
67135 if ( missing . length > 0 ) {
68136 console . log (
0 commit comments