Menjaga konsistensi, kualitas, dan kepatuhan terhadap standar desain sangat penting bagi tim yang menggunakan API. Spesifikasi API seperti OpenAPI dan AsyncAPI menyediakan cetak biru (blueprint), tetapi memastikan cetak biru ini diikuti dengan benar di berbagai layanan dan tim bisa menjadi tantangan yang menakutkan. Di sinilah alat linting API berperan, dan Spectral menonjol sebagai opsi sumber terbuka yang fleksibel dan kuat. Ketika dikombinasikan dengan TypeScript, Spectral memberdayakan pengembang untuk membuat aturan kustom yang tangguh dan aman tipe (type-safe), meningkatkan tata kelola API ke tingkat yang baru.
Tutorial ini akan memandu Anda melalui proses memanfaatkan Spectral dengan TypeScript, mulai dari pengaturan awal hingga membuat logika validasi kustom yang canggih. Kita akan menjelajahi bagaimana TypeScript meningkatkan pengembangan aturan Spectral, menghasilkan solusi linting API yang lebih mudah dipelihara dan lebih andal.
Ingin platform Terintegrasi, All-in-One untuk Tim Pengembang Anda bekerja sama dengan produktivitas maksimum?
Apidog memenuhi semua permintaan Anda, dan menggantikan Postman dengan harga yang jauh lebih terjangkau!
Memahami Spectral: Penjaga Spesifikasi API Anda
Sebelum masuk ke integrasi TypeScript, mari kita pahami apa itu Spectral dan mengapa ini adalah alat yang berharga dalam toolkit pengembangan API Anda.
Spectral adalah linter JSON/YAML sumber terbuka dengan fokus utama pada format deskripsi API seperti OpenAPI (v2 dan v3) dan AsyncAPI. Tujuannya adalah untuk membantu menegakkan pedoman desain API, mendeteksi kesalahan umum, dan memastikan konsistensi di seluruh lanskap API Anda. Anggap saja sebagai ESLint atau TSLint, tetapi khusus untuk kontrak API Anda.
Manfaat Utama Menggunakan Spectral:
- Konsistensi: Menegakkan desain API yang seragam di seluruh tim dan proyek.
- Jaminan Kualitas: Menangkap kesalahan dan praktik buruk sejak dini dalam siklus pengembangan.
- Peningkatan Kolaborasi: Memberikan pemahaman bersama tentang standar API.
- Otomasi: Terintegrasi dengan mulus ke dalam pipeline CI/CD untuk validasi otomatis.
- Ekstensibilitas: Memungkinkan pembuatan aturan kustom yang disesuaikan dengan kebutuhan organisasi tertentu.
- Inti yang Agnostik Format: Meskipun unggul dalam OpenAPI/AsyncAPI, intinya dapat melakukan linting pada struktur JSON/YAML apa pun.
Spectral beroperasi berdasarkan ruleset. Ruleset adalah kumpulan aturan, di mana setiap aturan menargetkan bagian tertentu dari dokumen API Anda (menggunakan ekspresi JSONPath) dan menerapkan logika validasi. Spectral dilengkapi dengan ruleset bawaan (misalnya, spectral:oas
untuk standar OpenAPI), tetapi kekuatan sebenarnya terletak pada kemampuan untuk menentukan ruleset kustom.
Mengapa TypeScript untuk Aturan Kustom Spectral?
Meskipun ruleset Spectral dapat didefinisikan dalam YAML atau JavaScript (file .js
), menggunakan TypeScript untuk mengembangkan fungsi kustom menawarkan keuntungan signifikan:
- Keamanan Tipe (Type Safety): Pengetikan statis TypeScript menangkap kesalahan pada waktu kompilasi, mengurangi kejutan runtime dalam logika linting kustom Anda. Ini sangat penting untuk aturan yang kompleks.
- Pengalaman Pengembang yang Lebih Baik: Pelengkapan otomatis, kemampuan refactoring, dan navigasi kode yang lebih baik di IDE membuat penulisan dan pemeliharaan fungsi kustom menjadi lebih mudah.
- Keterbacaan dan Kemudahan Pemeliharaan yang Ditingkatkan: Tipe eksplisit membuat tujuan dan struktur fungsi kustom Anda lebih jelas, terutama untuk tim.
- Fitur JavaScript Modern: Manfaatkan fitur ES modern dengan percaya diri, karena TypeScript dikompilasi menjadi JavaScript yang kompatibel.
- Kemampuan Uji yang Lebih Baik: Pengetikan memudahkan penulisan unit test yang tangguh untuk fungsi Spectral kustom Anda.
Dengan menulis fungsi Spectral kustom Anda dalam TypeScript, Anda membawa ketelitian dan manfaat perkakas yang sama ke kode tata kelola API Anda seperti yang Anda lakukan pada kode aplikasi Anda.
Menyiapkan Lingkungan Spectral dan TypeScript Anda
Mari kita mulai dan siapkan alat yang diperlukan.
Prasyarat:
- Node.js dan npm (atau yarn): Spectral adalah aplikasi Node.js. Pastikan Anda telah menginstal Node.js (versi LTS direkomendasikan) dan npm (atau yarn).
- Proyek TypeScript: Anda memerlukan proyek TypeScript atau bersedia menyiapkannya.
Langkah-langkah Instalasi:
Pertama, Anda memerlukan CLI Spectral untuk menjalankan operasi linting dan menguji aturan Anda. Seringkali berguna untuk menginstalnya secara global atau menggunakan npx
.Bash
npm install -g @stoplight/spectral-cli
# atau
yarn global add @stoplight/spectral-cli
Untuk mengembangkan aturan kustom secara terprogram dan menggunakan pustaka inti Spectral dalam proyek TypeScript, instal paket Spectral yang diperlukan:Bashnpm install @stoplight/spectral-core @stoplight/spectral-functions @stoplight/spectral-rulesets typescript ts-node --save-dev # atau yarn add @stoplight/spectral-core @stoplight/spectral-functions @stoplight/spectral-rulesets typescript ts-node --dev
Mari kita uraikan paket-paket ini:
@stoplight/spectral-core
: Inti dari Spectral, berisi mesin linting.@stoplight/spectral-functions
: Menyediakan kumpulan fungsi bawaan yang dapat digunakan aturan Anda (misalnya,alphabetical
,defined
,pattern
,truthy
,xor
).@stoplight/spectral-rulesets
: Menawarkan ruleset yang telah ditentukan sebelumnya sepertispectral:oas
(untuk OpenAPI) danspectral:asyncapi
.typescript
: Kompilator TypeScript.ts-node
: Memungkinkan Anda menjalankan file TypeScript secara langsung tanpa pra-kompilasi, berguna untuk pengembangan.
Konfigurasi TypeScript:
Buat file tsconfig.json
di root proyek Anda jika Anda belum memilikinya. Konfigurasi dasar mungkin terlihat seperti ini:JSON
{
"compilerOptions": {
"target": "es2020", // Atau versi yang lebih baru
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"outDir": "./dist", // Direktori output untuk JavaScript yang dikompilasi
"rootDir": "./src", // Direktori sumber untuk file TypeScript Anda
"resolveJsonModule": true // Memungkinkan mengimpor file JSON
},
"include": ["src/**/*"],
"exclude": ["node_modules", "**/*.spec.ts"]
}
Sesuaikan outDir
dan rootDir
sesuai dengan struktur proyek Anda. Kita akan mengasumsikan fungsi TypeScript kustom Anda akan berada di direktori src
.
Konsep Inti Spectral: Aturan, Ruleset, dan Fungsi
Sebelum menulis fungsi TypeScript, mari kita perkuat pemahaman kita tentang komponen utama Spectral.
Aturan:
Sebuah aturan mendefinisikan pemeriksaan spesifik yang akan dilakukan. Properti utama dari sebuah aturan meliputi:
description
: Penjelasan aturan yang dapat dibaca manusia.message
: Pesan kesalahan atau peringatan yang ditampilkan jika aturan dilanggar. Dapat menyertakan placeholder seperti{{error}}
,{{path}}
,{{value}}
.severity
: Mendefinisikan dampak pelanggaran aturan. Dapat berupaerror
,warn
,info
, atauhint
.given
: Ekspresi JSONPath (atau array darinya) yang menentukan bagian mana dari dokumen yang berlaku untuk aturan.then
: Mendefinisikan tindakan yang akan diambil pada nilai yang ditargetkan. Ini biasanya melibatkan penerapan satu atau lebih fungsi.function
: Nama fungsi bawaan atau kustom yang akan dieksekusi.functionOptions
: Opsi untuk diteruskan ke fungsi.formats
: Array yang menentukan format dokumen mana yang berlaku untuk aturan ini (misalnya,oas3
,oas2
,asyncapi2
).
Ruleset:
Ruleset adalah file YAML atau JavaScript (misalnya, .spectral.yaml, .spectral.js, atau .spectral.ts ketika dikompilasi) yang mengelompokkan aturan. Ia juga dapat:
extends
: Mewarisi aturan dari ruleset lain (misalnya, ruleset Spectral bawaan atau ruleset organisasi bersama).rules
: Objek yang berisi definisi aturan kustom Anda.functionsDir
: Menentukan direktori tempat file fungsi JavaScript kustom berada.functions
: Array fungsi kustom (kurang umum saat menggunakanfunctionsDir
atau pengaturan terprogram).
Fungsi:
Fungsi adalah unit logika inti yang melakukan validasi sebenarnya. Spectral menyediakan banyak fungsi bawaan seperti:
truthy
: Memeriksa apakah suatu nilai adalah truthy.falsy
: Memeriksa apakah suatu nilai adalah falsy.defined
: Memeriksa apakah suatu properti didefinisikan.undefined
: Memeriksa apakah suatu properti tidak didefinisikan.pattern
: Memeriksa apakah sebuah string cocok dengan regex.alphabetical
: Memeriksa apakah elemen array atau kunci objek dalam urutan abjad.length
: Memeriksa panjang string atau array.schema
: Memvalidasi nilai terhadap Skema JSON.
Kekuatan sebenarnya muncul ketika ini tidak cukup, dan Anda perlu menulis fungsi kustom Anda sendiri – di sinilah TypeScript bersinar.
Membuat Fungsi Spectral Kustom Pertama Anda di TypeScript
Mari kita buat fungsi kustom sederhana. Bayangkan kita ingin menegakkan aturan bahwa semua ringkasan operasi API harus dalam format Title Case dan tidak melebihi 70 karakter.
Langkah 1: Definisikan Fungsi Kustom di TypeScript
Buat file, misalnya src/customFunctions.ts
:TypeScript
import type { IFunction, IFunctionResult } from '@stoplight/spectral-core';
interface TitleCaseLengthOptions {
maxLength: number;
}
// Fungsi kustom untuk memeriksa apakah string dalam format title-cased dan dalam panjang maksimum
export const titleCaseAndLength: IFunction<string, TitleCaseLengthOptions> = (
targetVal,
options,
context
): IFunctionResult[] | void => {
const results: IFunctionResult[] = [];
if (typeof targetVal !== 'string') {
// Seharusnya tidak terjadi jika path 'given' menunjuk ke string, tetapi praktik yang baik
return [{ message: `Nilai pada path '${context.path.join('.')}' harus berupa string.` }];
}
// Periksa Title Case (pemeriksaan sederhana: huruf pertama setiap kata adalah huruf besar)
const words = targetVal.split(' ');
const isTitleCase = words.every(word => word.length === 0 || (word[0] === word[0].toUpperCase() && (word.length === 1 || word.substring(1) === word.substring(1).toLowerCase())));
if (!isTitleCase) {
results.push({
message: `Ringkasan "${targetVal}" pada path '${context.path.join('.')}' harus dalam Title Case.`,
path: [...context.path], // Path ke elemen yang melanggar
});
}
// Periksa panjang
const maxLength = options?.maxLength || 70; // Default ke 70 jika tidak disediakan
if (targetVal.length > maxLength) {
results.push({
message: `Ringkasan "${targetVal}" pada path '${context.path.join('.')}' melebihi panjang maksimum ${maxLength} karakter. Panjang saat ini: ${targetVal.length}.`,
path: [...context.path],
});
}
return results;
};
Penjelasan:
- Kita mengimpor
IFunction
danIFunctionResult
dari@stoplight/spectral-core
untuk keamanan tipe.IFunction<T = unknown, O = unknown>
mengambil dua argumen generik:T
untuk tipetargetVal
(nilai yang sedang dilinting) danO
untuk tipeoptions
yang diteruskan ke fungsi. targetVal
: Nilai sebenarnya dari dokumen API yang ditunjuk oleh JSONPathgiven
. Kita telah mengetiknya sebagaistring
.options
: Objek yang berisi opsi yang diteruskan dari definisi aturan (misalnya,{ "maxLength": 70 }
). Kita membuat antarmukaTitleCaseLengthOptions
untuk opsi ini.context
: Menyediakan informasi kontekstual tentang proses linting, termasuk:path
: Array segmen path yang mengarah ketargetVal
.document
: Seluruh dokumen yang di-parse.rule
: Aturan saat ini yang sedang diproses.- Fungsi mengembalikan array objek
IFunctionResult
jika ada pelanggaran, atauvoid
/undefined
/array kosong jika tidak ada masalah. SetiapIFunctionResult
harus memilikimessage
dan secara opsionalpath
(jika berbeda daricontext.path
). - Logika kita memeriksa format title case sederhana dan panjang maksimum.
Langkah 2: Kompilasi Fungsi TypeScript
Jika Anda berencana menggunakan fungsi ini dengan ruleset .spectral.yaml
atau .spectral.js
yang menunjuk ke functionsDir
, Anda perlu mengkompilasi TypeScript Anda ke JavaScript.
Tambahkan skrip build ke package.json
Anda:JSON
{
"scripts": {
"build": "tsc"
}
}
Jalankan npm run build
atau yarn build
. Ini akan mengkompilasi src/customFunctions.ts
ke dist/customFunctions.js
(berdasarkan tsconfig.json
kita).
Langkah 3: Buat File Ruleset
Mari kita buat ruleset, misalnya, .spectral.js
(atau .spectral.ts
jika Anda lebih suka pengaturan yang sepenuhnya berbasis TypeScript, lihat bagian selanjutnya).
Jika menggunakan file ruleset JavaScript yang langsung mereferensikan fungsi yang dikompilasi:JavaScript
// .spectral.js
const { titleCaseAndLength } = require('./dist/customFunctions'); // Path ke fungsi JS yang dikompilasi
module.exports = {
extends: [['@stoplight/spectral-rulesets/dist/rulesets/oas', 'recommended']],
rules: {
'operation-summary-title-case-length': {
description: 'Ringkasan operasi harus dalam format title-cased dan tidak melebihi 70 karakter.',
message: '{{error}}', // Pesan akan berasal dari fungsi kustom
given: '$.paths[*][*].summary', // Menargetkan semua ringkasan operasi
severity: 'warn',
formats: ["oas3"], // Terapkan hanya untuk dokumen OpenAPI v3
then: {
function: titleCaseAndLength, // Langsung mereferensikan fungsi yang diimpor
functionOptions: {
maxLength: 70,
},
},
},
// Anda dapat menambahkan aturan lain di sini
},
};
Atau, jika menggunakan .spectral.yaml
dan functionsDir
:
Pertama, pastikan direktori dist
Anda berisi index.js
yang mengekspor fungsi Anda, atau customFunctions.js
Anda langsung mengekspornya. Misalnya, jika dist/customFunctions.js
memiliki exports.titleCaseAndLength = ...;
, Anda bisa melakukan:YAML
# .spectral.yaml
extends:
- ["@stoplight/spectral-rulesets/dist/rulesets/oas", "recommended"]
functionsDir: "./dist" # Direktori yang berisi fungsi JS kustom yang dikompilasi
rules:
operation-summary-title-case-length:
description: "Ringkasan operasi harus dalam format title-cased dan tidak melebihi 70 karakter."
message: "{{error}}"
given: "$.paths[*][*].summary"
severity: "warn"
formats: ["oas3"]
then:
function: customFunctions#titleCaseAndLength # Mengasumsikan fungsi diekspor dari customFunctions.js
functionOptions:
maxLength: 70
Di sini, customFunctions#titleCaseAndLength
memberitahu Spectral untuk mencari customFunctions.js
(atau customFunctions/index.js
) di functionsDir
dan menggunakan fungsi titleCaseAndLength
yang diekspor.
Langkah 4: Buat Dokumen OpenAPI Sampel
Mari kita buat file openapi.yaml
sederhana untuk menguji aturan kita:YAML
# openapi.yaml
openapi: 3.0.0
info:
title: Sample API
version: 1.0.0
paths:
/items:
get:
summary: retrieves all items from the store # Salah: bukan title case
responses:
'200':
description: Daftar item.
post:
summary: Adds A New Item To The Ever Expanding Collection Of Items In The Store # Salah: terlalu panjang
responses:
'201':
description: Item dibuat.
/users:
get:
summary: Get User Details # Benar
responses:
'200':
description: Detail pengguna.
Langkah 5: Jalankan Spectral
Sekarang, jalankan Spectral CLI terhadap dokumen OpenAPI Anda:Bash
spectral lint openapi.yaml --ruleset .spectral.js
# atau jika menggunakan ruleset YAML (seringkali terdeteksi otomatis jika bernama .spectral.yaml)
spectral lint openapi.yaml
Output yang Diharapkan:
Anda akan melihat peringatan yang mirip dengan ini:
openapi.yaml
2:10 warning operation-summary-title-case-length Summary "retrieves all items from the store" at path 'paths./items.get.summary' must be in Title Case. paths./items.get.summary
6:10 warning operation-summary-title-case-length Summary "Adds A New Item To The Ever Expanding Collection Of Items In The Store" at path 'paths./items.post.summary' exceeds maximum length of 70 characters. Current length: 78. paths./items.post.summary
✖ 2 problems (0 errors, 2 warnings, 0 infos, 0 hints)
Output ini mengkonfirmasi bahwa fungsi TypeScript kustom kita, yang dikompilasi ke JavaScript, dengan benar mengidentifikasi pelanggaran.
Penggunaan Spectral Secara Terprogram dengan Ruleset TypeScript
Untuk skenario yang lebih kompleks atau integrasi yang lebih erat ke dalam aplikasi, Anda mungkin ingin menggunakan Spectral secara terprogram dan mendefinisikan ruleset Anda sepenuhnya dalam TypeScript. Ini melewati kebutuhan akan file .spectral.yaml
atau .spectral.js
terpisah jika diinginkan, dan memungkinkan konstruksi ruleset yang dinamis.
Buat file TypeScript untuk linter Anda, misalnya src/linter.ts
:TypeScript
import { Spectral, Document } from '@stoplight/spectral-core';
import { oas } from '@stoplight/spectral-rulesets';
import { truthy } from '@stoplight/spectral-functions'; // Contoh fungsi bawaan
import { titleCaseAndLength } from './customFunctions'; // Fungsi TS kustom Anda
import type { ISpectralDiagnostic } from '@stoplight/spectral-core';
import * as fs from 'fs/promises';
import * as path from 'path';
// Definisikan instance Spectral
const spectral = new Spectral();
// Muat ruleset dan fungsi bawaan
spectral.setRuleset({
extends: [[oas, 'recommended']], // Memperluas aturan OpenAPI yang direkomendasikan
rules: {
'operation-summary-title-case-length': {
description: 'Ringkasan operasi harus dalam format title-cased dan tidak melebihi 70 karakter.',
message: '{{error}}',
given: '$.paths[*][*].summary',
severity: 'warn',
formats: ["oas3"],
then: {
function: titleCaseAndLength, // Langsung menggunakan fungsi TypeScript
functionOptions: {
maxLength: 70,
},
},
},
'info-contact-defined': { // Contoh menggunakan fungsi bawaan
description: 'Objek info harus memiliki objek kontak.',
message: 'Informasi kontak API hilang.',
given: '$.info',
severity: 'warn',
formats: ["oas3"],
then: {
field: 'contact',
function: truthy, // Menggunakan fungsi bawaan
},
},
},
});
// Fungsi untuk melakukan linting pada dokumen
export async function lintDocument(filePath: string): Promise<ISpectralDiagnostic[]> {
try {
const absolutePath = path.resolve(filePath);
const fileContent = await fs.readFile(absolutePath, 'utf-8');
// Buat objek Dokumen Spectral
// Argumen kedua (URI) penting untuk menyelesaikan $refs relatif jika ada
const document = new Document(fileContent, undefined, absolutePath);
const results = await spectral.run(document);
return results;
} catch (error) {
console.error('Error linting dokumen:', error);
return [];
}
}
// Contoh penggunaan (misalnya, dalam skrip atau modul lain)
async function main() {
const diagnostics = await lintDocument('openapi.yaml'); // Path ke spesifikasi API Anda
if (diagnostics.length > 0) {
console.log('Ditemukan Masalah Linting API:');
diagnostics.forEach(issue => {
console.log(
`- [${issue.severity === 0 ? 'Error' : issue.severity === 1 ? 'Warning' : issue.severity === 2 ? 'Info' : 'Hint'}] ${issue.code} (${issue.message}) pada ${issue.path.join('.')}`
);
});
} else {
console.log('Tidak ada masalah linting API ditemukan. Kerja bagus!');
}
}
// Jika Anda ingin menjalankan file ini langsung dengan ts-node
if (require.main === module) {
main().catch(console.error);
}
Untuk menjalankan ini:Bash
npx ts-node src/linter.ts
Pendekatan ini memberikan fleksibilitas maksimum:
- Tidak Ada Langkah Kompilasi untuk Definisi Ruleset: Ruleset itu sendiri didefinisikan dalam TypeScript. Fungsi kustom Anda masih perlu diimpor (baik sebagai TS jika
ts-node
digunakan, atau JS yang dikompilasi jika menjalankan Node murni). - Aturan Dinamis: Anda dapat secara terprogram membuat atau memodifikasi ruleset berdasarkan kondisi runtime.
- Penggunaan Tipe Langsung: Anda langsung menggunakan fungsi TypeScript yang diimpor dalam definisi ruleset, meningkatkan keamanan tipe dan integrasi IDE.
Teknik Fungsi Kustom Tingkat Lanjut
Mari kita jelajahi beberapa aspek yang lebih canggih dalam membuat fungsi kustom.
Fungsi Kustom Asinkron:
Jika fungsi kustom Anda perlu melakukan operasi asinkron (misalnya, mengambil sumber daya eksternal untuk divalidasi, meskipun gunakan dengan hati-hati untuk kinerja), Anda dapat mendefinisikannya sebagai fungsi async.TypeScript
import type { IFunction, IFunctionResult } from '@stoplight/spectral-core';
export const checkExternalResource: IFunction<string, { url: string }> =
async (targetVal, options, context): Promise<IFunctionResult[] | void> => {
try {
const response = await fetch(`${options.url}/${targetVal}`);
if (!response.ok) {
return [{ message: `Sumber daya '${targetVal}' tidak ditemukan di ${options.url}. Status: ${response.status}` }];
}
} catch (error: any) {
return [{ message: `Error mengambil sumber daya '${targetVal}': ${error.message}` }];
}
};
Spectral akan dengan benar await
fungsi asinkron Anda.
Mengakses Dokumen Lengkap dan Nilai yang Diselesaikan:
Objek context.document memberi Anda akses ke seluruh dokumen yang di-parse. Lebih kuat lagi, context.document.resolved menyediakan versi dokumen yang sepenuhnya di-dereference, yang penting saat berurusan dengan pointer $ref.TypeScript
import type { IFunction, IFunctionResult } from '@stoplight/spectral-core';
import {isPlainObject} from '@stoplight/json';
// Contoh: Pastikan skema yang direferensikan memiliki properti spesifik
export const referencedSchemaHasProperty: IFunction<{$ref: string}, { propertyName: string }> = (
targetVal, // Ini akan menjadi objek seperti { $ref: '#/components/schemas/MySchema' }
options,
context
): IFunctionResult[] | void => {
if (!targetVal.$ref) return;
// Metode `context.document.resolveAnchor` dapat menemukan nilai yang diselesaikan untuk $ref
const resolvedValue = context.document.resolveAnchor(targetVal.$ref);
if (!resolvedValue || !isPlainObject(resolvedValue.value)) {
return [{ message: `Tidak dapat menyelesaikan $ref: ${targetVal.$ref}` }];
}
const schemaProperties = resolvedValue.value.properties as Record<string, unknown> | undefined;
if (!schemaProperties || schemaProperties[options.propertyName] === undefined) {
return [{
message: `Skema yang direferensikan oleh "${targetVal.$ref}" pada path '${context.path.join('.')}' harus memiliki properti "${options.propertyName}".`,
path: [...context.path, '$ref'] // Arahkan ke $ref itu sendiri
}];
}
};
Fungsi ini akan digunakan dengan path given
yang menargetkan objek yang berisi $ref
, misalnya: $.paths[*].*.responses.*.content.*.schema
.
Bekerja dengan format:
Pastikan aturan kustom Anda menentukan format yang berlaku (misalnya, oas2, oas3, asyncapi2). Ini mencegah aturan berjalan pada tipe dokumen yang tidak kompatibel. Anda dapat mengakses format yang terdeteksi dalam fungsi Anda melalui context.document.formats.
Mengorganisir dan Memperluas Ruleset
Seiring bertambahnya koleksi aturan kustom Anda, organisasi menjadi kunci.
- Ruleset Modular: Pecah ruleset besar menjadi file yang lebih kecil dan terfokus. Anda dapat menggunakan properti
extends
untuk menggabungkannya. JavaScript
// .spectral.js (ruleset utama)
module.exports = {
extends: ['./rulesets/common-rules.js', './rulesets/security-rules.js'],
// ... aturan atau override lainnya
};
- Ruleset Bersama: Publikasikan ruleset sebagai paket npm untuk membagikannya di berbagai proyek atau tim. Properti
extends
kemudian dapat mereferensikan paket-paket ini. functionsDir
untuk Kesederhanaan: Jika Anda memiliki banyak fungsi JS kustom (dikompilasi dari TS),functionsDir
dalam ruleset.spectral.yaml
bisa lebih sederhana daripada mendaftarkan semuanya atau menggunakan pengaturan yang sepenuhnya terprogram. Pastikan saja file JS yang dikompilasi mengekspor fungsi dengan benar.
Mengintegrasikan Spectral ke dalam Alur Kerja Anda
Kekuatan sebenarnya dari linting API terwujud ketika diotomatiskan.
- Pipeline CI/CD: Integrasikan perintah
spectral lint
ke dalam GitHub Actions, GitLab CI, Jenkins, atau pipeline CI/CD lainnya. Gagalkan build jika terdeteksi kesalahan kritis. YAML
# Contoh langkah GitHub Action
- name: Lint API Specification
run: spectral lint ./path/to/your/api-spec.yaml --ruleset ./.spectral.js --fail-severity=error
- Git Hooks: Gunakan alat seperti Husky untuk menjalankan Spectral pada hook pre-commit atau pre-push, menangkap masalah bahkan sebelum mencapai repositori.
- Integrasi IDE: Cari ekstensi Spectral untuk IDE Anda (misalnya, VS Code) untuk mendapatkan umpan balik waktu nyata saat Anda menulis spesifikasi API Anda.
Praktik Terbaik untuk Spectral dan Aturan Kustom TypeScript
- Deskripsi dan Pesan yang Jelas: Tulis properti
description
danmessage
yang bermakna untuk aturan Anda. Pesan harus memandu pengguna tentang cara memperbaiki masalah. - Tingkat Keparahan yang Sesuai: Gunakan
error
untuk pelanggaran kritis,warn
untuk saran penting,info
untuk pemeriksaan informasional, danhint
untuk saran kecil. - Path
given
yang Tepat: Buat ekspresi JSONPath Anda sespesifik mungkin untuk hanya menargetkan node yang dimaksud. Ini meningkatkan kinerja dan mengurangi false positive. - Fungsi Idempoten: Fungsi kustom harus murni jika memungkinkan – dengan input yang sama, mereka harus menghasilkan output yang sama tanpa efek samping.
- Uji Aturan Kustom Anda: Tulis unit test untuk fungsi TypeScript kustom Anda untuk memastikan mereka berperilaku seperti yang diharapkan dengan berbagai input.
- Pertimbangan Kinerja: Perhatikan komputasi kompleks atau banyak panggilan fungsi
schema
dalam aturan yang sensitif terhadap kinerja, terutama untuk dokumen yang sangat besar. Uji kinerja ruleset Anda. - Perbarui Tipe TypeScript: Pastikan fungsi kustom Anda mengetik dengan benar
targetVal
danoptions
yang mereka harapkan. Ini penting untuk kemudahan pemeliharaan.
Kesimpulan: Tingkatkan Tata Kelola API Anda dengan Spectral dan TypeScript
Spectral menawarkan kerangka kerja yang tangguh untuk linting API, dan dengan memanfaatkan TypeScript untuk pengembangan aturan kustom, Anda membawa peningkatan keamanan tipe, pengalaman pengembang, dan kemudahan pemeliharaan ke strategi tata kelola API Anda. Baik Anda menegakkan praktik terbaik OpenAPI, konvensi penamaan khusus perusahaan, atau logika bisnis kompleks dalam desain API Anda, kombinasi mesin aturan Spectral yang fleksibel dan sistem pengetikan yang kuat dari TypeScript menyediakan solusi yang ampuh.
Dengan mengintegrasikan Spectral ke dalam siklus pengembangan Anda, mulai dari umpan balik IDE hingga pipeline CI/CD, Anda dapat memastikan API Anda konsisten, berkualitas tinggi, dan mematuhi standar yang Anda definisikan, yang pada akhirnya menghasilkan API yang lebih andal dan lebih mudah dikonsumsi. Mulailah dari yang kecil, ulangi ruleset Anda, dan berdayakan tim Anda dengan alat untuk membangun API yang lebih baik.