# Nano ID Nano ID logo by Anton Lovchikov
[English](./README.md) | [日本語](./README.ja.md) | [Русский](./README.ru.md) | [简体中文](./README.zh-CN.md) | [Bahasa Indonesia](./README.id-ID.md) | [한국어](./README.ko.md) | **العربية** مُولِّد مُعرِّفات فريدة صغير الحجم وآمن ومتوافق مع الروابط (URL) لجافاسكربت. > "مستوى مذهل من الكمالية التي لا معنى لها، > والتي يستحيل ألّا تحظى بالاحترام." - **صغير الحجم.** 118 بايت فقط (بعد التصغير والضغط ببروتلي). بدون أيّ اعتماديات خارجية. يتم التحكّم بالحجم عبر [Size Limit]. - **سريع.** أسرع بنسبة 50% من `crypto.randomUUID()` الأصلية. - **آمن.** يستخدم مُولِّد أرقام عشوائية على مستوى العتاد. يمكن استخدامه في بيئات الكلستر. - **مُعرِّفات قصيرة.** يستخدم أبجدية أكبر من UUID وهي (`A-Za-z0-9_-`). لذا تم تقليص حجم المُعرِّف من 36 إلى 21 رمزًا. - **قابل للنقل.** تم نقل Nano ID إلى أكثر من [20 لغة برمجة](./README.md#other-programming-languages).
```js import { nanoid } from 'nanoid' model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT" ``` --- Made at Evil Martians, product consulting for developer tools. --- [Size Limit]: https://github.com/ai/size-limit
## جدول المحتويات - [جدول المحتويات](#جدول-المحتويات) - [المقارنة مع UUID](#المقارنة-مع-uuid) - [اختبار الأداء](#اختبار-الأداء) - [الأمان](#الأمان) - [التثبيت](#التثبيت) - [JSR](#jsr) - [CDN](#cdn) - [واجهة البرمجة (API)](#واجهة-البرمجة-api) - [أبجدية أو حجم مخصّص](#أبجدية-أو-حجم-مخصّص) - [مُولِّد بايتات عشوائية مخصّص](#مُولِّد-بايتات-عشوائية-مخصّص) - [غير آمن (Non-Secure)](#غير-آمن-non-secure) - [الاستخدام](#الاستخدام) - [React](#react) - [React Native](#react-native) - [PouchDB و CouchDB](#pouchdb-و-couchdb) - [سطر الأوامر (CLI)](#سطر-الأوامر-cli) - [TypeScript](#typescript) - [لغات البرمجة الأخرى](#لغات-البرمجة-الأخرى) - [الأدوات](#الأدوات) ## المقارنة مع UUID Nano ID قابل للمقارنة مع UUID v4 (المبني على العشوائية). يحتوي على عدد مماثل من البتّات العشوائية في المُعرِّف (126 في Nano ID و122 في UUID)، لذا فإنّ احتمالية التكرار متقاربة: > لكي تكون هناك فرصة واحدة من مليار لحدوث تكرار، > يجب توليد 103 تريليون مُعرِّف من النوع v4. يوجد اختلافان رئيسيان بين Nano ID و UUID v4: 1. يستخدم Nano ID أبجدية أكبر، لذا يتم ضغط عدد مماثل من البتّات العشوائية في 21 رمزًا فقط بدلاً من 36. 2. Nano ID أسرع من `crypto.randomUUID` و`uuid/v4`. ## اختبار الأداء
```rust $ node ./test/benchmark.js nope-id 20,386,830 ops/sec nanoid 20,434,827 ops/sec customAlphabet 20,544,476 ops/sec crypto.randomUUID 12,865,759 ops/sec uuid v4 7,930,104 ops/sec @napi-rs/uuid 5,573,171 ops/sec uid/secure 6,308,267 ops/sec @lukeed/uuid 5,278,597 ops/sec nanoid for browser 311,497 ops/sec secure-random-string 301,667 ops/sec uid-safe.sync 297,815 ops/sec Non-secure: uid 20,286,757 ops/sec nanoid/non-secure 2,397,594 ops/sec rndm 2,445,462 ops/sec ```
## الأمان _اقرأ مقالاً جيداً عن نظرية مُولِّدات الأرقام العشوائية: [Secure random values (in Node.js)]_ - **عدم القابلية للتنبؤ.** بدلاً من استخدام `Math.random()` غير الآمن، يستخدم Nano ID وحدة `crypto` في Node.js و Web Crypto API في المتصفحات. هذه الوحدات تستخدم مُولِّد أرقام عشوائية على مستوى العتاد لا يمكن التنبؤ به. - **التوزيع المنتظم.** `random % alphabet` هو خطأ شائع عند برمجة مُولِّد مُعرِّفات. التوزيع لن يكون متساويًا؛ بعض الرموز ستظهر بتواتر أقل من غيرها. وهذا يقلّل عدد المحاولات اللازمة للكسر بالقوة الغاشمة. يستخدم Nano ID [خوارزمية أفضل] وقد تم اختباره للتحقّق من انتظام التوزيع. انتظام توزيع Nano ID - **موثّق جيداً:** جميع الحيل البرمجية في Nano ID موثّقة. اطّلع على التعليقات في [الكود المصدري]. - **الثغرات الأمنية:** للإبلاغ عن ثغرة أمنية، يُرجى استخدام [جهة اتصال Tidelift الأمنية](https://tidelift.com/security). سيقوم Tidelift بتنسيق الإصلاح والإفصاح. [Secure random values (in Node.js)]: https://gist.github.com/joepie91/7105003c3b26e65efcea63f3db82dfba [خوارزمية أفضل]: https://github.com/ai/nanoid/blob/main/index.js [الكود المصدري]: https://github.com/ai/nanoid/blob/main/index.js ## التثبيت
```bash npm install nanoid ```
### JSR [JSR](https://jsr.io) هو بديل لـ npm بحوكمة مفتوحة وتطوير نشط (على عكس npm).
```bash npx jsr add @sitnik/nanoid ```
يمكنك استخدامه في Node.js و Deno و Bun وغيرها.
```js // استبدل `nanoid` بـ `@sitnik/nanoid` في جميع الاستيرادات import { nanoid } from '@sitnik/nanoid' ```
لـ Deno ثبّته عبر `deno add jsr:@sitnik/nanoid` أو استورده من `jsr:@sitnik/nanoid`. ### CDN للتجارب السريعة، يمكنك تحميل Nano ID من CDN. لكن لا يُنصح باستخدامه في الإنتاج بسبب انخفاض أداء التحميل.
```js import { nanoid } from 'https://cdn.jsdelivr.net/npm/nanoid/nanoid.js' ```
## واجهة البرمجة (API) بشكل افتراضي، يستخدم Nano ID رموزًا متوافقة مع الروابط (`A-Za-z0-9_-`) ويُنتج مُعرِّفًا مكوّنًا من 21 حرفًا (ليكون احتمال التكرار مماثلاً لـ UUID v4).
```js import { nanoid } from 'nanoid' model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT" ```
إذا أردت تقليل حجم المُعرِّف (وزيادة احتمالية التكرار)، يمكنك تمرير الحجم كمعامل.
```js nanoid(10) //=> "IRFa-VaY2b" ```
لا تنسَ التحقّق من أمان حجم المُعرِّف الخاص بك عبر حاسبة [احتمالية تكرار المُعرِّف]. يمكنك أيضًا استخدام [أبجدية مخصّصة](#أبجدية-أو-حجم-مخصّص) أو [مُولِّد أرقام عشوائية مخصّص](#مُولِّد-بايتات-عشوائية-مخصّص). [احتمالية تكرار المُعرِّف]: https://zelark.github.io/nano-id-cc/ ### أبجدية أو حجم مخصّص تُرجع `customAlphabet` دالة تتيح لك إنشاء `nanoid` بأبجديتك وحجمك الخاصّين.
```js import { customAlphabet } from 'nanoid' const nanoid = customAlphabet('1234567890abcdef', 10) model.id = nanoid() //=> "4f90d13a42" ``` ```js import { customAlphabet } from 'nanoid/non-secure' const nanoid = customAlphabet('1234567890abcdef', 10) user.id = nanoid() ```
تحقّق من أمان أبجديتك المخصّصة وحجم المُعرِّف عبر حاسبة [احتمالية تكرار المُعرِّف]. لمزيد من خيارات الأبجديات، اطّلع على [`nanoid-dictionary`]. يجب أن تحتوي الأبجدية على 256 رمزًا أو أقل. وإلا فإن أمان خوارزمية المُولِّد الداخلية غير مضمون. بالإضافة إلى تحديد حجم افتراضي، يمكنك تغيير حجم المُعرِّف عند استدعاء الدالة:
```js import { customAlphabet } from 'nanoid' const nanoid = customAlphabet('1234567890abcdef', 10) model.id = nanoid(5) //=> "f01a2" ``` [احتمالية تكرار المُعرِّف]: https://zelark.github.io/nano-id-cc/ [`nanoid-dictionary`]: https://github.com/CyberAP/nanoid-dictionary
### مُولِّد بايتات عشوائية مخصّص تتيح لك `customRandom` إنشاء `nanoid` واستبدال الأبجدية ومُولِّد البايتات العشوائية الافتراضي. في هذا المثال، يتم استخدام مُولِّد مبني على بذرة (seed):
```js import { customRandom } from 'nanoid' const rng = seedrandom(seed) const nanoid = customRandom('abcdef', 10, size => { return new Uint8Array(size).map(() => 256 * rng()) }) nanoid() //=> "fbaefaadeb" ```
يجب أن تقبل دالة `random` حجم المصفوفة وتُرجع مصفوفة من الأرقام العشوائية. إذا أردت استخدام نفس الرموز المتوافقة مع الروابط مع `customRandom`، يمكنك الحصول على الأبجدية الافتراضية عبر `urlAlphabet`.
```js const { customRandom, urlAlphabet } = require('nanoid') const nanoid = customRandom(urlAlphabet, 10, random) ```
ملاحظة: بين إصدارات Nano ID قد يتغيّر تسلسل استدعاء مُولِّد الأرقام العشوائية. إذا كنت تستخدم مُولِّدات مبنية على بذرة، فإننا لا نضمن نفس النتيجة. ### غير آمن (Non-Secure) بشكل افتراضي، يستخدم Nano ID توليد بايتات عشوائية على مستوى العتاد من أجل الأمان وتقليل احتمالية التكرار. إذا لم يكن الأمان مهمًا بالنسبة لك، يمكنك استخدامه في بيئات لا تتوفر فيها مُولِّدات أرقام عشوائية على مستوى العتاد.
```js import { nanoid } from 'nanoid/non-secure' const id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqLJ" ```
لاحظ أن النسخة غير الآمنة _أبطأ_ من النسخة الآمنة. استخدمها فقط إذا اضطُررت إلى ذلك. ## الاستخدام ### React لا توجد طريقة صحيحة لاستخدام Nano ID كخاصية `key` في React لأنها يجب أن تكون ثابتة بين عمليات التصيير (renders).
```jsx function Todos({ todos }) { return ( ) } ```
يجب عليك بدلاً من ذلك استخدام مُعرِّف ثابت من داخل عنصر القائمة.
```jsx const todoItems = todos.map(todo =>
  • {todo.text}
  • ) ```
    في حال لم تمتلك مُعرِّفات ثابتة، يُفضّل استخدام الفهرس (index) كـ `key` بدلاً من `nanoid()`:
    ```jsx const todoItems = todos.map((text, index) => (
  • {' '} /* غير مُوصى به لكنه أفضل من nanoid(). استخدمه فقط إذا لم تكن لديك مُعرِّفات ثابتة. */ {text}
  • )) ```
    إذا كنت تحتاج فقط إلى مُعرِّفات عشوائية لربط العناصر ببعضها مثل labels وحقول الإدخال، يُنصح باستخدام [`useId`]. تمت إضافة هذا الـ hook في React 18. [`useId`]: https://react.dev/reference/react/useId ### React Native لا يحتوي React Native على مُولِّد أرقام عشوائية مدمج. يعمل البوليفِل التالي مع React Native العادي و Expo بدءًا من الإصدار `39.x`. 1. اطّلع على توثيق [`react-native-get-random-values`] وثبّتها. 2. استوردها قبل Nano ID.
    ```js import 'react-native-get-random-values' import { nanoid } from 'nanoid' ``` [`react-native-get-random-values`]: https://github.com/LinusU/react-native-get-random-values
    ### PouchDB و CouchDB في PouchDB و CouchDB، لا يمكن أن تبدأ المُعرِّفات بشرطة سفلية `_`. يلزم إضافة بادئة لتجنّب هذه المشكلة، لأن Nano ID قد يستخدم `_` في بداية المُعرِّف بشكل افتراضي. أَعِد تعريف المُعرِّف الافتراضي بالخيار التالي:
    ```js db.put({ _id: 'id' + nanoid(), … }) ```
    ### سطر الأوامر (CLI) يمكنك الحصول على مُعرِّف فريد في الطرفية عبر تشغيل `npx nanoid`. تحتاج فقط إلى Node.js مثبّتًا على النظام. لا يلزم تثبيت Nano ID مسبقًا.
    ```sh $ npx nanoid npx: installed 1 in 0.63s LZfXLFzPPR4NNrgjlWDxn ```
    يمكن تحديد حجم المُعرِّف المُولَّد عبر خيار `--size` (أو `-s`):
    ```sh $ npx nanoid --size 10 L3til0JS4z ```
    يمكن تحديد أبجدية مخصّصة عبر خيار `--alphabet` (أو `-a`) (لاحظ أن `--size` مطلوب في هذه الحالة):
    ```sh $ npx nanoid --alphabet abc --size 15 bccbcabaabaccab ```
    ### TypeScript يتيح Nano ID تحويل النصوص المُولَّدة إلى أنواع مبهمة (opaque types) في TypeScript. مثال:
    ```ts declare const userIdBrand: unique symbol type UserId = string & { [userIdBrand]: true } // استخدم معامل النوع الصريح: mockUser(nanoid()) interface User { id: UserId name: string } const user: User = { // يتم التحويل تلقائيًا إلى UserId: id: nanoid(), name: 'Alice' } ```
    ### لغات البرمجة الأخرى تم نقل Nano ID إلى العديد من اللغات. يمكنك استخدام هذه الإصدارات للحصول على نفس مُولِّد المُعرِّفات على جانبَي العميل والخادم.
    - [C](https://github.com/lukateras/nanoid.h) - [C#](https://github.com/codeyu/nanoid-net) - [C++](https://github.com/mcmikecreations/nanoid_cpp) - [Clojure and ClojureScript](https://github.com/zelark/nano-id) - [ColdFusion/CFML](https://github.com/JamoCA/cfml-nanoid) - [Crystal](https://github.com/mamantoha/nanoid.cr) - [Dart & Flutter](https://github.com/pd4d10/nanoid-dart) - [Elixir](https://github.com/railsmechanic/nanoid) - [Gleam](https://github.com/0xca551e/glanoid) - [Go](https://github.com/matoous/go-nanoid) - [Haskell](https://github.com/MichelBoucey/NanoID) - [Haxe](https://github.com/flashultra/uuid) - [Janet](https://sr.ht/~statianzo/janet-nanoid/) - [Java](https://github.com/wosherco/jnanoid-enhanced) - [Kotlin](https://github.com/viascom/nanoid-kotlin) - [MySQL/MariaDB](https://github.com/viascom/nanoid-mysql-mariadb) - [Nim](https://github.com/icyphox/nanoid.nim) - [OCaml](https://github.com/routineco/ocaml-nanoid) - [Perl](https://github.com/tkzwtks/Nanoid-perl) - [PHP](https://github.com/hidehalo/nanoid-php) - Python [native](https://github.com/puyuan/py-nanoid) implementation with [dictionaries](https://pypi.org/project/nanoid-dictionary) and [fast](https://github.com/oliverlambson/fastnanoid) implementation (written in Rust) - Postgres [Extension](https://github.com/spa5k/uids-postgres) and [Native Function](https://github.com/viascom/nanoid-postgres) - [R](https://github.com/hrbrmstr/nanoid) (with dictionaries) - [Ruby](https://github.com/radeno/nanoid.rb) - [Rust](https://github.com/nikolay-govorov/nanoid) - [Swift](https://github.com/ShivaHuang/swift-nanoid) - [Unison](https://share.unison-lang.org/latest/namespaces/hojberg/nanoid) - [V](https://github.com/invipal/nanoid) - [Zig](https://github.com/SasLuca/zig-nanoid)
    للبيئات الأخرى، يتوفر [سطر الأوامر] لتوليد المُعرِّفات من الطرفية. [سطر الأوامر]: #سطر-الأوامر-cli ## الأدوات - [حاسبة حجم المُعرِّف] تعرض احتمالية التكرار عند تعديل أبجدية المُعرِّف أو حجمه. - [`nanoid-dictionary`] تحتوي على أبجديات شائعة لاستخدامها مع [`customAlphabet`]. - [`nanoid-good`] للتأكد من أن المُعرِّف لا يحتوي على كلمات غير لائقة. [`nanoid-dictionary`]: https://github.com/CyberAP/nanoid-dictionary [حاسبة حجم المُعرِّف]: https://zelark.github.io/nano-id-cc/ [`customAlphabet`]: #أبجدية-أو-حجم-مخصّص [`nanoid-good`]: https://github.com/y-gagar1n/nanoid-good