يوم جيد ، أيها الأصدقاء!
أقدم انتباهكم إلى ترجمة مقال "The Deno Handbook: A TypeScript Runtime Tutorial with Code Examples" لـ Flavio Copes.
في هذه المقالة سوف نتعلم كيفية العمل مع دينو. سنقارنه بـ Node.js ونبني بواجهة برمجة تطبيقات REST بسيطة معها.
ما هو دينو؟
إذا كنت معتادًا على Node.js ، نظام JavaScript البيئي الشهير من جانب الخادم ، فإن Deno هو نفس الشيء إلى حد كبير. تقريبًا ، لكن ليس تمامًا.
لنبدأ بقائمة ميزات Deno التي أحبها أكثر من غيرها:
- يعتمد على JavaScript الحديث
- لديها مكتبة قياسية قابلة للتوسيع
- يحتوي على دعم TypeScript قياسي (وهذا يعني أنه ليس عليك ترجمة TypeScript يدويًا ، فإن Deno يقوم بذلك تلقائيًا)
- يدعم وحدات ES
- ليس لديها مدير حزم
- لديها ملف
await
- لديها مرفق اختبار مدمج
- هدفه هو أقصى توافق للمتصفح. لهذا ، فإنه يوفر
fetch
كائنًا مضمنًا وعموميًاwindow
في هذا البرنامج التعليمي ، سوف نستكشف كل هذه الاحتمالات.
بعد التعرف على Deno وقدراته ، سيبدو Node.js قديمًا بعض الشيء.
خاصة وأن Node.js يعتمد على وظائف رد الاتصال (تمت كتابته قبل الوعود وغير المتزامن / الانتظار). من غير المحتمل أن تظهر هناك على الإطلاق ، لأن هذا يعني أن هناك حاجة إلى تغييرات أساسية.
Node.js رائع وسيظل المعيار الفعلي في عالم JavaScript. ومع ذلك ، أعتقد أن شعبية Deno ستنمو بسرعة بفضل دعم TypeScript والمكتبة القياسية الحديثة.
يمكن لـ Deno تحمل الكود الحديث لأنه لا يحتاج إلى التوافق مع الإصدارات السابقة. بالطبع ، ليس هناك ما يضمن أن هذا الرمز سيظل محدثًا في العقد المقبل ، لكنه اليوم كذلك.
لماذا دينو؟ لماذا الان؟
تم الإعلان عن Deno منذ عامين تقريبًا بواسطة مبتكر Node.js Ryan Dahl في JSConf EU. شاهد فيديو YouTube ، إنه ممتع للغاية ويجب أن ترى ما إذا كنت تعمل مع Node.js و JavaScript.
كل مدير مشروع (مبتكر) مجبر على اتخاذ قرارات. يأسف ريان على بعض القرارات المبكرة في Node. بالإضافة إلى ذلك ، تتقدم التكنولوجيا وأصبح JavaScript لغة مختلفة تمامًا اليوم عما كانت عليه في عام 2009 عندما كانت Node. فكر في العودة إلى ES6 / 2016/2017 وما إلى ذلك.
لذلك قرر بدء مشروع جديد ، نوع من الموجة الثانية من تطبيقات JavaScript من جانب الخادم.
السبب في أنني أكتب هذا المقال فقط الآن هو أن التكنولوجيا تستغرق وقتًا طويلاً لتنضج. أخيرًا ، حصلنا على Deno 1.0 (تم إصداره في 13 مايو 2020) ، وهو أول إصدار مستقر.
قد يبدو هذا رقمًا شائعًا ، ولكن 1.0 يعني أنه لن يكون هناك أي تغييرات جذرية حتى الإصدار 2.0 من Deno. عندما تتعلم تقنية جديدة ، فأنت لا تريدها أن تتغير بسرعة كبيرة.
هل يجب أن تتعلم دينو؟
سؤال جيد.
يتطلب تعلم شيء جديد مثل Deno الكثير من الجهد. نصيحتي: إذا كنت بدأت للتو مع JS من جانب الخادم ولا تعرف Node.js حتى الآن ، ولم تكتب TypeScript من قبل ، فابدأ بـ Node.
لم يُطرد أحد من قبل لاختياره Node (إعادة صياغة اقتباس مشهور).
ولكن إذا كنت تحب TypeScript ، والذي لا يعتمد على عدد كبير من حزم npm ، وتريد استخدامه في كل مكان
await
، فقد يكون Deno هو ما تبحث عنه.
هل سيحل محل Node.js؟
لا. Node.js هي شركة عملاقة ، سلطة كبيرة ، تقنية مدعومة جيدًا بشكل لا يصدق لن تذهب إلى أي مكان في العقد المقبل.
دعم TypeScript من الدرجة الأولى
تمت كتابة Deno بلغة Rust و TypeScript ، وهما لغتان شائعتان جدًا في عالم اليوم.
هذا يعني أننا نحصل على الكثير من الفوائد من TypeScript ، حتى لو كنا نكتب JavaScript.
لا يتطلب تشغيل رمز TypeScript مع Deno تجميعًا مسبقًا - يقوم Deno بذلك تلقائيًا.
لا يتعين عليك كتابة كود TypeScript ، ولكن حقيقة أن نواة Deno مكتوبة بلغة TypeScript تحدث فرقًا كبيرًا.
أولاً ، هناك نسبة كبيرة من مطوري JavaScript يحبون TypeScript.
ثانيًا ، يمكن للأدوات التي تستخدمها الحصول على الكثير من المعلومات حول برنامج TypeScript مثل Deno.
هذا يعني أنه عندما نكتب تعليمات برمجية في VS Code ، على سبيل المثال (التي تكاملت بشكل وثيق مع TypeScript منذ إنشائها) ، فإننا نحصل على مزايا مثل التحقق من النوع عند كتابة التعليمات البرمجية أو قدرات IntelliSense المتقدمة. بمعنى آخر ، تصبح مساعدة محرر الكود أكثر فاعلية.
الاختلافات من Node.js
نظرًا لأن Deno هو أساسًا بديل لـ Node.js ، فمن المنطقي المقارنة بين الاثنين.
جنرال لواء:
- كلاهما يعتمد على محرك V8
- كلاهما رائع لتطوير JavaScript من جانب الخادم
اختلافات:
- العقدة مكتوبة بلغة C ++ و JavaScript. تمت كتابة Deno بلغة Rust و TypeScript.
- لدى Node مدير حزم رسمي
npm
. لا يمتلك Deno مثل هذا المدير ، ولكنه يتيح لك بدلاً من ذلك استيراد أي وحدة باستخدام عنوان URL. - تستخدم Node بنية CommonJS لاستيراد الحزم. يستخدم Deno الطريقة الرسمية - وحدات ES.
- Deno ECMAScript , Node.js .
- Deno () . . Node.js , .
- Deno , .. , , Go, . .
إن عدم وجود مدير حزم واستخدام عنوان URL للحصول على حزم واستيرادها له مزايا وعيوب. إحدى الميزات الرئيسية هي المرونة الكبيرة في القدرة على إنشاء الحزم دون الحاجة إلى نشرها في مستودع مثل npm.
أعتقد أن بعض البدائل لمدير الحزم في Deno ستظهر عاجلاً أم آجلاً.
يستضيف موقع Deno الرسمي حزم الطرف الثالث: https://deno.land/x/
تثبيت Deno
يكفي الحديث! لنقم بتثبيت Deno.
أسهل طريقة للقيام بذلك هي استخدام Homebrew:
brew install deno
طرق التثبيت الأخرى مذكورة هنا .
بعد التثبيت ، يصبح الأمر متاحًا
deno
. إليك المساعدة التي يمكنك الحصول عليها عن طريق كتابة deno --help
:
flavio@mbp~> deno --help
deno 0.42.0
A secure JavaScript and TypeScript runtime
Docs: https://deno.land/std/manual.md
Modules: https://deno.land/std/ https://deno.land/x/
Bugs: https://github.com/denoland/deno/issues
To start the REPL, supply no arguments:
deno
To execute a script:
deno run https://deno.land/std/examples/welcome.ts
deno https://deno.land/std/examples/welcome.ts
To evaluate code in the shell:
deno eval "console.log(30933 + 404)"
Run 'deno help run' for 'run'-specific flags.
USAGE:
deno [OPTIONS] [SUBCOMMAND]
OPTIONS:
-h, --help
Prints help information
-L, --log-level <log-level>
Set log level [possible values: debug, info]
-q, --quiet
Suppress diagnostic output
By default, subcommands print human-readable diagnostic messages to stderr.
If the flag is set, restrict these messages to errors.
-V, --version
Prints version information
SUBCOMMANDS:
bundle Bundle module and dependencies into single file
cache Cache the dependencies
completions Generate shell completions
doc Show documentation for a module
eval Eval script
fmt Format source files
help Prints this message or the help of the given subcommand(s)
info Show info about cache or info related to source file
install Install script as an executable
repl Read Eval Print Loop
run Run a program given a filename or url to the module
test Run tests
types Print runtime TypeScript declarations
upgrade Upgrade deno executable to newest version
ENVIRONMENT VARIABLES:
DENO_DIR Set deno's base directory (defaults to $HOME/.deno)
DENO_INSTALL_ROOT Set deno install's output directory
(defaults to $HOME/.deno/bin)
NO_COLOR Set to disable color
HTTP_PROXY Proxy address for HTTP requests
(module downloads, fetch)
HTTPS_PROXY Same but for HTTPS
فرق دينو
هل لاحظت المقطع
SUBCOMMANDS
؟ هذه قائمة بجميع الأوامر التي يمكننا تشغيلها. ما الفرق التي لدينا؟
bundle
- يجمع تبعيات الوحدة النمطية والمشروع في ملف واحدcache
- مخابئ التبعياتcompletions
- يولد عبوات شلdoc
- يعرض وثائق الوحدةeval
- تستخدم لحساب كتلة من التعليمات البرمجية ، على سبيل المثالdeno eval "console.log(1 + 2)"
fmt
- منسق كود مدمج (كماgoFmt
في Go)help
- يعرض قائمة بالأوامر المساعدةinfo
- يعرض معلومات حول ذاكرة التخزين المؤقت أو الملفinstall
- يحدد البرنامج النصي على أنه قابل للتنفيذrepl
- دورة قراءة-حساب-إخراج (افتراضي)run
- يدير البرنامج بالاسم المحدد أو عنوان URL للوحدةtest
- يدير الاختباراتtypes
- يعرض قائمة بميزات TypeScriptupgrade
- تحديثات Deno إلى أحدث إصدار
يمكنك الجري
deno <subcommand> help
للحصول على معلومات حول أمر معين ، على سبيل المثال deno run --help
.
يمكننا استخدام أمر
deno
لبدء حلقة قراءة-تقييم-إخراج:
هذا هو نفس البدء
deno repl
. تُستخدم
عادةً
deno
لتشغيل تطبيق Deno الموجود في ملف TypeScript.
يمكنك تشغيل ملفات TypeScript (.ts) وملفات JavaScript (.js).
إذا كنت مستخدمًا جديدًا لـ TypeScript ، فلا تقلق: تمت كتابة Deno بلغة TypeScript ، ولكن يمكنك كتابة تطبيقات العميل الخاصة بك في JavaScript.
أول تطبيق على Deno
لنقم بإنشاء تطبيقنا الأول.
للقيام بذلك ، ليس علينا حتى كتابة التعليمات البرمجية ، سنقوم بتشغيلها في المحطة باستخدام عنوان URL.
يقوم Deno بتنزيل البرنامج وتجميعه وتشغيله:
بالطبع ، لا أوصي بتشغيل رمز عشوائي من الإنترنت. في هذه الحالة ، نقوم بإطلاقه من موقع Deno الرسمي ، بالإضافة إلى أن Deno لديه وضع الحماية الذي يمنع البرامج من القيام بما لم نسمح لهم به صراحةً.
هذا البرنامج بسيط للغاية وهو عبارة عن مكالمة
console.log()
:
console.log('Welcome to Deno ') // ,
إذا فتحت https://deno.land/std/examples/welcome.ts في متصفح ، فسترى ما يلي:
غريب ، أليس كذلك؟ ربما كنت تتوقع أن ترى ملف TypeScript ، ولكن بدلاً من ذلك حصلت على صفحة ويب. النقطة المهمة هي أن خادم موقع ويب Deno يعرف أنك تستخدم متصفحًا ويوفر لك صفحة أكثر سهولة في الاستخدام.
قم بتحميل نفس عنوان URL باستخدام
wget
، على سبيل المثال ، واحصل عليه text/plain
بدلاً من ذلك text/html
:
عند إعادة تشغيل البرنامج ، بفضل التخزين المؤقت ، لا يلزم إعادة التشغيل:
باستخدام علامة ،
--reload
يمكنك إجراء إعادة تشغيل قسري:
deno run
يحتوي على العديد من الوظائف المختلفة التي لا يتم عرضها من خلال deno --help
. لكي تراهم ، يجب عليك تشغيل deno run --help
:
flavio@mbp~> deno run --help
deno-run
Run a program given a filename or url to the module.
By default all programs are run in sandbox without access to disk, network or
ability to spawn subprocesses.
deno run https://deno.land/std/examples/welcome.ts
Grant all permissions:
deno run -A https://deno.land/std/http/file_server.ts
Grant permission to read from disk and listen to network:
deno run --allow-read --allow-net https://deno.land/std/http/file_server.ts
Grant permission to read whitelisted files from disk:
deno run --allow-read=/etc https://deno.land/std/http/file_server.ts
USAGE:
deno run [OPTIONS] <SCRIPT_ARG>...
OPTIONS:
-A, --allow-all
Allow all permissions
--allow-env
Allow environment access
--allow-hrtime
Allow high resolution time measurement
--allow-net=<allow-net>
Allow network access
--allow-plugin
Allow loading plugins
--allow-read=<allow-read>
Allow file system read access
--allow-run
Allow running subprocesses
--allow-write=<allow-write>
Allow file system write access
--cached-only
Require that remote dependencies are already cached
--cert <FILE>
Load certificate authority from PEM encoded file
-c, --config <FILE>
Load tsconfig.json configuration file
-h, --help
Prints help information
--importmap <FILE>
UNSTABLE:
Load import map file
Docs: https://deno.land/std/manual.md#import-maps
Specification: https://wicg.github.io/import-maps/
Examples: https://github.com/WICG/import-maps#the-import-map
--inspect=<HOST:PORT>
activate inspector on host:port (default: 127.0.0.1:9229)
--inspect-brk=<HOST:PORT>
activate inspector on host:port and break at start of user script
--lock <FILE>
Check the specified lock file
--lock-write
Write lock file. Use with --lock.
-L, --log-level <log-level>
Set log level [possible values: debug, info]
--no-remote
Do not resolve remote modules
-q, --quiet
Suppress diagnostic output
By default, subcommands print human-readable diagnostic messages to stderr.
If the flag is set, restrict these messages to errors.
-r, --reload=<CACHE_BLACKLIST>
Reload source code cache (recompile TypeScript)
--reload
Reload everything
--reload=https://deno.land/std
Reload only standard modules
--reload=https://deno.land/std/fs/utils.ts,https://deno.land/std/fmt/colors.ts
Reloads specific modules
--seed <NUMBER>
Seed Math.random()
--unstable
Enable unstable APIs
--v8-flags=<v8-flags>
Set V8 command line options. For help: --v8-flags=--help
ARGS:
<SCRIPT_ARG>...
script args
أمثلة التعليمات البرمجية
هناك أمثلة أخرى على موقع Deno يمكن العثور عليها هنا .
في وقت كتابة هذا التقرير ، كان من الممكن العثور على ما يلي في المستودع المحدد:
cat.ts
- يعرض محتويات الملفات التي تم تمريرها كوسيطاتcatj.ts
- يفعل نفس الشيء ،cat.ts
لكنه يقوم أولاً ببعض التلاعب بمحتويات الملفاتchat/
- تنفيذ الدردشةcolors.ts
- مثال على تصميم النص باستخدام الوحداتcurl.ts
- تطبيق بسيطcurl
ينتج عنه محتوى عنوان URL الذي تم تمريره كوسيطةecho_server.ts
- خادم صدى TCPgist.ts
- برنامج لوضع الملفات في gist.github.comtest.ts
- برنامج الاختبارwelcome.ts
- البرنامج الذي أطلقناهxeval.ts
- يسمح لك بتشغيل TypeScript التي تم الحصول عليها من أي مصدر بيانات قياسي.deno xeval
تم حذفه من قائمة الفرق الرسمية
أول تطبيق حقيقي على Deno
لنكتب بعض التعليمات البرمجية.
تمت كتابة التطبيق الأول الذي أطلقناه
deno run https://deno.land/std/examples/welcome.ts
بالفعل ، لذا لم تتعلم أي شيء جديد عن Deno.
لنبدأ بمثال قياسي منشور على موقع Deno الإلكتروني:
import { serve } from 'https://deno.land/std/http/server.ts'
const s = serve({ port: 8000 })
console.log('http://localhost:8000/')
for await (const req of s) {
req.respond({ body: 'Hello World\n' })
}
نحن هنا نستورد دالة
serve
من وحدة http/server
. نرى؟ لم يكن علينا تثبيته ، ولم يتم تخزينه على جهاز الكمبيوتر الخاص بنا مثل وحدات Node. هذا هو أحد أسباب التثبيت السريع لـ Deno.
بمساعدة المساعدة
https://deno.land/std/http/server.ts
نقوم باستيراد أحدث إصدار من الوحدة. يمكن استيراد إصدار محدد باستخدام @VERSION
:
import { serve } from 'https://deno.land/std@v0.42.0/http/server.ts'
هذه هي الوظيفة
serve
:
/**
* Create a HTTP server
*
* import { serve } from "https://deno.land/std/http/server.ts";
* const body = "Hello World\n";
* const s = serve({ port: 8000 });
* for await (const req of s) {
* req.respond({ body });
* }
*/
export function serve(addr: string | HTTPOptions): Server {
if (typeof addr === 'string') {
const [hostname, port] = addr.split(':')
addr = { hostname, port: Number(port) }
}
const listener = listen(addr)
return new Server(listener)
}
بعد ذلك ، نسمي الوظيفة
serve()
ونمررها كائنًا بخاصية port
.
ثم نقوم بتشغيل حلقة للرد على كل طلب من الخادم:
for await (const req of s) {
req.respond({ body: 'Hello World\n' })
}
لاحظ أننا نستخدم الكلمة الأساسية
await
دون تغليف الكود في async
دالة.
لنقم بتشغيل البرنامج محليًا. أنا أستخدم VS Code ، لكن يمكنك استخدام أي محرر.
أوصي بتثبيت امتداد من justjavac (هناك ملحق آخر بنفس الاسم ، لكنه مهمل وقد يختفي في المستقبل):
يوفر الامتداد العديد من الأدوات المساعدة لمساعدتك في كتابة تطبيقات Deno.
لنقم بإنشاء ملف
app.ts
وإدخال الكود الخاص بنا
فيه
deno run app.ts
: قم
بتشغيله باستخدام : سيقوم Deno بتحميل جميع التبعيات التي يحتاجها البرنامج ، ولكن أولاً الذي نقوم باستيراده في الملف.
يحتوي ملف https://deno.land/std/http/server.ts على العديد من التبعيات الخاصة به:
import { encode } from '../encoding/utf8.ts'
import { BufReader, BufWriter } from '../io/bufio.ts'
import { assert } from '../testing/asserts.ts'
import { deferred, Deferred, MuxAsyncIterator } from '../async/mod.ts'
import {
bodyReader,
chunkedBodyReader,
emptyReader,
writeResponse,
readRequest,
} from './_io.ts'
import Listener = Deno.Listener
import Conn = Deno.Conn
import Reader = Deno.Reader
يتم استيراد هذه التبعيات تلقائيًا.
في النهاية لدينا مشكلة:
ما الذي يحدث؟ حصلنا على إذن رفض الخطأ.
لنتحدث عن الصندوق الرمل.
صندوق الرمل
كما ذكرت سابقًا ، لدى Deno وضع حماية يمنع البرامج من القيام بأشياء لم يتلقوا إذنًا بشأنها.
ماذا يعني هذا؟
كما يقول Ryan في حديثه ، فأنت تريد أحيانًا تشغيل برنامج JavaScript خارج المتصفح ، ولا تريد أن يتمكن البرنامج من الوصول إلى كل شيء على نظامك. أو عندما يتعلق الأمر بالعالم الخارجي باستخدام الشبكة.
لا شيء يمنع تطبيق Node.js من الحصول على مفتاح SSH أو أي معلومات أخرى من نظامك وإرسالها إلى الخادم. لهذا السبب نقوم عادةً بتثبيت حزم Node من مصادر موثوقة فقط. ولكن كيف نعرف ما إذا كان أحد المشاريع التي نستخدمها قد تعرض للاختراق؟
يحاكي Deno نظام الأذونات الذي يستخدمه المتصفح. لا تستطيع شفرة JavaScript التي تعمل في المستعرض أن تفعل أي شيء مع نظامك ما لم تسمح له صراحةً بذلك.
بالعودة إلى Deno ، إذا احتاج أحد البرامج إلى الوصول إلى الشبكة ، فعلينا منحه الإذن للقيام بذلك.
يتم ذلك باستخدام العلم
--allow-net
:
deno run --allow-net app.ts
الخادم يعمل الآن على المنفذ 8000:
العلامات الأخرى:
--allow-env
- يسمح بالوصول إلى متغيرات البيئة--allow-hrtime
- يسمح بقياس دقة عالية--allow-net=<allow-net>
- يسمح بالوصول إلى الشبكة--allow-plugin
- يسمح بتحميل الإضافات--allow-read=<allow-read>
- يسمح بقراءة الملفات--allow-run
- يسمح ببدء العمليات الفرعية--allow-write=<allow-write>
- يسمح لكتابة الملفات--allow-all
- يمنح جميع الأذونات (مماثلة-A
)
ضوابط ل
net
، read
و write
قد يكون جزئيا. على سبيل المثال، يمكننا أن نسمح الملفات للقراءة فقط التي هي في دليل معين: --allow-read=/dev
.
تنسيق الكود
أحد الأشياء التي أحبها في Go هو الأمر
gofmt
. كل كود Go يبدو كما هو. الجميع يستخدمه gofmt
.
عادةً ما يستخدم مطورو JavaScript Prettier ، وفي
deno fmt
الواقع يستخدمونها أيضًا تحت القص.
لنفترض أن لديك مثل هذا الملف المنسق بشكل سيئ:
تبدأ
deno fmt app.ts
ويتم التنسيق التلقائي مع الفواصل المنقوطة المفقودة:
مكتبة قياسية
مكتبة دينو القياسية واسعة جدًا على الرغم من عمر المشروع.
وهي تشمل ما يلي:
archieve
- مرافق للأرشفةasync
- الأدوات المساعدة للعمل مع التعليمات البرمجية غير المتزامنةbytes
- الوظائف المساعدة لتقسيم البايتdatetime
- تحليل التواريخ / الأوقاتencoding
- ترميز / فك في صيغ مختلفةflags
- تحليل أعلام سطر الأوامرfmt
- التشكيل والعرضfs
- واجهة تطبيق للعمل مع نظام الملفاتhash
- مكتبة التشفيرhttp
- خادم HTTPio
- مكتبة عمليات الإدخال / الإخراجlog
- المرافق للتسجيلmime
- دعم البيانات المختلطةnode
- طبقة التوافق مع العُقدةpath
- العمل مع المساراتws
- مآخذ الويب
مثال آخر
دعنا نلقي نظرة على مثال رسمي آخر -
cat.ts
:
const filenames = Deno.args
for (const filename of filenames) {
const file = await Deno.open(filename)
await Deno.copy(file, Deno.stdout)
file.close()
}
نقوم بتعيين
filenames
المحتوى إلى متغير Deno.args
، وهو متغير يحتوي على الوسائط التي تم تمريرها باستخدام سطر الأوامر.
نحن نكررها ، ولكل منها ، نستخدم أولاً
Deno.open()
لفتح الملف ثم Deno.copy()
نسخ المحتوى إلى Deno.stdout
. أخيرًا ، نغلق الملف.
اذا ركضت:
deno run https://deno.land/std/examples/cat.ts
سيتم تحميل البرنامج وتجميعه ، لكن لا شيء يحدث لأننا لم نجتاز أي وسيطات.
الآن لنجرب هذا:
deno run https://deno.land/std/examples/cat.ts app.ts
حصلنا
على خطأ في الإذن: لا يمتلك Deno حق الوصول إلى النظام افتراضيًا. لنمنحه هذا الإذن من خلال
--allow-read
:
deno run --allow-read=./ https://deno.land/std/examples/cat.ts app.ts
هل يوجد Express / Hapi / Koa / * لدينو؟
بالطبع. ألق نظرة على المشاريع التالية:
مثال: استخدام البلوط لإنشاء واجهة برمجة تطبيقات REST
سأقوم بإنشاء REST API باستخدام Oak. البلوط مثير للاهتمام لأنه مستوحى من Koa ، البرنامج الوسيط الشهير لـ NOde.js ، وله تركيب مماثل.
ستكون واجهة برمجة التطبيقات الخاصة بنا بسيطة للغاية.
سيخزن خادمنا في الذاكرة قائمة بالكلاب وأسمائهم وأعمارهم.
نريد الحصول على الوظائف التالية:
- إضافة كلاب جديدة إلى القائمة
- احصل على قائمة بكل الكلاب
- الحصول على معلومات حول كلب معين
- إزالة كلب من القائمة
- تحديث عمر الكلب
سنقوم بكتابة الكود في Typescript ، لكن لا شيء يمنعك من القيام بذلك في JavaScript - فقط لا تحدد أنواع البيانات.
نقوم بإنشاء ملف
app.ts
.
لنبدأ باستيراد العناصر من
Application
وإلى :Router
Oak
import { Application, Router } from 'https://deno.land/x/oak/mod.ts'
نحصل على متغيرات البيئة PORT و HOST:
const env = Deno.env.toObject()
const PORT = env.PORT || 4000
const HOST = env.HOST || '127.0.0.1'
بشكل افتراضي ، سيتم تشغيل تطبيقنا على المضيف المحلي: 4000.
قم بإنشاء تطبيق Oak وقم بتشغيله:
const router = new Router()
const app = new Application()
app.use(router.routes())
app.use(router.allowedMethods())
console.log(`Listening on port ${PORT}...`)
await app.listen(`${HOST}:${PORT}`)
يجب أن يعمل التطبيق الآن.
نحن نفحص:
deno run --allow-env --allow-net app.ts
يقوم Deno بتنزيل التبعيات:
ويبدأ الاستماع على المنفذ 4000.
عند إعادة التشغيل ، سيتم تخطي خطوة التثبيت بفضل التخزين المؤقت:
حدد واجهة للكلب ، ثم حدد مصفوفة
dog
تحتوي على الكائنات Dog
:
interface Dog {
name: string
age: number
}
let dogs: Array<Dog> = [
{
name: 'Roger',
age: 8,
},
{
name: 'Syd',
age: 7,
},
]
لنبدأ في تنفيذ API.
كل شيء في مكانه. دعنا نضيف بعض الوظائف إلى جهاز التوجيه الذي سيتم استدعاؤه عند الوصول إلى نقطة النهاية المحددة:
const router = new Router()
router
.get('/dogs', getDogs)
.get('/dogs/:name', getDog)
.post('/dogs', addDog)
.put('/dogs/:name', updateDog)
.delete('/dogs/:name', removeDog)
لقد حددنا ما يلي:
GET /dogs
GET /dogs/:name
POST /dogs
PUT /dogs/:name
DELETE /dogs/:name
دعونا ننفذ هذه المسارات واحدة تلو الأخرى.
لنبدأ
GET /dogs
، الذي يعرض قائمة بكل الكلاب:
export const getDogs = ({ response }: { response: any }) => {
response.body = dogs
}
إليك كيفية الحصول على كلب معين بالاسم:
export const getDog = ({
params,
response,
}: {
params: {
name: string
},
response: any
}) => {
const dog = dogs.filter(dog => dog.name === params.name)
if (dog.length) {
response.status = 200
response.body = dog[0]
return
}
response.status = 400
response.body = { msg: `Cannot find dog ${params.name}` }
}
إليك كيفية إضافة كلب جديد إلى القائمة:
export const addDog = async ({
request,
response,
}: {
request: any
response: any
}) => {
const body = await request.body()
const dog: Dog = await body.value
dogs.push(dog)
response.body = { msg: 'OK' }
response.status = 200
}
إليك كيفية تحديث عمر كلبك:
export const updateDog = async ({
params,
request,
response,
}: {
params: {
name: string
},
request: any
response: any
}) => {
const temp = dogs.filter((existingDog) => existingDog.name === params.name)
const body = await request.body()
const { age }: { age: number } = await body.value
if (temp.length) {
temp[0].age = age
response.status = 200
response.body = { msg: 'OK' }
return
}
response.status = 400
response.body = { msg: `Cannot find dog ${params.name}` }
}
وإليك طريقة إزالة كلب من القائمة:
export const removeDog = ({
params,
response,
}: {
params: {
name: string
},
response: any
}) => {
const lengthBefore = dogs.length
dogs = dogs.filter((dog) => dog.name !== params.name)
if (dogs.length === lengthBefore) {
response.status = 400
response.body = { msg: `Cannot find dog ${params.name}` }
return
}
response.body = { msg: 'OK' }
response.status = 200
}
كود التطبيق الكامل:
import { Application, Router } from 'https://deno.land/x/oak/mod.ts'
const env = Deno.env.toObject()
const PORT = env.PORT || 4000
const HOST = env.HOST || '127.0.0.1'
interface Dog {
name: string
age: number
}
let dogs: Array<Dog> = [
{
name: 'Roger',
age: 8,
},
{
name: 'Syd',
age: 7,
},
]
export const getDogs = ({ response }: { response: any }) => {
response.body = dogs
}
export const getDog = ({
params,
response,
}: {
params: {
name: string
},
response: any
}) => {
const dog = dogs.filter(dog => dog.name === params.name)
if (dog.length) {
response.status = 200
response.body = dog[0]
return
}
response.status = 400
response.body = { msg: `Cannot find dog ${params.name}` }
}
export const addDog = async ({
request,
response,
}: {
request: any
response: any
}) => {
const body = await request.body()
const { name, age }: { name: string; age: number } = await body.value
dogs.push({
name: name,
age: age,
})
response.body = { msg: 'OK' }
response.status = 200
}
export const updateDog = async ({
params,
request,
response,
}: {
params: {
name: string
},
request: any
response: any
}) => {
const temp = dogs.filter((existingDog) => existingDog.name === params.name)
const body = await request.body()
const { age }: { age: number } = await body.value
if (temp.length) {
temp[0].age = age
response.status = 200
response.body = { msg: 'OK' }
return
}
response.status = 400
response.body = { msg: `Cannot find dog ${params.name}` }
}
export const removeDog = ({
params,
response,
}: {
params: {
name: string
},
response: any
}) => {
const lengthBefore = dogs.length
dogs = dogs.filter(dog => dog.name !== params.name)
if (dogs.length === lengthBefore) {
response.status = 400
response.body = { msg: `Cannot find dog ${params.name}` }
return
}
response.body = { msg: 'OK' }
response.status = 200
}
const router = new Router()
router
.get('/dogs', getDogs)
.get('/dogs/:name', getDog)
.post('/dogs', addDog)
.put('/dogs/:name', updateDog)
.delete('/dogs/:name', removeDog)
const app = new Application()
app.use(router.routes())
app.use(router.allowedMethods())
console.log(`Listening on port ${PORT}...`)
await app.listen(`${HOST}:${PORT}`)
شكرآ لك على أهتمامك.