This file is a merged representation of the entire codebase, combined into a single document by Repomix.
The content has been processed where comments have been removed, empty lines have been removed, line numbers have been added.
This section contains a summary of this file.
This file contains a packed representation of the entire repository's contents.
It is designed to be easily consumable by AI systems for analysis, code review,
or other automated processes.
The content is organized as follows:
1. This summary section
2. Repository information
3. Directory structure
4. Repository files (if enabled)
5. Multiple file entries, each consisting of:
- File path as an attribute
- Full contents of the file
- This file should be treated as read-only. Any changes should be made to the
original repository files, not this packed version.
- When processing this file, use the file path to distinguish
between different files in the repository.
- Be aware that this file may contain sensitive information. Handle it with
the same level of security as you would the original repository.
- Some files may have been excluded based on .gitignore rules and Repomix's configuration
- Binary files are not included in this packed representation. Please refer to the Repository Structure section for a complete list of file paths, including binary files
- Files matching patterns in .gitignore are excluded
- Files matching default ignore patterns are excluded
- Code comments have been removed from supported file types
- Empty lines have been removed from all files
- Line numbers have been added to the beginning of each line
- Files are sorted by Git change count (files with more changes are at the bottom)
database/index.ts
database/relations/address-predefined.relations.ts
database/relations/address.relations.ts
database/relations/attribute.relations.ts
database/relations/brand.relations.ts
database/relations/campaign.relations.ts
database/relations/category.relations.ts
database/relations/country.relations.ts
database/relations/index.ts
database/relations/option.relations.ts
database/relations/price-history.relations.ts
database/relations/product-attribute.relations.ts
database/relations/product-variant-option.relations.ts
database/relations/product-variant.relations.ts
database/relations/product.relations.ts
database/relations/stock-movement.relations.ts
database/relations/upload.relations.ts
database/relations/user-avatar.relations.ts
database/relations/user.relations.ts
database/schemas/address-predefined.schema.ts
database/schemas/address.schema.ts
database/schemas/attribute.schema.ts
database/schemas/base.schema.ts
database/schemas/brand.schema.ts
database/schemas/campaign-product.schema.ts
database/schemas/campaign.schema.ts
database/schemas/category.schema.ts
database/schemas/country.schema.ts
database/schemas/index.ts
database/schemas/option.schema.ts
database/schemas/otp.schema.ts
database/schemas/price-history.schema.ts
database/schemas/product-attribute.schema.ts
database/schemas/product-image.schema.ts
database/schemas/product-variant-option.schema.ts
database/schemas/product-variant.schema.ts
database/schemas/product.schema.ts
database/schemas/stock-movement.schema.ts
database/schemas/upload.schema.ts
database/schemas/user-avatar.schema.ts
database/schemas/user.schema.ts
database/seeders/address-predefined.seeder.ts
database/seeders/country.seeder.ts
database/seeders/data/address-predefined.de.seed.json
database/seeders/data/address-predefined.ir.seed.json
database/seeders/data/countries.seed.json
database/seeders/index.ts
database/seeders/schemas.ts
database/seeders/truncate.ts
infra/postgres.ts
infra/redis.ts
services/auth/backoffice/auth.service.ts
services/auth/backoffice/constants.ts
services/auth/credentials.service.ts
services/session/session.service.ts
services/translation/load.ts
services/translation/types.ts
services/translation/watch.ts
services/upload/upload.errors.ts
services/upload/upload.helpers.ts
services/upload/upload.service.ts
services/upload/upload.types.ts
tests/setup/db.ts
tests/setup/global.ts
tests/setup/reset.ts
validators/auth.validator.ts
This section contains the contents of the repository's files.
1: import {postgres} from "@/server/infra/postgres";
2: export const db = postgres
1: import { defineRelationsPart } from 'drizzle-orm';
2: import * as schema from '@/server/database/schemas';
3: export const addressPredefinedValueRelations = defineRelationsPart(schema, (r) => ({
4: addressPredefined: {
5: country: r.one.countries({
6: from: r.addressPredefined.countryCode,
7: to: r.countries.code,
8: }),
9: parent: r.one.addressPredefined({
10: from: r.addressPredefined.parentId,
11: to: r.addressPredefined.id,
12: alias: 'address_predefined_value_hierarchy',
13: }),
14: children: r.many.addressPredefined({
15: from: r.addressPredefined.id,
16: to: r.addressPredefined.parentId,
17: alias: 'address_predefined_value_hierarchy',
18: }),
19: },
20: }));
1: import { defineRelationsPart } from 'drizzle-orm';
2: import * as schema from '@/server/database/schemas';
3: export const addressRelations = defineRelationsPart(schema, (r) => ({
4: addresses: {
5: user: r.one.users({
6: from: r.addresses.userId,
7: to: r.users.id,
8: }),
9: country: r.one.countries({
10: from: r.addresses.countryCode,
11: to: r.countries.code,
12: }),
13: },
14: }));
1: import { defineRelations } from 'drizzle-orm';
2: import * as schema from '@/server/database/schemas';
3: export const attributeRelations = defineRelations(schema, (r) => ({
4: attributes: {
5: options: r.many.options({
6: from: r.attributes.id,
7: to: r.options.attributeId,
8: }),
9: productAttributes: r.many.productAttributes({
10: from: r.attributes.id,
11: to: r.productAttributes.attributeId,
12: }),
13: },
14: }));
1: import { defineRelations } from 'drizzle-orm';
2: import * as schema from '@/server/database/schemas';
3: export const brandRelations = defineRelations(schema, (r) => ({
4: brands: {
5: country: r.one.countries({
6: from: r.brands.countryCode,
7: to: r.countries.code,
8: }),
9: logo: r.one.uploads({
10: from: r.brands.logoUploadId,
11: to: r.uploads.id,
12: }),
13: products: r.many.products({
14: from: r.brands.id,
15: to: r.products.brandId,
16: }),
17: },
18: }));
1: import { defineRelations } from 'drizzle-orm';
2: import * as schema from '@/server/database/schemas';
3: export const campaignRelations = defineRelations(schema, (r) => ({
4: campaigns: {
5: campaignProducts: r.many.campaignProducts({
6: from: r.campaigns.id,
7: to: r.campaignProducts.campaignId,
8: }),
9: },
10: campaignProducts: {
11: campaign: r.one.campaigns({
12: from: r.campaignProducts.campaignId,
13: to: r.campaigns.id,
14: }),
15: variant: r.one.productVariants({
16: from: r.campaignProducts.variantId,
17: to: r.productVariants.id,
18: }),
19: },
20: }));
1: import { defineRelations } from 'drizzle-orm';
2: import * as schema from '@/server/database/schemas';
3: export const categoryRelations = defineRelations(schema, (r) => ({
4: categories: {
5: parent: r.one.categories({
6: from: r.categories.parentId,
7: to: r.categories.id,
8: }),
9: children: r.many.categories({
10: from: r.categories.id,
11: to: r.categories.parentId,
12: }),
13: products: r.many.products({
14: from: r.categories.id,
15: to: r.products.categoryId,
16: }),
17: },
18: }));
1: import { defineRelationsPart } from 'drizzle-orm';
2: import * as schema from '@/server/database/schemas';
3: export const countryRelations = defineRelationsPart(schema, (r) => ({
4: countries: {
5: addresses: r.many.addresses({
6: from: r.countries.code,
7: to: r.addresses.countryCode,
8: }),
9: addressPredefined: r.many.addressPredefined({
10: from: r.countries.code,
11: to: r.addressPredefined.countryCode,
12: }),
13: },
14: }));
1: import { defineRelations } from 'drizzle-orm';
2: import * as schema from '@/server/database/schemas';
3: import { userRelations } from './user.relations';
4: import { countryRelations } from './country.relations';
5: import { addressRelations } from './address.relations';
6: import { addressPredefinedValueRelations } from './address-predefined.relations';
7: import { uploadsRelations } from './upload.relations';
8: import { userAvatarRelations } from './user-avatar.relations';
9: import { productRelations } from './product.relations';
10: import { productVariantOptionRelations } from './product-variant-option.relations';
11: import { categoryRelations } from './category.relations';
12: import { brandRelations } from './brand.relations';
13: import { attributeRelations } from './attribute.relations';
14: import { optionRelations } from './option.relations';
15: import { productAttributeRelations } from './product-attribute.relations';
16: import {priceHistoryRelations} from "./price-history.relations";
17: import {stockMovementRelations} from "./stock-movement.relations";
18: import {campaignRelations} from "./campaign.relations";
19: const mainRelations = defineRelations(schema, () => ({}));
20: export const relations = {
21: ...mainRelations,
22: ...uploadsRelations,
23: ...userRelations,
24: ...userAvatarRelations,
25: ...countryRelations,
26: ...addressRelations,
27: ...addressPredefinedValueRelations,
28: ...productRelations,
29: ...productVariantOptionRelations,
30: ...categoryRelations,
31: ...brandRelations,
32: ...attributeRelations,
33: ...optionRelations,
34: ...productAttributeRelations,
35: ...priceHistoryRelations,
36: ...stockMovementRelations,
37: ...campaignRelations,
38: };
1: import { defineRelations } from 'drizzle-orm';
2: import * as schema from '@/server/database/schemas';
3: export const optionRelations = defineRelations(schema, (r) => ({
4: options: {
5: attribute: r.one.attributes({
6: from: r.options.attributeId,
7: to: r.attributes.id,
8: }),
9: productAttributes: r.many.productAttributes({
10: from: r.options.id,
11: to: r.productAttributes.optionId,
12: }),
13: variantOptions: r.many.productVariantOptions({
14: from: r.options.id,
15: to: r.productVariantOptions.optionId,
16: }),
17: },
18: }));
1: import { defineRelations } from 'drizzle-orm';
2: import * as schema from '@/server/database/schemas';
3: export const priceHistoryRelations = defineRelations(schema, (r) => ({
4: priceHistory: {
5: variant: r.one.productVariants({ from: r.priceHistory.variantId, to: r.productVariants.id }),
6: changedByUser: r.one.users({ from: r.priceHistory.changedBy, to: r.users.id }),
7: },
8: }));
1: import { defineRelations } from 'drizzle-orm';
2: import * as schema from '@/server/database/schemas';
3: export const productAttributeRelations = defineRelations(schema, (r) => ({
4: productAttributes: {
5: product: r.one.products({
6: from: r.productAttributes.productId,
7: to: r.products.id,
8: }),
9: attribute: r.one.attributes({
10: from: r.productAttributes.attributeId,
11: to: r.attributes.id,
12: }),
13: option: r.one.options({
14: from: r.productAttributes.optionId,
15: to: r.options.id,
16: }),
17: },
18: }));
1: import { defineRelations } from 'drizzle-orm';
2: import * as schema from '@/server/database/schemas';
3: export const productVariantOptionRelations = defineRelations(schema, (r) => ({
4: productVariantOptions: {
5: variant: r.one.productVariants({
6: from: r.productVariantOptions.variantId,
7: to: r.productVariants.id,
8: }),
9: option: r.one.options({
10: from: r.productVariantOptions.optionId,
11: to: r.options.id,
12: }),
13: },
14: }));
1: import { defineRelations } from 'drizzle-orm';
2: import * as schema from '@/server/database/schemas';
3: export const productVariantRelations = defineRelations(schema, (r) => ({
4: products: {
5: variants: r.many.productVariants({
6: from: r.products.id,
7: to: r.productVariants.productId,
8: }),
9: },
10: productVariants: {
11: product: r.one.products({
12: from: r.productVariants.productId,
13: to: r.products.id,
14: }),
15: variantOptions: r.many.productVariantOptions({
16: from: r.productVariants.id,
17: to: r.productVariantOptions.variantId,
18: }),
19: },
20: }));
1: import {defineRelations} from 'drizzle-orm';
2: import * as schema from '@/server/database/schemas';
3: export const productRelations = defineRelations(schema, (r) => ({
4: products: {
5: category: r.one.categories({
6: from: r.products.categoryId,
7: to: r.categories.id,
8: }),
9: brand: r.one.brands({
10: from: r.products.brandId,
11: to: r.brands.id,
12: }),
13: images: r.many.productImages({
14: from: r.products.id,
15: to: r.productImages.productId,
16: }),
17: attributes: r.many.productAttributes({
18: from: r.products.id,
19: to: r.productAttributes.productId,
20: }),
21: variants: r.many.productVariants({
22: from: r.products.id,
23: to: r.productVariants.productId,
24: }),
25: },
26: productVariants: {
27: product: r.one.products({
28: from: r.productVariants.productId,
29: to: r.products.id,
30: }),
31: variantOptions: r.many.productVariantOptions({
32: from: r.productVariants.id,
33: to: r.productVariantOptions.variantId,
34: }),
35: priceHistory: r.many.priceHistory({
36: from: r.productVariants.id,
37: to: r.priceHistory.variantId
38: }),
39: stockMovements: r.many.stockMovements({
40: from: r.productVariants.id,
41: to: r.stockMovements.variantId
42: }),
43: campaignProducts: r.many.campaignProducts({
44: from: r.productVariants.id,
45: to: r.campaignProducts.variantId
46: }),
47: },
48: }));
1: import { defineRelations } from 'drizzle-orm';
2: import * as schema from '@/server/database/schemas';
3: export const stockMovementRelations = defineRelations(schema, (r) => ({
4: stockMovements: {
5: variant: r.one.productVariants({
6: from: r.stockMovements.variantId,
7: to: r.productVariants.id,
8: }),
9: createdByUser: r.one.users({
10: from: r.stockMovements.createdBy,
11: to: r.users.id,
12: }),
13: },
14: }));
1: import { defineRelationsPart } from "drizzle-orm";
2: import * as schema from '@/server/database/schemas';
3: export const uploadsRelations = defineRelationsPart(schema, (r) => ({
4: uploads: {
5: uploadedByUser: r.one.users({
6: from: r.uploads.uploadedBy,
7: to: r.users.id,
8: }),
9: },
10: }));
1: import { defineRelationsPart } from 'drizzle-orm';
2: import * as schema from '@/server/database/schemas';
3: export const userAvatarRelations = defineRelationsPart(schema, (r) => ({
4: userAvatars: {
5: user: r.one.users({
6: from: r.userAvatars.userId,
7: to: r.users.id,
8: }),
9: upload: r.one.uploads({
10: from: r.userAvatars.uploadId,
11: to: r.uploads.id,
12: }),
13: },
14: }));
1: import { defineRelationsPart } from 'drizzle-orm';
2: import * as schema from '@/server/database/schemas';
3: export const userRelations = defineRelationsPart(schema, (r) => ({
4: users: {
5: addresses: r.many.addresses({
6: from: r.users.id,
7: to: r.addresses.userId,
8: }),
9: avatar: r.one.userAvatars({
10: from: r.users.id,
11: to: r.userAvatars.userId,
12: }),
13: },
14: }));
1: import { sql } from 'drizzle-orm';
2: import { pgEnum, uuid, varchar, jsonb, char, uniqueIndex } from 'drizzle-orm/pg-core';
3: import type { AnyPgColumn } from 'drizzle-orm/pg-core';
4: import {baseTable, LocalizedLabel} from './base.schema';
5: import { countries } from './country.schema';
6: export const addressFieldEnum = pgEnum('address_field', [
7: 'administrative_area',
8: 'locality',
9: 'dependent_locality',
10: ]);
11: export const addressPredefined = baseTable(
12: 'address_predefined',
13: {
14: parentId: uuid('parent_id').references((): AnyPgColumn => addressPredefined.id),
15: field: addressFieldEnum('field').notNull(),
16: key: varchar('key', { length: 255 }).notNull(),
17: name: jsonb('name').$type().notNull(),
18: countryCode: char('country_code', { length: 2 })
19: .notNull()
20: .references(() => countries.code),
21: },
22: (table) => [
23: uniqueIndex('address_predefined_scope_key_idx').on(
24: table.countryCode,
25: table.field,
26: table.parentId,
27: table.key
28: ),
29: uniqueIndex('address_predefined_values_root_key_idx')
30: .on(table.countryCode, table.field, table.key)
31: .where(sql`${table.parentId} IS NULL`),
32: ]
33: );
34: export type AddressPredefined = typeof addressPredefined.$inferSelect;
35: export type NewAddressPredefined = typeof addressPredefined.$inferInsert;
1: import { boolean, char, decimal, text, uuid, varchar } from 'drizzle-orm/pg-core';
2: import { baseTable } from './base.schema';
3: import { users } from './user.schema';
4: import { countries } from './country.schema';
5: export const addresses = baseTable('addresses', {
6: userId: uuid('user_id').references(() => users.id),
7: countryCode: char('country_code', { length: 2 })
8: .notNull()
9: .references(() => countries.code),
10: recipientName: varchar('recipient_name', { length: 255 }),
11: organization: varchar('organization', { length: 255 }),
12: addressLine1: varchar('address_line1', { length: 255 }),
13: addressLine2: varchar('address_line2', { length: 255 }),
14: dependentLocality: varchar('dependent_locality', { length: 255 }),
15: locality: varchar('locality', { length: 255 }),
16: administrativeArea: varchar('administrative_area', { length: 255 }),
17: postalCode: varchar('postal_code', { length: 20 }),
18: sortingCode: varchar('sorting_code', { length: 20 }),
19: formattedAddress: text('formatted_address'),
20: latitude: decimal('latitude', { precision: 10, scale: 7 }),
21: longitude: decimal('longitude', { precision: 10, scale: 7 }),
22: phone: varchar('phone', { length: 30 }),
23: email: varchar('email', { length: 255 }),
24: label: varchar('label', { length: 50 }),
25: isVerified: boolean('is_verified').default(false),
26: isDefault: boolean('is_default').default(false).notNull(),
27: });
28: export type Address = typeof addresses.$inferSelect;
29: export type NewAddress = typeof addresses.$inferInsert;
1: import { jsonb } from 'drizzle-orm/pg-core';
2: import { baseTable, type LocalizedLabel } from './base.schema';
3: export const attributes = baseTable('attributes', {
4: name: jsonb('name').$type().notNull(),
5: });
6: export type Attribute = typeof attributes.$inferSelect;
7: export type NewAttribute = typeof attributes.$inferInsert;
1: import { pgTable } from 'drizzle-orm/pg-core';
2: import type { AnyPgColumnBuilder } from 'drizzle-orm/pg-core';
3: import { uuidv7 } from 'uuidv7';
4: import { uuid, timestamp } from 'drizzle-orm/pg-core';
5: export const idColumn = {
6: id: uuid('id').primaryKey().$defaultFn(() => uuidv7()),
7: };
8: export const timestampColumns = {
9: createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
10: updatedAt: timestamp('updated_at', { withTimezone: true })
11: .defaultNow()
12: .notNull()
13: .$onUpdate(() => new Date()),
14: deletedAt: timestamp('deleted_at', { withTimezone: true }),
15: };
16: export function baseTable>(
17: name: string,
18: columns: T,
19: extraConfig?: (table: ReturnType>) => unknown
20: ) {
21: return pgTable(
22: name,
23: {
24: ...idColumn,
25: ...columns,
26: ...timestampColumns,
27: },
28: extraConfig as never
29: );
30: }
31: export type LocalizedLabel = Record;
1: import {jsonb, char, uuid} from 'drizzle-orm/pg-core';
2: import { baseTable, type LocalizedLabel } from './base.schema';
3: import { countries } from './country.schema';
4: import {uploads} from "@/server/database/schemas/upload.schema";
5: export const brands = baseTable('brands', {
6: name: jsonb('name').$type().notNull(),
7: description: jsonb('description').$type(),
8: countryCode: char('country_code', { length: 2 }).references(() => countries.code, {
9: onDelete: 'set null',
10: }),
11: logoUploadId: uuid("logo_upload_id").references(() => uploads.id),
12: });
13: export type Brand = typeof brands.$inferSelect;
14: export type NewBrand = typeof brands.$inferInsert;
1: import { uuid, varchar, integer, unique } from 'drizzle-orm/pg-core';
2: import { baseTable } from './base.schema';
3: import { campaigns } from './campaign.schema';
4: import { productVariants } from './product-variant.schema';
5: import { type DiscountType } from './campaign.schema';
6: export const campaignProducts = baseTable(
7: 'campaign_products',
8: {
9: campaignId: uuid('campaign_id').notNull().references(() => campaigns.id),
10: variantId: uuid('variant_id').notNull().references(() => productVariants.id),
11: discountType: varchar('discount_type', { length: 20 }).$type(),
12: discountValue: integer('discount_value'),
13: },
14: (table) => [
15: unique('campaign_variant_unique').on(table.campaignId, table.variantId),
16: ]
17: );
18: export type CampaignProduct = typeof campaignProducts.$inferSelect;
19: export type NewCampaignProduct = typeof campaignProducts.$inferInsert;
1: import { varchar, timestamp, integer, boolean, jsonb } from 'drizzle-orm/pg-core';
2: import { baseTable, type LocalizedLabel } from './base.schema';
3: export const discountTypeValues = ["percentage", "fixed_amount"] as const;
4: export type DiscountType = (typeof discountTypeValues)[number];
5: export const campaigns = baseTable('campaigns', {
6: name: jsonb('name').$type().notNull(),
7: slug: varchar('slug', { length: 255 }).notNull().unique(),
8: startsAt: timestamp('starts_at', { withTimezone: true }).notNull(),
9: endsAt: timestamp('ends_at', { withTimezone: true }).notNull(),
10: isActive: boolean('is_active').notNull().default(true),
11: defaultDiscountType: varchar('default_discount_type', { length: 20 }).$type(),
12: defaultDiscountValue: integer('default_discount_value'),
13: });
14: export type Campaign = typeof campaigns.$inferSelect;
15: export type NewCampaign = typeof campaigns.$inferInsert;
1: import { varchar, jsonb, uuid, index, unique } from 'drizzle-orm/pg-core';
2: import type { AnyPgColumn } from 'drizzle-orm/pg-core';
3: import { baseTable, type LocalizedLabel } from './base.schema';
4: export const categories = baseTable(
5: 'categories',
6: {
7: name: jsonb('name').$type().notNull(),
8: parentId: uuid('parent_id').references((): AnyPgColumn => categories.id),
9: slug: varchar('slug', { length: 255 }).notNull().unique(),
10: },
11: (table) => [
12: index('categories_parent_id_idx').on(table.parentId),
13: unique('categories_id_parent_id_unique').on(table.id, table.parentId),
14: ]
15: );
16: export type Category = typeof categories.$inferSelect;
17: export type NewCategory = typeof categories.$inferInsert;
1: import { pgTable, char, varchar, jsonb, uniqueIndex } from 'drizzle-orm/pg-core';
2: import { sql } from 'drizzle-orm';
3: import type { LocalizedLabel } from './base.schema';
4: export type AddressFieldLabels = {
5: administrativeArea?: LocalizedLabel;
6: locality?: LocalizedLabel;
7: dependentLocality?: LocalizedLabel;
8: postalCode?: LocalizedLabel;
9: sortingCode?: LocalizedLabel;
10: };
11: export const countries = pgTable(
12: 'countries',
13: {
14: code: char('code', { length: 2 }).primaryKey(),
15: name: jsonb('name').$type().notNull(),
16: phoneCode: varchar('phone_code', { length: 5 }).notNull(),
17: addressLabels: jsonb('address_labels').$type(),
18: },
19: (table) => [uniqueIndex('countries_name_en_idx').on(sql`(${table.name}->>'en')`)]
20: );
21: export type Country = typeof countries.$inferSelect;
22: export type NewCountry = typeof countries.$inferInsert;
1: export * from './base.schema';
2: export * from './user.schema';
3: export * from './upload.schema';
4: export * from './user-avatar.schema';
5: export * from './country.schema';
6: export * from './address.schema';
7: export * from './address-predefined.schema';
8: export * from './category.schema';
9: export * from './brand.schema';
10: export * from './product.schema';
11: export * from './product-image.schema';
12: export * from './attribute.schema';
13: export * from './option.schema';
14: export * from './product-attribute.schema';
15: export * from './product-variant.schema';
16: export * from './product-variant-option.schema';
17: export * from './price-history.schema';
18: export * from './stock-movement.schema';
19: export * from './campaign.schema';
20: export * from './campaign-product.schema';
1: import { jsonb, uuid } from 'drizzle-orm/pg-core';
2: import { baseTable, type LocalizedLabel } from './base.schema';
3: import { attributes } from './attribute.schema';
4: export const options = baseTable('options', {
5: attributeId: uuid('attribute_id')
6: .notNull()
7: .references(() => attributes.id),
8: name: jsonb('name').$type().notNull(),
9: });
10: export type Option = typeof options.$inferSelect;
11: export type NewOption = typeof options.$inferInsert;
1: import { pgEnum, uuid, varchar, integer, timestamp, index } from 'drizzle-orm/pg-core';
2: import { baseTable } from './base.schema';
3: import { users } from './user.schema';
4: export const otpChannelEnum = pgEnum('otp_channel', ['email', 'phone']);
5: export const otpPurposeEnum = pgEnum('otp_purpose', [
6: 'email_verification',
7: 'phone_verification',
8: 'password_reset',
9: ]);
10: export const otps = baseTable(
11: 'otps',
12: {
13: userId: uuid('user_id').references(() => users.id),
14: identifier: varchar('identifier', { length: 255 }).notNull(),
15: channel: otpChannelEnum('channel').notNull(),
16: purpose: otpPurposeEnum('purpose').notNull(),
17: codeHash: varchar('code_hash', { length: 255 }).notNull(),
18: attempts: integer('attempts').notNull().default(0),
19: expiresAt: timestamp('expires_at', { withTimezone: true }).notNull(),
20: consumedAt: timestamp('consumed_at', { withTimezone: true }),
21: },
22: (table) => [
23: index('otps_lookup_idx').on(table.identifier, table.channel, table.purpose),
24: ]
25: );
26: export type Otp = typeof otps.$inferSelect;
27: export type NewOtp = typeof otps.$inferInsert;
1: import { bigint, uuid } from 'drizzle-orm/pg-core';
2: import { baseTable } from './base.schema';
3: import { productVariants } from './product-variant.schema';
4: import { users } from './user.schema';
5: export const priceHistory = baseTable('price_history', {
6: variantId: uuid('variant_id')
7: .notNull()
8: .references(() => productVariants.id),
9: oldPrice: bigint('old_price', { mode: 'number' }).notNull(),
10: newPrice: bigint('new_price', { mode: 'number' }).notNull(),
11: changedBy: uuid('changed_by').references(() => users.id),
12: });
13: export type PriceHistory = typeof priceHistory.$inferSelect;
14: export type NewPriceHistory = typeof priceHistory.$inferInsert;
1: import { varchar, uuid } from 'drizzle-orm/pg-core';
2: import { baseTable } from './base.schema';
3: import { products } from './product.schema';
4: import { attributes } from './attribute.schema';
5: import { options } from './option.schema';
6: export const productAttributes = baseTable('product_attributes', {
7: productId: uuid('product_id')
8: .notNull()
9: .references(() => products.id),
10: attributeId: uuid('attribute_id')
11: .notNull()
12: .references(() => attributes.id),
13: optionId: uuid('option_id').references(() => options.id),
14: value: varchar('value', { length: 255 }),
15: });
16: export type ProductAttribute = typeof productAttributes.$inferSelect;
17: export type NewProductAttribute = typeof productAttributes.$inferInsert;
1: import {boolean, uuid, integer} from 'drizzle-orm/pg-core';
2: import { baseTable } from './base.schema';
3: import { products } from './product.schema';
4: import {uploads} from "@/server/database/schemas/upload.schema";
5: export const productImages = baseTable('product_images', {
6: productId: uuid('product_id')
7: .notNull()
8: .references(() => products.id),
9: uploadId: uuid("upload_id").notNull().references(() => uploads.id),
10: position: integer("position").notNull().default(0),
11: isMain: boolean('is_main').notNull().default(false),
12: });
13: export type ProductImage = typeof productImages.$inferSelect;
14: export type NewProductImage = typeof productImages.$inferInsert;
1: import { uuid, unique } from 'drizzle-orm/pg-core';
2: import { baseTable } from './base.schema';
3: import { productVariants } from './product-variant.schema';
4: import { options } from './option.schema';
5: export const productVariantOptions = baseTable(
6: 'product_variant_options',
7: {
8: variantId: uuid('variant_id')
9: .notNull()
10: .references(() => productVariants.id),
11: optionId: uuid('option_id')
12: .notNull()
13: .references(() => options.id),
14: },
15: (table) => [
16: unique('variant_option_unique').on(table.variantId, table.optionId),
17: ]
18: );
19: export type ProductVariantOption = typeof productVariantOptions.$inferSelect;
20: export type NewProductVariantOption = typeof productVariantOptions.$inferInsert;
1: import { varchar, bigint, uuid } from 'drizzle-orm/pg-core';
2: import { baseTable } from './base.schema';
3: import { products } from './product.schema';
4: export const productVariants = baseTable('product_variants', {
5: productId: uuid('product_id')
6: .notNull()
7: .references(() => products.id),
8: sku: varchar('sku', { length: 100 }).notNull().unique(),
9: price: bigint('price', { mode: 'number' }).notNull(),
10: stock: bigint('stock', { mode: 'number' }).notNull().default(0),
11: });
12: export type ProductVariant = typeof productVariants.$inferSelect;
13: export type NewProductVariant = typeof productVariants.$inferInsert;
1: import { jsonb, bigint, uuid } from 'drizzle-orm/pg-core';
2: import { baseTable, type LocalizedLabel } from './base.schema';
3: import { categories } from './category.schema';
4: import { brands } from './brand.schema';
5: export const products = baseTable('products', {
6: code: bigint('code', { mode: 'number' }).notNull(),
7: name: jsonb('name').$type().notNull(),
8: description: jsonb('description').$type(),
9: categoryId: uuid('category_id')
10: .notNull()
11: .references(() => categories.id),
12: brandId: uuid('brand_id').references(() => brands.id),
13: });
14: export type Product = typeof products.$inferSelect;
15: export type NewProduct = typeof products.$inferInsert;
1: import { integer, uuid, varchar } from 'drizzle-orm/pg-core';
2: import { baseTable } from './base.schema';
3: import { productVariants } from './product-variant.schema';
4: import { users } from './user.schema';
5: export const stockMovementReasonValues = [
6: "sale",
7: "restock",
8: "damaged",
9: "returned",
10: "manual_adjustment",
11: ] as const;
12: export type StockMovementReason = (typeof stockMovementReasonValues)[number];
13: export const stockMovements = baseTable('stock_movements', {
14: variantId: uuid('variant_id')
15: .notNull()
16: .references(() => productVariants.id),
17: quantity: integer('quantity').notNull(),
18: balanceAfter: integer('balance_after').notNull(),
19: reason: varchar('reason', { length: 30 }).$type().notNull(),
20: referenceId: uuid('reference_id'),
21: createdBy: uuid('created_by').references(() => users.id),
22: });
23: export type StockMovement = typeof stockMovements.$inferSelect;
24: export type NewStockMovement = typeof stockMovements.$inferInsert;
1: import {varchar, bigint, uuid} from "drizzle-orm/pg-core";
2: import {baseTable} from "./base.schema";
3: import {users} from "./user.schema";
4: export const uploadStatusValues = ["pending", "completed", "failed"] as const;
5: export type UploadStatus = (typeof uploadStatusValues)[number];
6: export const uploads = baseTable("uploads",
7: {
8: bucket: varchar("bucket", {length: 100}).notNull().default("shop-storage"),
9: storageKey: varchar("storage_key", {length: 500}).notNull(),
10: checksum: varchar("checksum", {length: 64}),
11: originalName: varchar("original_name", {length: 255}).notNull(),
12: mimeType: varchar("mime_type", {length: 100}).notNull(),
13: sizeBytes: bigint("size_bytes", {mode: "number"}).notNull(),
14: status: varchar("status", {length: 20})
15: .$type()
16: .notNull()
17: .default("pending"),
18: uploadedBy: uuid('uploaded_by')
19: .notNull()
20: .references(() => users.id),
21: }
22: );
23: export type Upload = typeof uploads.$inferSelect;
24: export type NewUpload = typeof uploads.$inferInsert;
1: import {uuid, uniqueIndex} from "drizzle-orm/pg-core";
2: import {baseTable} from "./base.schema";
3: import {users} from "./user.schema";
4: import {uploads} from "./upload.schema";
5: export const userAvatars = baseTable("user_avatars",
6: {
7: userId: uuid("user_id")
8: .notNull()
9: .references(() => users.id),
10: uploadId: uuid("upload_id")
11: .notNull()
12: .references(() => uploads.id),
13: },
14: (table) => [
15: uniqueIndex('user_avatars_user_id_idx').on(table.userId),
16: ]
17: );
18: export type UserAvatar = typeof userAvatars.$inferSelect;
19: export type NewUserAvatar = typeof userAvatars.$inferInsert;
1: import {varchar, timestamp, uniqueIndex, check} from 'drizzle-orm/pg-core';
2: import { sql } from 'drizzle-orm';
3: import { baseTable } from './base.schema';
4: export const users = baseTable(
5: 'users',
6: {
7: name: varchar('name', { length: 255 }).notNull(),
8: email: varchar('email', { length: 255 }),
9: password: varchar('password', { length: 255 }),
10: emailVerifiedAt: timestamp('email_verified_at', { withTimezone: true }),
11: phone: varchar('phone', { length: 20 }),
12: phoneVerifiedAt: timestamp('phone_verified_at', { withTimezone: true }),
13: },
14: (table) => [
15: uniqueIndex('users_email_idx').on(table.email),
16: uniqueIndex('users_phone_idx').on(table.phone),
17: check('users_email_or_phone_check', sql`${table.email} IS NOT NULL OR ${table.phone} IS NOT NULL`),
18: ]
19: );
20: export type User = typeof users.$inferSelect;
21: export type NewUser = typeof users.$inferInsert;
1: import { z } from 'zod';
2: import { db } from '@/server/database';
3: import { addressPredefined } from '@/server/database/schemas';
4: import { LocalizedLabelSchema } from '@/server/database/seeders/schemas';
5: import deAddressPredefinedSeedData from './data/address-predefined.de.seed.json';
6: import irAddressPredefinedSeedData from './data/address-predefined.ir.seed.json';
7: const fieldEnumSchema = z.enum(['administrative_area', 'locality', 'dependent_locality']);
8: type SeedNode = {
9: field: z.infer;
10: key: string;
11: name: z.infer;
12: children?: SeedNode[];
13: };
14: const seedNodeSchema: z.ZodType = z.lazy(() =>
15: z.object({
16: field: fieldEnumSchema,
17: key: z.string(),
18: name: LocalizedLabelSchema,
19: children: z.array(seedNodeSchema).optional(),
20: })
21: );
22: const addressPredefinedSeedSchema = z.array(
23: seedNodeSchema.and(z.object({ countryCode: z.string().length(2) }))
24: );
25: async function insertNode(
26: node: SeedNode,
27: countryCode: string,
28: parentId: string | null
29: ): Promise {
30: const [inserted] = await db
31: .insert(addressPredefined)
32: .values({
33: countryCode,
34: field: node.field,
35: key: node.key,
36: name: node.name,
37: parentId: parentId ?? undefined,
38: })
39: .onConflictDoNothing()
40: .returning({ id: addressPredefined.id });
41: const id =
42: inserted?.id ??
43: (
44: await db.query.addressPredefined.findFirst({
45: where: {
46: countryCode: countryCode,
47: field: node.field,
48: key: node.key,
49: parentId: parentId ? parentId : { isNull: true },
50: },
51: })
52: )?.id;
53: if (!id) {
54: throw new Error(`Failed to resolve id for ${countryCode}/${node.field}/${node.key}`);
55: }
56: let count = 1;
57: for (const child of node.children ?? []) {
58: count += await insertNode(child, countryCode, id);
59: }
60: return count;
61: }
62: const ADDRESS_PREDEFINED_SEED_SOURCES = [
63: deAddressPredefinedSeedData,
64: irAddressPredefinedSeedData,
65: ] as const;
66: export async function seedAddressPredefined() {
67: const roots = ADDRESS_PREDEFINED_SEED_SOURCES.flatMap(
68: (data) => addressPredefinedSeedSchema.parse(data)
69: );
70: const counts = await Promise.all(
71: roots.map((root) => insertNode(root, root.countryCode, null))
72: );
73: const total = counts.reduce((sum, n) => sum + n, 0);
74: console.log(`Seeded ${total} address predefined values`);
75: }
1: import { z } from 'zod';
2: import { db } from '@/server/database';
3: import { countries } from '@/server/database/schemas';
4: import countrySeedData from './data/countries.seed.json';
5: import { LocalizedLabelSchema } from '@/server/database/seeders/schemas';
6: const countrySeedSchema = z.array(z.object({
7: code: z.string().length(2),
8: name: z.record(z.string(), z.string()),
9: phoneCode: z.string(),
10: addressLabels: z.object({
11: administrativeArea: LocalizedLabelSchema.optional(),
12: locality: LocalizedLabelSchema.optional(),
13: dependentLocality: LocalizedLabelSchema.optional(),
14: postalCode: LocalizedLabelSchema.optional(),
15: sortingCode: LocalizedLabelSchema.optional(),
16: }).optional(),
17: }));
18: export async function seedCountries() {
19: const data = countrySeedSchema.parse(countrySeedData);
20: await db
21: .insert(countries)
22: .values(data)
23: .onConflictDoUpdate({
24: target: countries.code,
25: set: {
26: name: countries.name,
27: phoneCode: countries.phoneCode,
28: addressLabels: countries.addressLabels,
29: },
30: });
31: console.log(`Seeded ${data.length} countries`);
32: }
1: [
2: {
3: "countryCode": "DE",
4: "field": "administrative_area",
5: "key": "baden_wuerttemberg",
6: "name": {
7: "en": "Baden-Württemberg",
8: "fa": "بادن-وورتمبرگ",
9: "de": "Baden-Württemberg"
10: }
11: },
12: {
13: "countryCode": "DE",
14: "field": "administrative_area",
15: "key": "berlin",
16: "name": {
17: "en": "Berlin",
18: "fa": "برلین",
19: "de": "Berlin"
20: }
21: },
22: {
23: "countryCode": "DE",
24: "field": "administrative_area",
25: "key": "brandenburg",
26: "name": {
27: "en": "Brandenburg",
28: "fa": "براندنبورگ",
29: "de": "Brandenburg"
30: }
31: },
32: {
33: "countryCode": "DE",
34: "field": "administrative_area",
35: "key": "bremen",
36: "name": {
37: "en": "Bremen",
38: "fa": "برمن",
39: "de": "Bremen"
40: }
41: },
42: {
43: "countryCode": "DE",
44: "field": "administrative_area",
45: "key": "hamburg",
46: "name": {
47: "en": "Hamburg",
48: "fa": "هامبورگ",
49: "de": "Hamburg"
50: }
51: },
52: {
53: "countryCode": "DE",
54: "field": "administrative_area",
55: "key": "hesse",
56: "name": {
57: "en": "Hesse",
58: "fa": "هسن",
59: "de": "Hessen"
60: }
61: },
62: {
63: "countryCode": "DE",
64: "field": "administrative_area",
65: "key": "lower_saxony",
66: "name": {
67: "en": "Lower Saxony",
68: "fa": "نیدرزاکسن",
69: "de": "Niedersachsen"
70: }
71: },
72: {
73: "countryCode": "DE",
74: "field": "administrative_area",
75: "key": "mecklenburg_vorpommern",
76: "name": {
77: "en": "Mecklenburg-Vorpommern",
78: "fa": "مکلنبورگ-فورپومرن",
79: "de": "Mecklenburg-Vorpommern"
80: }
81: },
82: {
83: "countryCode": "DE",
84: "field": "administrative_area",
85: "key": "north_rhine_westphalia",
86: "name": {
87: "en": "North Rhine-Westphalia",
88: "fa": "نوردراین-وستفالن",
89: "de": "Nordrhein-Westfalen"
90: }
91: },
92: {
93: "countryCode": "DE",
94: "field": "administrative_area",
95: "key": "rhineland_palatinate",
96: "name": {
97: "en": "Rhineland-Palatinate",
98: "fa": "راینلاند-فالتس",
99: "de": "Rheinland-Pfalz"
100: }
101: },
102: {
103: "countryCode": "DE",
104: "field": "administrative_area",
105: "key": "saarland",
106: "name": {
107: "en": "Saarland",
108: "fa": "زارلاند",
109: "de": "Saarland"
110: }
111: },
112: {
113: "countryCode": "DE",
114: "field": "administrative_area",
115: "key": "saxony",
116: "name": {
117: "en": "Saxony",
118: "fa": "زاکسن",
119: "de": "Sachsen"
120: }
121: },
122: {
123: "countryCode": "DE",
124: "field": "administrative_area",
125: "key": "saxony_anhalt",
126: "name": {
127: "en": "Saxony-Anhalt",
128: "fa": "زاکسن-آنهالت",
129: "de": "Sachsen-Anhalt"
130: }
131: },
132: {
133: "countryCode": "DE",
134: "field": "administrative_area",
135: "key": "schleswig_holstein",
136: "name": {
137: "en": "Schleswig-Holstein",
138: "fa": "اشلسویگ-هولشتاین",
139: "de": "Schleswig-Holstein"
140: }
141: },
142: {
143: "countryCode": "DE",
144: "field": "administrative_area",
145: "key": "thuringia",
146: "name": {
147: "en": "Thuringia",
148: "fa": "تورینگن",
149: "de": "Thüringen"
150: }
151: },
152: {
153: "countryCode": "DE",
154: "field": "administrative_area",
155: "key": "bavaria",
156: "name": { "en": "Bavaria", "fa": "باواریا", "de": "Bayern" }
157: }
158: ]
1: [
2: {
3: "countryCode": "IR",
4: "field": "administrative_area",
5: "key": "alborz",
6: "name": {
7: "en": "Alborz",
8: "fa": "البرز",
9: "de": "Alborz"
10: },
11: "children": [
12: {
13: "field": "locality",
14: "key": "chaharbagh",
15: "name": {
16: "en": "Chaharbagh",
17: "fa": "چهارباغ",
18: "de": "Chaharbagh"
19: }
20: },
21: {
22: "field": "locality",
23: "key": "eshtehard",
24: "name": {
25: "en": "Eshtehard",
26: "fa": "اشتهارد",
27: "de": "Eshtehard"
28: }
29: },
30: {
31: "field": "locality",
32: "key": "fardis",
33: "name": {
34: "en": "Fardis",
35: "fa": "فردیس",
36: "de": "Fardis"
37: }
38: },
39: {
40: "field": "locality",
41: "key": "karaj",
42: "name": {
43: "en": "Karaj",
44: "fa": "کرج",
45: "de": "Karaj"
46: }
47: },
48: {
49: "field": "locality",
50: "key": "nazarabad",
51: "name": {
52: "en": "Nazarabad",
53: "fa": "نظرآباد",
54: "de": "Nazarabad"
55: }
56: },
57: {
58: "field": "locality",
59: "key": "savojbolagh",
60: "name": {
61: "en": "Savojbolagh",
62: "fa": "ساوجبلاغ",
63: "de": "Savojbolagh"
64: }
65: },
66: {
67: "field": "locality",
68: "key": "taleqan",
69: "name": {
70: "en": "Taleqan",
71: "fa": "طالقان",
72: "de": "Taleqan"
73: }
74: }
75: ]
76: },
77: {
78: "countryCode": "IR",
79: "field": "administrative_area",
80: "key": "ardabil",
81: "name": {
82: "en": "Ardabil",
83: "fa": "اردبیل",
84: "de": "Ardabil"
85: },
86: "children": [
87: {
88: "field": "locality",
89: "key": "ardabil",
90: "name": {
91: "en": "Ardabil",
92: "fa": "اردبیل",
93: "de": "Ardabil"
94: }
95: },
96: {
97: "field": "locality",
98: "key": "aslanduz",
99: "name": {
100: "en": "Aslan Duz",
101: "fa": "اصلاندوز",
102: "de": "Aslan Duz"
103: }
104: },
105: {
106: "field": "locality",
107: "key": "bilehsavar",
108: "name": {
109: "en": "Bileh Savar",
110: "fa": "بیلهسوار",
111: "de": "Bileh Savar"
112: }
113: },
114: {
115: "field": "locality",
116: "key": "germi",
117: "name": {
118: "en": "Germi",
119: "fa": "گرمی",
120: "de": "Germi"
121: }
122: },
123: {
124: "field": "locality",
125: "key": "khalkhal",
126: "name": {
127: "en": "Khalkhal",
128: "fa": "خلخال",
129: "de": "Khalkhal"
130: }
131: },
132: {
133: "field": "locality",
134: "key": "kowsar",
135: "name": {
136: "en": "Kowsar",
137: "fa": "کوثر",
138: "de": "Kowsar"
139: }
140: },
141: {
142: "field": "locality",
143: "key": "meshginshahr",
144: "name": {
145: "en": "Meshgin Shahr",
146: "fa": "مشگینشهر",
147: "de": "Meshgin Shahr"
148: }
149: },
150: {
151: "field": "locality",
152: "key": "namin",
153: "name": {
154: "en": "Namin",
155: "fa": "نمین",
156: "de": "Namin"
157: }
158: },
159: {
160: "field": "locality",
161: "key": "nir",
162: "name": {
163: "en": "Nir",
164: "fa": "نیر",
165: "de": "Nir"
166: }
167: },
168: {
169: "field": "locality",
170: "key": "parsabad",
171: "name": {
172: "en": "Parsabad",
173: "fa": "پارسآباد",
174: "de": "Parsabad"
175: }
176: },
177: {
178: "field": "locality",
179: "key": "sareyn",
180: "name": {
181: "en": "Sareyn",
182: "fa": "سرعین",
183: "de": "Sareyn"
184: }
185: },
186: {
187: "field": "locality",
188: "key": "ungut",
189: "name": {
190: "en": "Ungut",
191: "fa": "انگوت",
192: "de": "Ungut"
193: }
194: }
195: ]
196: },
197: {
198: "countryCode": "IR",
199: "field": "administrative_area",
200: "key": "bushehr",
201: "name": {
202: "en": "Bushehr",
203: "fa": "بوشهر",
204: "de": "Buschehr"
205: },
206: "children": [
207: {
208: "field": "locality",
209: "key": "asaluyeh",
210: "name": {
211: "en": "Asaluyeh",
212: "fa": "عسلویه",
213: "de": "Asaluyeh"
214: }
215: },
216: {
217: "field": "locality",
218: "key": "bushehr",
219: "name": {
220: "en": "Bushehr",
221: "fa": "بوشهر",
222: "de": "Buschehr"
223: }
224: },
225: {
226: "field": "locality",
227: "key": "dashtestan",
228: "name": {
229: "en": "Dashtestan",
230: "fa": "دشتستان",
231: "de": "Dashtestan"
232: }
233: },
234: {
235: "field": "locality",
236: "key": "dashti",
237: "name": {
238: "en": "Dashti",
239: "fa": "دشتی",
240: "de": "Dashti"
241: }
242: },
243: {
244: "field": "locality",
245: "key": "deylam",
246: "name": {
247: "en": "Deylam",
248: "fa": "دیلم",
249: "de": "Deylam"
250: }
251: },
252: {
253: "field": "locality",
254: "key": "deyr",
255: "name": {
256: "en": "Deyr",
257: "fa": "دیر",
258: "de": "Deyr"
259: }
260: },
261: {
262: "field": "locality",
263: "key": "ganaveh",
264: "name": {
265: "en": "Ganaveh",
266: "fa": "گناوه",
267: "de": "Ganaveh"
268: }
269: },
270: {
271: "field": "locality",
272: "key": "jam",
273: "name": {
274: "en": "Jam",
275: "fa": "جم",
276: "de": "Jam"
277: }
278: },
279: {
280: "field": "locality",
281: "key": "kangan",
282: "name": {
283: "en": "Kangan",
284: "fa": "کنگان",
285: "de": "Kangan"
286: }
287: },
288: {
289: "field": "locality",
290: "key": "tangestan",
291: "name": {
292: "en": "Tangestan",
293: "fa": "تنگستان",
294: "de": "Tangestan"
295: }
296: }
297: ]
298: },
299: {
300: "countryCode": "IR",
301: "field": "administrative_area",
302: "key": "chaharmahalandbakhtiari",
303: "name": {
304: "en": "Chaharmahal and Bakhtiari",
305: "fa": "چهارمحال و بختیاری",
306: "de": "Tschahar Mahal und Bachtiari"
307: },
308: "children": [
309: {
310: "field": "locality",
311: "key": "ardal",
312: "name": {
313: "en": "Ardal",
314: "fa": "اردل",
315: "de": "Ardal"
316: }
317: },
318: {
319: "field": "locality",
320: "key": "ben",
321: "name": {
322: "en": "Ben",
323: "fa": "بن",
324: "de": "Ben"
325: }
326: },
327: {
328: "field": "locality",
329: "key": "borujen",
330: "name": {
331: "en": "Borujen",
332: "fa": "بروجن",
333: "de": "Borujen"
334: }
335: },
336: {
337: "field": "locality",
338: "key": "falard",
339: "name": {
340: "en": "Falard",
341: "fa": "فلارد",
342: "de": "Falard"
343: }
344: },
345: {
346: "field": "locality",
347: "key": "farrokhshahr",
348: "name": {
349: "en": "Farrokhshahr",
350: "fa": "فرخشهر",
351: "de": "Farrokhshahr"
352: }
353: },
354: {
355: "field": "locality",
356: "key": "farsan",
357: "name": {
358: "en": "Farsan",
359: "fa": "فارسان",
360: "de": "Farsan"
361: }
362: },
363: {
364: "field": "locality",
365: "key": "khanmirza",
366: "name": {
367: "en": "Khanmirza",
368: "fa": "خانمیرزا",
369: "de": "Khanmirza"
370: }
371: },
372: {
373: "field": "locality",
374: "key": "kiar",
375: "name": {
376: "en": "Kiar",
377: "fa": "کیار",
378: "de": "Kiar"
379: }
380: },
381: {
382: "field": "locality",
383: "key": "kuhrang",
384: "name": {
385: "en": "Kuhrang",
386: "fa": "کوهرنگ",
387: "de": "Kuhrang"
388: }
389: },
390: {
391: "field": "locality",
392: "key": "lordegan",
393: "name": {
394: "en": "Lordegan",
395: "fa": "لردگان",
396: "de": "Lordegan"
397: }
398: },
399: {
400: "field": "locality",
401: "key": "saman",
402: "name": {
403: "en": "Saman",
404: "fa": "سامان",
405: "de": "Saman"
406: }
407: },
408: {
409: "field": "locality",
410: "key": "shahrekord",
411: "name": {
412: "en": "Shahrekord",
413: "fa": "شهرکرد",
414: "de": "Shahrekord"
415: }
416: }
417: ]
418: },
419: {
420: "countryCode": "IR",
421: "field": "administrative_area",
422: "key": "eastazerbaijan",
423: "name": {
424: "en": "East Azerbaijan",
425: "fa": "آذربایجان شرقی",
426: "de": "Ost-Aserbaidschan"
427: },
428: "children": [
429: {
430: "field": "locality",
431: "key": "ahar",
432: "name": {
433: "en": "Ahar",
434: "fa": "اهر",
435: "de": "Ahar"
436: }
437: },
438: {
439: "field": "locality",
440: "key": "ajabshir",
441: "name": {
442: "en": "Ajab Shir",
443: "fa": "عجبشیر",
444: "de": "Ajab Shir"
445: }
446: },
447: {
448: "field": "locality",
449: "key": "azarshahr",
450: "name": {
451: "en": "Azarshahr",
452: "fa": "آذرشهر",
453: "de": "Azarshahr"
454: }
455: },
456: {
457: "field": "locality",
458: "key": "bonab",
459: "name": {
460: "en": "Bonab",
461: "fa": "بناب",
462: "de": "Bonab"
463: }
464: },
465: {
466: "field": "locality",
467: "key": "bostanabad",
468: "name": {
469: "en": "Bostanabad",
470: "fa": "بستانآباد",
471: "de": "Bostanabad"
472: }
473: },
474: {
475: "field": "locality",
476: "key": "charuymaq",
477: "name": {
478: "en": "Charuymaq",
479: "fa": "چاروایماق",
480: "de": "Charuymaq"
481: }
482: },
483: {
484: "field": "locality",
485: "key": "hashtrud",
486: "name": {
487: "en": "Hashtrud",
488: "fa": "هشترود",
489: "de": "Hashtrud"
490: }
491: },
492: {
493: "field": "locality",
494: "key": "heris",
495: "name": {
496: "en": "Heris",
497: "fa": "هریس",
498: "de": "Heris"
499: }
500: },
501: {
502: "field": "locality",
503: "key": "hurand",
504: "name": {
505: "en": "Hurand",
506: "fa": "هوراند",
507: "de": "Hurand"
508: }
509: },
510: {
511: "field": "locality",
512: "key": "jolfa",
513: "name": {
514: "en": "Jolfa",
515: "fa": "جلفا",
516: "de": "Jolfa"
517: }
518: },
519: {
520: "field": "locality",
521: "key": "kaleybar",
522: "name": {
523: "en": "Kaleybar",
524: "fa": "کلیبر",
525: "de": "Kaleybar"
526: }
527: },
528: {
529: "field": "locality",
530: "key": "khodaafarin",
531: "name": {
532: "en": "Khoda Afarin",
533: "fa": "خداآفرین",
534: "de": "Khoda Afarin"
535: }
536: },
537: {
538: "field": "locality",
539: "key": "malekan",
540: "name": {
541: "en": "Malekan",
542: "fa": "ملکان",
543: "de": "Malekan"
544: }
545: },
546: {
547: "field": "locality",
548: "key": "maragheh",
549: "name": {
550: "en": "Maragheh",
551: "fa": "مراغه",
552: "de": "Maragheh"
553: }
554: },
555: {
556: "field": "locality",
557: "key": "marand",
558: "name": {
559: "en": "Marand",
560: "fa": "مرند",
561: "de": "Marand"
562: }
563: },
564: {
565: "field": "locality",
566: "key": "mianeh",
567: "name": {
568: "en": "Mianeh",
569: "fa": "میانه",
570: "de": "Mianeh"
571: }
572: },
573: {
574: "field": "locality",
575: "key": "osku",
576: "name": {
577: "en": "Osku",
578: "fa": "اسکو",
579: "de": "Osku"
580: }
581: },
582: {
583: "field": "locality",
584: "key": "sarab",
585: "name": {
586: "en": "Sarab",
587: "fa": "سراب",
588: "de": "Sarab"
589: }
590: },
591: {
592: "field": "locality",
593: "key": "shabestar",
594: "name": {
595: "en": "Shabestar",
596: "fa": "شبستر",
597: "de": "Shabestar"
598: }
599: },
600: {
601: "field": "locality",
602: "key": "tabriz",
603: "name": {
604: "en": "Tabriz",
605: "fa": "تبریز",
606: "de": "Täbris"
607: }
608: },
609: {
610: "field": "locality",
611: "key": "varzaqan",
612: "name": {
613: "en": "Varzaqan",
614: "fa": "ورزقان",
615: "de": "Varzaqan"
616: }
617: }
618: ]
619: },
620: {
621: "countryCode": "IR",
622: "field": "administrative_area",
623: "key": "fars",
624: "name": {
625: "en": "Fars",
626: "fa": "فارس",
627: "de": "Fars"
628: },
629: "children": [
630: {
631: "field": "locality",
632: "key": "abadeh",
633: "name": {
634: "en": "Abadeh",
635: "fa": "آباده",
636: "de": "Abadeh"
637: }
638: },
639: {
640: "field": "locality",
641: "key": "arsanjan",
642: "name": {
643: "en": "Arsanjan",
644: "fa": "ارسنجان",
645: "de": "Arsanjan"
646: }
647: },
648: {
649: "field": "locality",
650: "key": "bakhtegan",
651: "name": {
652: "en": "Bakhtegan",
653: "fa": "بختگان",
654: "de": "Bakhtegan"
655: }
656: },
657: {
658: "field": "locality",
659: "key": "bavanat",
660: "name": {
661: "en": "Bavanat",
662: "fa": "بوانات",
663: "de": "Bavanat"
664: }
665: },
666: {
667: "field": "locality",
668: "key": "beyza",
669: "name": {
670: "en": "Beyza",
671: "fa": "بیضا",
672: "de": "Beyza"
673: }
674: },
675: {
676: "field": "locality",
677: "key": "darab",
678: "name": {
679: "en": "Darab",
680: "fa": "داراب",
681: "de": "Darab"
682: }
683: },
684: {
685: "field": "locality",
686: "key": "eqlid",
687: "name": {
688: "en": "Eqlid",
689: "fa": "اقلید",
690: "de": "Eqlid"
691: }
692: },
693: {
694: "field": "locality",
695: "key": "estahban",
696: "name": {
697: "en": "Estahban",
698: "fa": "استهبان",
699: "de": "Estahban"
700: }
701: },
702: {
703: "field": "locality",
704: "key": "evaz",
705: "name": {
706: "en": "Evaz",
707: "fa": "اوز",
708: "de": "Evaz"
709: }
710: },
711: {
712: "field": "locality",
713: "key": "farashband",
714: "name": {
715: "en": "Farashband",
716: "fa": "فراشبند",
717: "de": "Farashband"
718: }
719: },
720: {
721: "field": "locality",
722: "key": "fasa",
723: "name": {
724: "en": "Fasa",
725: "fa": "فسا",
726: "de": "Fasa"
727: }
728: },
729: {
730: "field": "locality",
731: "key": "firuzabad",
732: "name": {
733: "en": "Firuzabad",
734: "fa": "فیروزآباد",
735: "de": "Firuzabad"
736: }
737: },
738: {
739: "field": "locality",
740: "key": "gerash",
741: "name": {
742: "en": "Gerash",
743: "fa": "گراش",
744: "de": "Gerash"
745: }
746: },
747: {
748: "field": "locality",
749: "key": "jahrom",
750: "name": {
751: "en": "Jahrom",
752: "fa": "جهرم",
753: "de": "Jahrom"
754: }
755: },
756: {
757: "field": "locality",
758: "key": "juyom",
759: "name": {
760: "en": "Juyom",
761: "fa": "جویم",
762: "de": "Juyom"
763: }
764: },
765: {
766: "field": "locality",
767: "key": "kavar",
768: "name": {
769: "en": "Kavar",
770: "fa": "کوار",
771: "de": "Kavar"
772: }
773: },
774: {
775: "field": "locality",
776: "key": "kazerun",
777: "name": {
778: "en": "Kazerun",
779: "fa": "کازرون",
780: "de": "Kazerun"
781: }
782: },
783: {
784: "field": "locality",
785: "key": "khafr",
786: "name": {
787: "en": "Khafr",
788: "fa": "خفر",
789: "de": "Khafr"
790: }
791: },
792: {
793: "field": "locality",
794: "key": "kharameh",
795: "name": {
796: "en": "Kharameh",
797: "fa": "خرامه",
798: "de": "Kharameh"
799: }
800: },
801: {
802: "field": "locality",
803: "key": "khonj",
804: "name": {
805: "en": "Khonj",
806: "fa": "خنج",
807: "de": "Khonj"
808: }
809: },
810: {
811: "field": "locality",
812: "key": "khorrambid",
813: "name": {
814: "en": "Khorrambid",
815: "fa": "خرمبید",
816: "de": "Khorrambid"
817: }
818: },
819: {
820: "field": "locality",
821: "key": "kuhchenar",
822: "name": {
823: "en": "Kuhchenar",
824: "fa": "کوهچنار",
825: "de": "Kuhchenar"
826: }
827: },
828: {
829: "field": "locality",
830: "key": "lamerd",
831: "name": {
832: "en": "Lamerd",
833: "fa": "لامرد",
834: "de": "Lamerd"
835: }
836: },
837: {
838: "field": "locality",
839: "key": "larestan",
840: "name": {
841: "en": "Larestan",
842: "fa": "لارستان",
843: "de": "Larestan"
844: }
845: },
846: {
847: "field": "locality",
848: "key": "mamasani",
849: "name": {
850: "en": "Mamasani",
851: "fa": "ممسنی",
852: "de": "Mamasani"
853: }
854: },
855: {
856: "field": "locality",
857: "key": "marvdasht",
858: "name": {
859: "en": "Marvdasht",
860: "fa": "مرودشت",
861: "de": "Marvdasht"
862: }
863: },
864: {
865: "field": "locality",
866: "key": "mohr",
867: "name": {
868: "en": "Mohr",
869: "fa": "مهر",
870: "de": "Mohr"
871: }
872: },
873: {
874: "field": "locality",
875: "key": "neyriz",
876: "name": {
877: "en": "Neyriz",
878: "fa": "نیریز",
879: "de": "Neyriz"
880: }
881: },
882: {
883: "field": "locality",
884: "key": "pasargad",
885: "name": {
886: "en": "Pasargad",
887: "fa": "پاسارگاد",
888: "de": "Pasargad"
889: }
890: },
891: {
892: "field": "locality",
893: "key": "qirandkarzin",
894: "name": {
895: "en": "Qir and Karzin",
896: "fa": "قیر و کارزین",
897: "de": "Qir and Karzin"
898: }
899: },
900: {
901: "field": "locality",
902: "key": "rostam",
903: "name": {
904: "en": "Rostam",
905: "fa": "رستم",
906: "de": "Rostam"
907: }
908: },
909: {
910: "field": "locality",
911: "key": "sarchehan",
912: "name": {
913: "en": "Sarchehan",
914: "fa": "سرچهان",
915: "de": "Sarchehan"
916: }
917: },
918: {
919: "field": "locality",
920: "key": "sarvestan",
921: "name": {
922: "en": "Sarvestan",
923: "fa": "سروستان",
924: "de": "Sarvestan"
925: }
926: },
927: {
928: "field": "locality",
929: "key": "sepidan",
930: "name": {
931: "en": "Sepidan",
932: "fa": "سپیدان",
933: "de": "Sepidan"
934: }
935: },
936: {
937: "field": "locality",
938: "key": "shiraz",
939: "name": {
940: "en": "Shiraz",
941: "fa": "شیراز",
942: "de": "Schiras"
943: }
944: },
945: {
946: "field": "locality",
947: "key": "zarqan",
948: "name": {
949: "en": "Zarqan",
950: "fa": "زرقان",
951: "de": "Zarqan"
952: }
953: },
954: {
955: "field": "locality",
956: "key": "zarrindasht",
957: "name": {
958: "en": "Zarrin Dasht",
959: "fa": "زریندشت",
960: "de": "Zarrin Dasht"
961: }
962: }
963: ]
964: },
965: {
966: "countryCode": "IR",
967: "field": "administrative_area",
968: "key": "gilan",
969: "name": {
970: "en": "Gilan",
971: "fa": "گیلان",
972: "de": "Gilan"
973: },
974: "children": [
975: {
976: "field": "locality",
977: "key": "amlash",
978: "name": {
979: "en": "Amlash",
980: "fa": "املش",
981: "de": "Amlash"
982: }
983: },
984: {
985: "field": "locality",
986: "key": "astanehyeashrafiyeh",
987: "name": {
988: "en": "Astaneh-ye Ashrafiyeh",
989: "fa": "آستانهاشرفیه",
990: "de": "Astaneh-ye Ashrafiyeh"
991: }
992: },
993: {
994: "field": "locality",
995: "key": "astara",
996: "name": {
997: "en": "Astara",
998: "fa": "آستارا",
999: "de": "Astara"
1000: }
1001: },
1002: {
1003: "field": "locality",
1004: "key": "bandareanzali",
1005: "name": {
1006: "en": "Bandar-e Anzali",
1007: "fa": "بندر انزلی",
1008: "de": "Bandar-e Anzali"
1009: }
1010: },
1011: {
1012: "field": "locality",
1013: "key": "fuman",
1014: "name": {
1015: "en": "Fuman",
1016: "fa": "فومن",
1017: "de": "Fuman"
1018: }
1019: },
1020: {
1021: "field": "locality",
1022: "key": "khomam",
1023: "name": {
1024: "en": "Khomam",
1025: "fa": "خمام",
1026: "de": "Khomam"
1027: }
1028: },
1029: {
1030: "field": "locality",
1031: "key": "lahijan",
1032: "name": {
1033: "en": "Lahijan",
1034: "fa": "لاهیجان",
1035: "de": "Lahijan"
1036: }
1037: },
1038: {
1039: "field": "locality",
1040: "key": "langarud",
1041: "name": {
1042: "en": "Langarud",
1043: "fa": "لنگرود",
1044: "de": "Langarud"
1045: }
1046: },
1047: {
1048: "field": "locality",
1049: "key": "masal",
1050: "name": {
1051: "en": "Masal",
1052: "fa": "ماسال",
1053: "de": "Masal"
1054: }
1055: },
1056: {
1057: "field": "locality",
1058: "key": "rasht",
1059: "name": {
1060: "en": "Rasht",
1061: "fa": "رشت",
1062: "de": "Rasht"
1063: }
1064: },
1065: {
1066: "field": "locality",
1067: "key": "rezvanshahr",
1068: "name": {
1069: "en": "Rezvanshahr",
1070: "fa": "رضوانشهر",
1071: "de": "Rezvanshahr"
1072: }
1073: },
1074: {
1075: "field": "locality",
1076: "key": "rudbar",
1077: "name": {
1078: "en": "Rudbar",
1079: "fa": "رودبار",
1080: "de": "Rudbar"
1081: }
1082: },
1083: {
1084: "field": "locality",
1085: "key": "rudsar",
1086: "name": {
1087: "en": "Rudsar",
1088: "fa": "رودسر",
1089: "de": "Rudsar"
1090: }
1091: },
1092: {
1093: "field": "locality",
1094: "key": "shaft",
1095: "name": {
1096: "en": "Shaft",
1097: "fa": "شفت",
1098: "de": "Shaft"
1099: }
1100: },
1101: {
1102: "field": "locality",
1103: "key": "siahkal",
1104: "name": {
1105: "en": "Siahkal",
1106: "fa": "سیاهکل",
1107: "de": "Siahkal"
1108: }
1109: },
1110: {
1111: "field": "locality",
1112: "key": "sowmeehsara",
1113: "name": {
1114: "en": "Sowme'eh Sara",
1115: "fa": "صومعهسرا",
1116: "de": "Sowme'eh Sara"
1117: }
1118: },
1119: {
1120: "field": "locality",
1121: "key": "talesh",
1122: "name": {
1123: "en": "Talesh",
1124: "fa": "تالش",
1125: "de": "Talesh"
1126: }
1127: }
1128: ]
1129: },
1130: {
1131: "countryCode": "IR",
1132: "field": "administrative_area",
1133: "key": "golestan",
1134: "name": {
1135: "en": "Golestan",
1136: "fa": "گلستان",
1137: "de": "Golestan"
1138: },
1139: "children": [
1140: {
1141: "field": "locality",
1142: "key": "aliabad",
1143: "name": {
1144: "en": "Aliabad",
1145: "fa": "علیآباد کتول",
1146: "de": "Aliabad"
1147: }
1148: },
1149: {
1150: "field": "locality",
1151: "key": "aqqala",
1152: "name": {
1153: "en": "Aqqala",
1154: "fa": "آققلا",
1155: "de": "Aqqala"
1156: }
1157: },
1158: {
1159: "field": "locality",
1160: "key": "azadshahr",
1161: "name": {
1162: "en": "Azadshahr",
1163: "fa": "آزادشهر",
1164: "de": "Azadshahr"
1165: }
1166: },
1167: {
1168: "field": "locality",
1169: "key": "bandaregaz",
1170: "name": {
1171: "en": "Bandar-e Gaz",
1172: "fa": "بندر گز",
1173: "de": "Bandar-e Gaz"
1174: }
1175: },
1176: {
1177: "field": "locality",
1178: "key": "galikash",
1179: "name": {
1180: "en": "Galikash",
1181: "fa": "گالیکش",
1182: "de": "Galikash"
1183: }
1184: },
1185: {
1186: "field": "locality",
1187: "key": "gomishan",
1188: "name": {
1189: "en": "Gomishan",
1190: "fa": "گمیشان",
1191: "de": "Gomishan"
1192: }
1193: },
1194: {
1195: "field": "locality",
1196: "key": "gonbadekavus",
1197: "name": {
1198: "en": "Gonbad-e Kavus",
1199: "fa": "گنبد کاووس",
1200: "de": "Gonbad-e Kavus"
1201: }
1202: },
1203: {
1204: "field": "locality",
1205: "key": "gorgan",
1206: "name": {
1207: "en": "Gorgan",
1208: "fa": "گرگان",
1209: "de": "Gorgan"
1210: }
1211: },
1212: {
1213: "field": "locality",
1214: "key": "kalaleh",
1215: "name": {
1216: "en": "Kalaleh",
1217: "fa": "کلاله",
1218: "de": "Kalaleh"
1219: }
1220: },
1221: {
1222: "field": "locality",
1223: "key": "kordkuy",
1224: "name": {
1225: "en": "Kordkuy",
1226: "fa": "کردکوی",
1227: "de": "Kordkuy"
1228: }
1229: },
1230: {
1231: "field": "locality",
1232: "key": "maravehtappeh",
1233: "name": {
1234: "en": "Maraveh Tappeh",
1235: "fa": "مراوهتپه",
1236: "de": "Maraveh Tappeh"
1237: }
1238: },
1239: {
1240: "field": "locality",
1241: "key": "minudasht",
1242: "name": {
1243: "en": "Minudasht",
1244: "fa": "مینودشت",
1245: "de": "Minudasht"
1246: }
1247: },
1248: {
1249: "field": "locality",
1250: "key": "ramian",
1251: "name": {
1252: "en": "Ramian",
1253: "fa": "رامیان",
1254: "de": "Ramian"
1255: }
1256: },
1257: {
1258: "field": "locality",
1259: "key": "torkaman",
1260: "name": {
1261: "en": "Torkaman",
1262: "fa": "ترکمن",
1263: "de": "Torkaman"
1264: }
1265: }
1266: ]
1267: },
1268: {
1269: "countryCode": "IR",
1270: "field": "administrative_area",
1271: "key": "hamadan",
1272: "name": {
1273: "en": "Hamadan",
1274: "fa": "همدان",
1275: "de": "Hamadan"
1276: },
1277: "children": [
1278: {
1279: "field": "locality",
1280: "key": "asadabad",
1281: "name": {
1282: "en": "Asadabad",
1283: "fa": "اسدآباد",
1284: "de": "Asadabad"
1285: }
1286: },
1287: {
1288: "field": "locality",
1289: "key": "bahar",
1290: "name": {
1291: "en": "Bahar",
1292: "fa": "بهار",
1293: "de": "Bahar"
1294: }
1295: },
1296: {
1297: "field": "locality",
1298: "key": "dargazin",
1299: "name": {
1300: "en": "Dargazin",
1301: "fa": "درگزین",
1302: "de": "Dargazin"
1303: }
1304: },
1305: {
1306: "field": "locality",
1307: "key": "famenin",
1308: "name": {
1309: "en": "Famenin",
1310: "fa": "فامنین",
1311: "de": "Famenin"
1312: }
1313: },
1314: {
1315: "field": "locality",
1316: "key": "hamadan",
1317: "name": {
1318: "en": "Hamadan",
1319: "fa": "همدان",
1320: "de": "Hamadan"
1321: }
1322: },
1323: {
1324: "field": "locality",
1325: "key": "kabudarahang",
1326: "name": {
1327: "en": "Kabudarahang",
1328: "fa": "کبودراهنگ",
1329: "de": "Kabudarahang"
1330: }
1331: },
1332: {
1333: "field": "locality",
1334: "key": "malayer",
1335: "name": {
1336: "en": "Malayer",
1337: "fa": "ملایر",
1338: "de": "Malayer"
1339: }
1340: },
1341: {
1342: "field": "locality",
1343: "key": "nahavand",
1344: "name": {
1345: "en": "Nahavand",
1346: "fa": "نهاوند",
1347: "de": "Nahavand"
1348: }
1349: },
1350: {
1351: "field": "locality",
1352: "key": "razan",
1353: "name": {
1354: "en": "Razan",
1355: "fa": "رزن",
1356: "de": "Razan"
1357: }
1358: },
1359: {
1360: "field": "locality",
1361: "key": "tuyserkan",
1362: "name": {
1363: "en": "Tuyserkan",
1364: "fa": "تویسرکان",
1365: "de": "Tuyserkan"
1366: }
1367: }
1368: ]
1369: },
1370: {
1371: "countryCode": "IR",
1372: "field": "administrative_area",
1373: "key": "hormozgan",
1374: "name": {
1375: "en": "Hormozgan",
1376: "fa": "هرمزگان",
1377: "de": "Hormozgan"
1378: },
1379: "children": [
1380: {
1381: "field": "locality",
1382: "key": "abumusa",
1383: "name": {
1384: "en": "Abumusa",
1385: "fa": "ابوموسی",
1386: "de": "Abumusa"
1387: }
1388: },
1389: {
1390: "field": "locality",
1391: "key": "bandarabbas",
1392: "name": {
1393: "en": "Bandar Abbas",
1394: "fa": "بندرعباس",
1395: "de": "Bandar Abbas"
1396: }
1397: },
1398: {
1399: "field": "locality",
1400: "key": "bandarlengeh",
1401: "name": {
1402: "en": "Bandar Lengeh",
1403: "fa": "بندر لنگه",
1404: "de": "Bandar Lengeh"
1405: }
1406: },
1407: {
1408: "field": "locality",
1409: "key": "bashagard",
1410: "name": {
1411: "en": "Bashagard",
1412: "fa": "بشاگرد",
1413: "de": "Bashagard"
1414: }
1415: },
1416: {
1417: "field": "locality",
1418: "key": "bastak",
1419: "name": {
1420: "en": "Bastak",
1421: "fa": "بستک",
1422: "de": "Bastak"
1423: }
1424: },
1425: {
1426: "field": "locality",
1427: "key": "hajjiabad",
1428: "name": {
1429: "en": "Hajjiabad",
1430: "fa": "حاجیآباد",
1431: "de": "Hajjiabad"
1432: }
1433: },
1434: {
1435: "field": "locality",
1436: "key": "jask",
1437: "name": {
1438: "en": "Jask",
1439: "fa": "جاسک",
1440: "de": "Jask"
1441: }
1442: },
1443: {
1444: "field": "locality",
1445: "key": "khamir",
1446: "name": {
1447: "en": "Khamir",
1448: "fa": "بندر خمیر",
1449: "de": "Khamir"
1450: }
1451: },
1452: {
1453: "field": "locality",
1454: "key": "minab",
1455: "name": {
1456: "en": "Minab",
1457: "fa": "میناب",
1458: "de": "Minab"
1459: }
1460: },
1461: {
1462: "field": "locality",
1463: "key": "parsian",
1464: "name": {
1465: "en": "Parsian",
1466: "fa": "پارسیان",
1467: "de": "Parsian"
1468: }
1469: },
1470: {
1471: "field": "locality",
1472: "key": "qeshm",
1473: "name": {
1474: "en": "Qeshm",
1475: "fa": "قشم",
1476: "de": "Qeshm"
1477: }
1478: },
1479: {
1480: "field": "locality",
1481: "key": "rudan",
1482: "name": {
1483: "en": "Rudan",
1484: "fa": "رودان",
1485: "de": "Rudan"
1486: }
1487: },
1488: {
1489: "field": "locality",
1490: "key": "sirik",
1491: "name": {
1492: "en": "Sirik",
1493: "fa": "سیریک",
1494: "de": "Sirik"
1495: }
1496: }
1497: ]
1498: },
1499: {
1500: "countryCode": "IR",
1501: "field": "administrative_area",
1502: "key": "ilam",
1503: "name": {
1504: "en": "Ilam",
1505: "fa": "ایلام",
1506: "de": "Ilam"
1507: },
1508: "children": [
1509: {
1510: "field": "locality",
1511: "key": "abdanan",
1512: "name": {
1513: "en": "Abdanan",
1514: "fa": "آبدانان",
1515: "de": "Abdanan"
1516: }
1517: },
1518: {
1519: "field": "locality",
1520: "key": "badreh",
1521: "name": {
1522: "en": "Badreh",
1523: "fa": "بدره",
1524: "de": "Badreh"
1525: }
1526: },
1527: {
1528: "field": "locality",
1529: "key": "chardavol",
1530: "name": {
1531: "en": "Chardavol",
1532: "fa": "چرداول",
1533: "de": "Chardavol"
1534: }
1535: },
1536: {
1537: "field": "locality",
1538: "key": "chavar",
1539: "name": {
1540: "en": "Chavar",
1541: "fa": "چوار",
1542: "de": "Chavar"
1543: }
1544: },
1545: {
1546: "field": "locality",
1547: "key": "darrehshahr",
1548: "name": {
1549: "en": "Darreh Shahr",
1550: "fa": "درهشهر",
1551: "de": "Darreh Shahr"
1552: }
1553: },
1554: {
1555: "field": "locality",
1556: "key": "dehloran",
1557: "name": {
1558: "en": "Dehloran",
1559: "fa": "دهلران",
1560: "de": "Dehloran"
1561: }
1562: },
1563: {
1564: "field": "locality",
1565: "key": "eyvan",
1566: "name": {
1567: "en": "Eyvan",
1568: "fa": "ایوان",
1569: "de": "Eyvan"
1570: }
1571: },
1572: {
1573: "field": "locality",
1574: "key": "holeylan",
1575: "name": {
1576: "en": "Holeylan",
1577: "fa": "هلیلان",
1578: "de": "Holeylan"
1579: }
1580: },
1581: {
1582: "field": "locality",
1583: "key": "ilam",
1584: "name": {
1585: "en": "Ilam",
1586: "fa": "ایلام",
1587: "de": "Ilam"
1588: }
1589: },
1590: {
1591: "field": "locality",
1592: "key": "malekshahi",
1593: "name": {
1594: "en": "Malekshahi",
1595: "fa": "ملکشاهی",
1596: "de": "Malekshahi"
1597: }
1598: },
1599: {
1600: "field": "locality",
1601: "key": "mehran",
1602: "name": {
1603: "en": "Mehran",
1604: "fa": "مهران",
1605: "de": "Mehran"
1606: }
1607: },
1608: {
1609: "field": "locality",
1610: "key": "sirvan",
1611: "name": {
1612: "en": "Sirvan",
1613: "fa": "سیروان",
1614: "de": "Sirvan"
1615: }
1616: }
1617: ]
1618: },
1619: {
1620: "countryCode": "IR",
1621: "field": "administrative_area",
1622: "key": "isfahan",
1623: "name": {
1624: "en": "Isfahan",
1625: "fa": "اصفهان",
1626: "de": "Isfahan"
1627: },
1628: "children": [
1629: {
1630: "field": "locality",
1631: "key": "aranvabidgol",
1632: "name": {
1633: "en": "Aran va Bidgol",
1634: "fa": "آران و بیدگل",
1635: "de": "Aran va Bidgol"
1636: }
1637: },
1638: {
1639: "field": "locality",
1640: "key": "ardestan",
1641: "name": {
1642: "en": "Ardestan",
1643: "fa": "اردستان",
1644: "de": "Ardestan"
1645: }
1646: },
1647: {
1648: "field": "locality",
1649: "key": "borkhar",
1650: "name": {
1651: "en": "Borkhar",
1652: "fa": "برخوار",
1653: "de": "Borkhar"
1654: }
1655: },
1656: {
1657: "field": "locality",
1658: "key": "buinmiandasht",
1659: "name": {
1660: "en": "Buin Miandasht",
1661: "fa": "بویینمیاندشت",
1662: "de": "Buin Miandasht"
1663: }
1664: },
1665: {
1666: "field": "locality",
1667: "key": "chadegan",
1668: "name": {
1669: "en": "Chadegan",
1670: "fa": "چادگان",
1671: "de": "Chadegan"
1672: }
1673: },
1674: {
1675: "field": "locality",
1676: "key": "dehaqan",
1677: "name": {
1678: "en": "Dehaqan",
1679: "fa": "دهاقان",
1680: "de": "Dehaqan"
1681: }
1682: },
1683: {
1684: "field": "locality",
1685: "key": "falavarjan",
1686: "name": {
1687: "en": "Falavarjan",
1688: "fa": "فلاورجان",
1689: "de": "Falavarjan"
1690: }
1691: },
1692: {
1693: "field": "locality",
1694: "key": "faridan",
1695: "name": {
1696: "en": "Faridan",
1697: "fa": "فریدن",
1698: "de": "Faridan"
1699: }
1700: },
1701: {
1702: "field": "locality",
1703: "key": "fereydunshahr",
1704: "name": {
1705: "en": "Fereydunshahr",
1706: "fa": "فریدونشهر",
1707: "de": "Fereydunshahr"
1708: }
1709: },
1710: {
1711: "field": "locality",
1712: "key": "golpayegan",
1713: "name": {
1714: "en": "Golpayegan",
1715: "fa": "گلپایگان",
1716: "de": "Golpayegan"
1717: }
1718: },
1719: {
1720: "field": "locality",
1721: "key": "harand",
1722: "name": {
1723: "en": "Harand",
1724: "fa": "هرند",
1725: "de": "Harand"
1726: }
1727: },
1728: {
1729: "field": "locality",
1730: "key": "isfahan",
1731: "name": {
1732: "en": "Isfahan",
1733: "fa": "اصفهان",
1734: "de": "Isfahan"
1735: }
1736: },
1737: {
1738: "field": "locality",
1739: "key": "jarqavieh",
1740: "name": {
1741: "en": "Jarqavieh",
1742: "fa": "جرقویه",
1743: "de": "Jarqavieh"
1744: }
1745: },
1746: {
1747: "field": "locality",
1748: "key": "kashan",
1749: "name": {
1750: "en": "Kashan",
1751: "fa": "کاشان",
1752: "de": "Kashan"
1753: }
1754: },
1755: {
1756: "field": "locality",
1757: "key": "khansar",
1758: "name": {
1759: "en": "Khansar",
1760: "fa": "خوانسار",
1761: "de": "Khansar"
1762: }
1763: },
1764: {
1765: "field": "locality",
1766: "key": "khomeynishahr",
1767: "name": {
1768: "en": "Khomeyni Shahr",
1769: "fa": "خمینیشهر",
1770: "de": "Khomeyni Shahr"
1771: }
1772: },
1773: {
1774: "field": "locality",
1775: "key": "khurandbiabanak",
1776: "name": {
1777: "en": "Khur and Biabanak",
1778: "fa": "خور و بیابانک",
1779: "de": "Khur and Biabanak"
1780: }
1781: },
1782: {
1783: "field": "locality",
1784: "key": "kuhpayeh",
1785: "name": {
1786: "en": "Kuhpayeh",
1787: "fa": "کوهپایه",
1788: "de": "Kuhpayeh"
1789: }
1790: },
1791: {
1792: "field": "locality",
1793: "key": "lenjan",
1794: "name": {
1795: "en": "Lenjan",
1796: "fa": "لنجان",
1797: "de": "Lenjan"
1798: }
1799: },
1800: {
1801: "field": "locality",
1802: "key": "mobarakeh",
1803: "name": {
1804: "en": "Mobarakeh",
1805: "fa": "مبارکه",
1806: "de": "Mobarakeh"
1807: }
1808: },
1809: {
1810: "field": "locality",
1811: "key": "nain",
1812: "name": {
1813: "en": "Nain",
1814: "fa": "نایین",
1815: "de": "Nain"
1816: }
1817: },
1818: {
1819: "field": "locality",
1820: "key": "najafabad",
1821: "name": {
1822: "en": "Najafabad",
1823: "fa": "نجفآباد",
1824: "de": "Najafabad"
1825: }
1826: },
1827: {
1828: "field": "locality",
1829: "key": "natanz",
1830: "name": {
1831: "en": "Natanz",
1832: "fa": "نطنز",
1833: "de": "Natanz"
1834: }
1835: },
1836: {
1837: "field": "locality",
1838: "key": "semirom",
1839: "name": {
1840: "en": "Semirom",
1841: "fa": "سمیرم",
1842: "de": "Semirom"
1843: }
1844: },
1845: {
1846: "field": "locality",
1847: "key": "shahinshahrandmeymeh",
1848: "name": {
1849: "en": "Shahin Shahr and Meymeh",
1850: "fa": "شاهینشهر و میمه",
1851: "de": "Shahin Shahr and Meymeh"
1852: }
1853: },
1854: {
1855: "field": "locality",
1856: "key": "shahreza",
1857: "name": {
1858: "en": "Shahreza",
1859: "fa": "شهرضا",
1860: "de": "Shahreza"
1861: }
1862: },
1863: {
1864: "field": "locality",
1865: "key": "tiranandkarvan",
1866: "name": {
1867: "en": "Tiran and Karvan",
1868: "fa": "تیران و کرون",
1869: "de": "Tiran and Karvan"
1870: }
1871: },
1872: {
1873: "field": "locality",
1874: "key": "varzaneh",
1875: "name": {
1876: "en": "Varzaneh",
1877: "fa": "ورزنه",
1878: "de": "Varzaneh"
1879: }
1880: }
1881: ]
1882: },
1883: {
1884: "countryCode": "IR",
1885: "field": "administrative_area",
1886: "key": "kerman",
1887: "name": {
1888: "en": "Kerman",
1889: "fa": "کرمان",
1890: "de": "Kerman"
1891: },
1892: "children": [
1893: {
1894: "field": "locality",
1895: "key": "anar",
1896: "name": {
1897: "en": "Anar",
1898: "fa": "انار",
1899: "de": "Anar"
1900: }
1901: },
1902: {
1903: "field": "locality",
1904: "key": "anbarabad",
1905: "name": {
1906: "en": "Anbarabad",
1907: "fa": "عنبرآباد",
1908: "de": "Anbarabad"
1909: }
1910: },
1911: {
1912: "field": "locality",
1913: "key": "arzuiyeh",
1914: "name": {
1915: "en": "Arzuiyeh",
1916: "fa": "ارزوئیه",
1917: "de": "Arzuiyeh"
1918: }
1919: },
1920: {
1921: "field": "locality",
1922: "key": "baft",
1923: "name": {
1924: "en": "Baft",
1925: "fa": "بافت",
1926: "de": "Baft"
1927: }
1928: },
1929: {
1930: "field": "locality",
1931: "key": "bam",
1932: "name": {
1933: "en": "Bam",
1934: "fa": "بم",
1935: "de": "Bam"
1936: }
1937: },
1938: {
1939: "field": "locality",
1940: "key": "bardsir",
1941: "name": {
1942: "en": "Bardsir",
1943: "fa": "بردسیر",
1944: "de": "Bardsir"
1945: }
1946: },
1947: {
1948: "field": "locality",
1949: "key": "fahraj",
1950: "name": {
1951: "en": "Fahraj",
1952: "fa": "فهرج",
1953: "de": "Fahraj"
1954: }
1955: },
1956: {
1957: "field": "locality",
1958: "key": "faryab",
1959: "name": {
1960: "en": "Faryab",
1961: "fa": "فاریاب",
1962: "de": "Faryab"
1963: }
1964: },
1965: {
1966: "field": "locality",
1967: "key": "gonbaki",
1968: "name": {
1969: "en": "Gonbaki",
1970: "fa": "گنبکی",
1971: "de": "Gonbaki"
1972: }
1973: },
1974: {
1975: "field": "locality",
1976: "key": "jazmurian",
1977: "name": {
1978: "en": "Jazmurian",
1979: "fa": "جازموریان",
1980: "de": "Jazmurian"
1981: }
1982: },
1983: {
1984: "field": "locality",
1985: "key": "jiroft",
1986: "name": {
1987: "en": "Jiroft",
1988: "fa": "جیرفت",
1989: "de": "Jiroft"
1990: }
1991: },
1992: {
1993: "field": "locality",
1994: "key": "kahnuj",
1995: "name": {
1996: "en": "Kahnuj",
1997: "fa": "کهنوج",
1998: "de": "Kahnuj"
1999: }
2000: },
2001: {
2002: "field": "locality",
2003: "key": "kerman",
2004: "name": {
2005: "en": "Kerman",
2006: "fa": "کرمان",
2007: "de": "Kerman"
2008: }
2009: },
2010: {
2011: "field": "locality",
2012: "key": "kuhbanan",
2013: "name": {
2014: "en": "Kuhbanan",
2015: "fa": "کوهبنان",
2016: "de": "Kuhbanan"
2017: }
2018: },
2019: {
2020: "field": "locality",
2021: "key": "manujan",
2022: "name": {
2023: "en": "Manujan",
2024: "fa": "منوجان",
2025: "de": "Manujan"
2026: }
2027: },
2028: {
2029: "field": "locality",
2030: "key": "narmashir",
2031: "name": {
2032: "en": "Narmashir",
2033: "fa": "نرماشیر",
2034: "de": "Narmashir"
2035: }
2036: },
2037: {
2038: "field": "locality",
2039: "key": "qalehganj",
2040: "name": {
2041: "en": "Qaleh Ganj",
2042: "fa": "قلعهگنج",
2043: "de": "Qaleh Ganj"
2044: }
2045: },
2046: {
2047: "field": "locality",
2048: "key": "rabor",
2049: "name": {
2050: "en": "Rabor",
2051: "fa": "رابر",
2052: "de": "Rabor"
2053: }
2054: },
2055: {
2056: "field": "locality",
2057: "key": "rafsanjan",
2058: "name": {
2059: "en": "Rafsanjan",
2060: "fa": "رفسنجان",
2061: "de": "Rafsanjan"
2062: }
2063: },
2064: {
2065: "field": "locality",
2066: "key": "ravar",
2067: "name": {
2068: "en": "Ravar",
2069: "fa": "راور",
2070: "de": "Ravar"
2071: }
2072: },
2073: {
2074: "field": "locality",
2075: "key": "rigan",
2076: "name": {
2077: "en": "Rigan",
2078: "fa": "ریگان",
2079: "de": "Rigan"
2080: }
2081: },
2082: {
2083: "field": "locality",
2084: "key": "rudbarejonubi",
2085: "name": {
2086: "en": "Rudbar-e Jonubi",
2087: "fa": "رودبار جنوب",
2088: "de": "Rudbar-e Jonubi"
2089: }
2090: },
2091: {
2092: "field": "locality",
2093: "key": "shahrebabak",
2094: "name": {
2095: "en": "Shahr-e Babak",
2096: "fa": "شهر بابک",
2097: "de": "Shahr-e Babak"
2098: }
2099: },
2100: {
2101: "field": "locality",
2102: "key": "sirjan",
2103: "name": {
2104: "en": "Sirjan",
2105: "fa": "سیرجان",
2106: "de": "Sirjan"
2107: }
2108: },
2109: {
2110: "field": "locality",
2111: "key": "zarand",
2112: "name": {
2113: "en": "Zarand",
2114: "fa": "زرند",
2115: "de": "Zarand"
2116: }
2117: }
2118: ]
2119: },
2120: {
2121: "countryCode": "IR",
2122: "field": "administrative_area",
2123: "key": "kermanshah",
2124: "name": {
2125: "en": "Kermanshah",
2126: "fa": "کرمانشاه",
2127: "de": "Kermanschah"
2128: },
2129: "children": [
2130: {
2131: "field": "locality",
2132: "key": "dalahu",
2133: "name": {
2134: "en": "Dalahu",
2135: "fa": "دالاهو",
2136: "de": "Dalahu"
2137: }
2138: },
2139: {
2140: "field": "locality",
2141: "key": "gilanegharb",
2142: "name": {
2143: "en": "Gilan-e Gharb",
2144: "fa": "گیلان غرب",
2145: "de": "Gilan-e Gharb"
2146: }
2147: },
2148: {
2149: "field": "locality",
2150: "key": "harsin",
2151: "name": {
2152: "en": "Harsin",
2153: "fa": "هرسین",
2154: "de": "Harsin"
2155: }
2156: },
2157: {
2158: "field": "locality",
2159: "key": "javanrud",
2160: "name": {
2161: "en": "Javanrud",
2162: "fa": "جوانرود",
2163: "de": "Javanrud"
2164: }
2165: },
2166: {
2167: "field": "locality",
2168: "key": "kangavar",
2169: "name": {
2170: "en": "Kangavar",
2171: "fa": "کنگاور",
2172: "de": "Kangavar"
2173: }
2174: },
2175: {
2176: "field": "locality",
2177: "key": "kermanshah",
2178: "name": {
2179: "en": "Kermanshah",
2180: "fa": "کرمانشاه",
2181: "de": "Kermanschah"
2182: }
2183: },
2184: {
2185: "field": "locality",
2186: "key": "paveh",
2187: "name": {
2188: "en": "Paveh",
2189: "fa": "پاوه",
2190: "de": "Paveh"
2191: }
2192: },
2193: {
2194: "field": "locality",
2195: "key": "qasreshirin",
2196: "name": {
2197: "en": "Qasr-e Shirin",
2198: "fa": "قصر شیرین",
2199: "de": "Qasr-e Shirin"
2200: }
2201: },
2202: {
2203: "field": "locality",
2204: "key": "ravansar",
2205: "name": {
2206: "en": "Ravansar",
2207: "fa": "روانسر",
2208: "de": "Ravansar"
2209: }
2210: },
2211: {
2212: "field": "locality",
2213: "key": "sahneh",
2214: "name": {
2215: "en": "Sahneh",
2216: "fa": "صحنه",
2217: "de": "Sahneh"
2218: }
2219: },
2220: {
2221: "field": "locality",
2222: "key": "salasebabajani",
2223: "name": {
2224: "en": "Salas-e Babajani",
2225: "fa": "ثلاث باباجانی",
2226: "de": "Salas-e Babajani"
2227: }
2228: },
2229: {
2230: "field": "locality",
2231: "key": "sarpolezahab",
2232: "name": {
2233: "en": "Sarpol-e Zahab",
2234: "fa": "سرپل ذهاب",
2235: "de": "Sarpol-e Zahab"
2236: }
2237: },
2238: {
2239: "field": "locality",
2240: "key": "shahabadegharb",
2241: "name": {
2242: "en": "Shahabad-e Gharb",
2243: "fa": "شاهآباد غرب",
2244: "de": "Shahabad-e Gharb"
2245: }
2246: },
2247: {
2248: "field": "locality",
2249: "key": "sonqor",
2250: "name": {
2251: "en": "Sonqor",
2252: "fa": "سنقر",
2253: "de": "Sonqor"
2254: }
2255: }
2256: ]
2257: },
2258: {
2259: "countryCode": "IR",
2260: "field": "administrative_area",
2261: "key": "khuzestan",
2262: "name": {
2263: "en": "Khuzestan",
2264: "fa": "خوزستان",
2265: "de": "Chuzestan"
2266: },
2267: "children": [
2268: {
2269: "field": "locality",
2270: "key": "abadan",
2271: "name": {
2272: "en": "Abadan",
2273: "fa": "آبادان",
2274: "de": "Abadan"
2275: }
2276: },
2277: {
2278: "field": "locality",
2279: "key": "aghajri",
2280: "name": {
2281: "en": "Aghajri",
2282: "fa": "آغاجاری",
2283: "de": "Aghajri"
2284: }
2285: },
2286: {
2287: "field": "locality",
2288: "key": "ahvaz",
2289: "name": {
2290: "en": "Ahvaz",
2291: "fa": "اهواز",
2292: "de": "Ahvaz"
2293: }
2294: },
2295: {
2296: "field": "locality",
2297: "key": "andika",
2298: "name": {
2299: "en": "Andika",
2300: "fa": "اندیکا",
2301: "de": "Andika"
2302: }
2303: },
2304: {
2305: "field": "locality",
2306: "key": "andimeshk",
2307: "name": {
2308: "en": "Andimeshk",
2309: "fa": "اندیمشک",
2310: "de": "Andimeshk"
2311: }
2312: },
2313: {
2314: "field": "locality",
2315: "key": "baghemalek",
2316: "name": {
2317: "en": "Bagh-e Malek",
2318: "fa": "باغملک",
2319: "de": "Bagh-e Malek"
2320: }
2321: },
2322: {
2323: "field": "locality",
2324: "key": "bavi",
2325: "name": {
2326: "en": "Bavi",
2327: "fa": "باوی",
2328: "de": "Bavi"
2329: }
2330: },
2331: {
2332: "field": "locality",
2333: "key": "behbahan",
2334: "name": {
2335: "en": "Behbahan",
2336: "fa": "بهبهان",
2337: "de": "Behbahan"
2338: }
2339: },
2340: {
2341: "field": "locality",
2342: "key": "dashteazadegan",
2343: "name": {
2344: "en": "Dasht-e Azadegan",
2345: "fa": "دشت آزادگان",
2346: "de": "Dasht-e Azadegan"
2347: }
2348: },
2349: {
2350: "field": "locality",
2351: "key": "dezful",
2352: "name": {
2353: "en": "Dezful",
2354: "fa": "دزفول",
2355: "de": "Dezful"
2356: }
2357: },
2358: {
2359: "field": "locality",
2360: "key": "dezpart",
2361: "name": {
2362: "en": "Dezpart",
2363: "fa": "دزپارت",
2364: "de": "Dezpart"
2365: }
2366: },
2367: {
2368: "field": "locality",
2369: "key": "gotvand",
2370: "name": {
2371: "en": "Gotvand",
2372: "fa": "گتوند",
2373: "de": "Gotvand"
2374: }
2375: },
2376: {
2377: "field": "locality",
2378: "key": "haftkel",
2379: "name": {
2380: "en": "Haftkel",
2381: "fa": "هفتکل",
2382: "de": "Haftkel"
2383: }
2384: },
2385: {
2386: "field": "locality",
2387: "key": "hamidiyeh",
2388: "name": {
2389: "en": "Hamidiyeh",
2390: "fa": "حمیدیه",
2391: "de": "Hamidiyeh"
2392: }
2393: },
2394: {
2395: "field": "locality",
2396: "key": "hendijan",
2397: "name": {
2398: "en": "Hendijan",
2399: "fa": "هندیجان",
2400: "de": "Hendijan"
2401: }
2402: },
2403: {
2404: "field": "locality",
2405: "key": "hoveyzeh",
2406: "name": {
2407: "en": "Hoveyzeh",
2408: "fa": "هویزه",
2409: "de": "Hoveyzeh"
2410: }
2411: },
2412: {
2413: "field": "locality",
2414: "key": "izeh",
2415: "name": {
2416: "en": "Izeh",
2417: "fa": "ایذه",
2418: "de": "Izeh"
2419: }
2420: },
2421: {
2422: "field": "locality",
2423: "key": "karkheh",
2424: "name": {
2425: "en": "Karkheh",
2426: "fa": "کرخه",
2427: "de": "Karkheh"
2428: }
2429: },
2430: {
2431: "field": "locality",
2432: "key": "karun",
2433: "name": {
2434: "en": "Karun",
2435: "fa": "کارون",
2436: "de": "Karun"
2437: }
2438: },
2439: {
2440: "field": "locality",
2441: "key": "khorramshahr",
2442: "name": {
2443: "en": "Khorramshahr",
2444: "fa": "خرمشهر",
2445: "de": "Khorramshahr"
2446: }
2447: },
2448: {
2449: "field": "locality",
2450: "key": "lali",
2451: "name": {
2452: "en": "Lali",
2453: "fa": "لالی",
2454: "de": "Lali"
2455: }
2456: },
2457: {
2458: "field": "locality",
2459: "key": "mahshahr",
2460: "name": {
2461: "en": "Mahshahr",
2462: "fa": "بندر ماهشهر",
2463: "de": "Mahshahr"
2464: }
2465: },
2466: {
2467: "field": "locality",
2468: "key": "masjedsoleyman",
2469: "name": {
2470: "en": "Masjed Soleyman",
2471: "fa": "مسجدسلیمان",
2472: "de": "Masjed Soleyman"
2473: }
2474: },
2475: {
2476: "field": "locality",
2477: "key": "omidiyeh",
2478: "name": {
2479: "en": "Omidiyeh",
2480: "fa": "امیدیه",
2481: "de": "Omidiyeh"
2482: }
2483: },
2484: {
2485: "field": "locality",
2486: "key": "ramhormoz",
2487: "name": {
2488: "en": "Ramhormoz",
2489: "fa": "رامهرمز",
2490: "de": "Ramhormoz"
2491: }
2492: },
2493: {
2494: "field": "locality",
2495: "key": "ramshir",
2496: "name": {
2497: "en": "Ramshir",
2498: "fa": "رامشیر",
2499: "de": "Ramshir"
2500: }
2501: },
2502: {
2503: "field": "locality",
2504: "key": "seydun",
2505: "name": {
2506: "en": "Seydun",
2507: "fa": "سیدون",
2508: "de": "Seydun"
2509: }
2510: },
2511: {
2512: "field": "locality",
2513: "key": "shadegan",
2514: "name": {
2515: "en": "Shadegan",
2516: "fa": "شادگان",
2517: "de": "Shadegan"
2518: }
2519: },
2520: {
2521: "field": "locality",
2522: "key": "shush",
2523: "name": {
2524: "en": "Shush",
2525: "fa": "شوش",
2526: "de": "Shush"
2527: }
2528: },
2529: {
2530: "field": "locality",
2531: "key": "shushtar",
2532: "name": {
2533: "en": "Shushtar",
2534: "fa": "شوشتر",
2535: "de": "Shushtar"
2536: }
2537: }
2538: ]
2539: },
2540: {
2541: "countryCode": "IR",
2542: "field": "administrative_area",
2543: "key": "kohgiluyehandboyerahmad",
2544: "name": {
2545: "en": "Kohgiluyeh and Boyer-Ahmad",
2546: "fa": "کهگیلویه و بویراحمد",
2547: "de": "Kohgiluye und Buyer Ahmad"
2548: },
2549: "children": [
2550: {
2551: "field": "locality",
2552: "key": "bahmai",
2553: "name": {
2554: "en": "Bahmai",
2555: "fa": "بهمئی",
2556: "de": "Bahmai"
2557: }
2558: },
2559: {
2560: "field": "locality",
2561: "key": "basht",
2562: "name": {
2563: "en": "Basht",
2564: "fa": "باشت",
2565: "de": "Basht"
2566: }
2567: },
2568: {
2569: "field": "locality",
2570: "key": "boyerahmad",
2571: "name": {
2572: "en": "Boyer-Ahmad",
2573: "fa": "بویراحمد",
2574: "de": "Boyer-Ahmad"
2575: }
2576: },
2577: {
2578: "field": "locality",
2579: "key": "charam",
2580: "name": {
2581: "en": "Charam",
2582: "fa": "چرام",
2583: "de": "Charam"
2584: }
2585: },
2586: {
2587: "field": "locality",
2588: "key": "dana",
2589: "name": {
2590: "en": "Dana",
2591: "fa": "دنا",
2592: "de": "Dana"
2593: }
2594: },
2595: {
2596: "field": "locality",
2597: "key": "gachsaran",
2598: "name": {
2599: "en": "Gachsaran",
2600: "fa": "گچساران",
2601: "de": "Gachsaran"
2602: }
2603: },
2604: {
2605: "field": "locality",
2606: "key": "kohgiluyeh",
2607: "name": {
2608: "en": "Kohgiluyeh",
2609: "fa": "کهگیلویه",
2610: "de": "Kohgiluyeh"
2611: }
2612: },
2613: {
2614: "field": "locality",
2615: "key": "landeh",
2616: "name": {
2617: "en": "Landeh",
2618: "fa": "لنده",
2619: "de": "Landeh"
2620: }
2621: },
2622: {
2623: "field": "locality",
2624: "key": "margown",
2625: "name": {
2626: "en": "Margown",
2627: "fa": "مارگون",
2628: "de": "Margown"
2629: }
2630: }
2631: ]
2632: },
2633: {
2634: "countryCode": "IR",
2635: "field": "administrative_area",
2636: "key": "kurdistan",
2637: "name": {
2638: "en": "Kurdistan",
2639: "fa": "کردستان",
2640: "de": "Kurdistan"
2641: },
2642: "children": [
2643: {
2644: "field": "locality",
2645: "key": "baneh",
2646: "name": {
2647: "en": "Baneh",
2648: "fa": "بانه",
2649: "de": "Baneh"
2650: }
2651: },
2652: {
2653: "field": "locality",
2654: "key": "bijar",
2655: "name": {
2656: "en": "Bijar",
2657: "fa": "بیجار",
2658: "de": "Bijar"
2659: }
2660: },
2661: {
2662: "field": "locality",
2663: "key": "dehgolan",
2664: "name": {
2665: "en": "Dehgolan",
2666: "fa": "دهگلان",
2667: "de": "Dehgolan"
2668: }
2669: },
2670: {
2671: "field": "locality",
2672: "key": "divandarreh",
2673: "name": {
2674: "en": "Divandarreh",
2675: "fa": "دیواندره",
2676: "de": "Divandarreh"
2677: }
2678: },
2679: {
2680: "field": "locality",
2681: "key": "kamyaran",
2682: "name": {
2683: "en": "Kamyaran",
2684: "fa": "کامیاران",
2685: "de": "Kamyaran"
2686: }
2687: },
2688: {
2689: "field": "locality",
2690: "key": "marivan",
2691: "name": {
2692: "en": "Marivan",
2693: "fa": "مریوان",
2694: "de": "Marivan"
2695: }
2696: },
2697: {
2698: "field": "locality",
2699: "key": "qorveh",
2700: "name": {
2701: "en": "Qorveh",
2702: "fa": "قروه",
2703: "de": "Qorveh"
2704: }
2705: },
2706: {
2707: "field": "locality",
2708: "key": "sanandaj",
2709: "name": {
2710: "en": "Sanandaj",
2711: "fa": "سنندج",
2712: "de": "Sanandaj"
2713: }
2714: },
2715: {
2716: "field": "locality",
2717: "key": "saqqez",
2718: "name": {
2719: "en": "Saqqez",
2720: "fa": "سقز",
2721: "de": "Saqqez"
2722: }
2723: },
2724: {
2725: "field": "locality",
2726: "key": "sarvabad",
2727: "name": {
2728: "en": "Sarvabad",
2729: "fa": "سروآباد",
2730: "de": "Sarvabad"
2731: }
2732: }
2733: ]
2734: },
2735: {
2736: "countryCode": "IR",
2737: "field": "administrative_area",
2738: "key": "lorestan",
2739: "name": {
2740: "en": "Lorestan",
2741: "fa": "لرستان",
2742: "de": "Lorestan"
2743: },
2744: "children": [
2745: {
2746: "field": "locality",
2747: "key": "aligudarz",
2748: "name": {
2749: "en": "Aligudarz",
2750: "fa": "الیگودرز",
2751: "de": "Aligudarz"
2752: }
2753: },
2754: {
2755: "field": "locality",
2756: "key": "azna",
2757: "name": {
2758: "en": "Azna",
2759: "fa": "ازنا",
2760: "de": "Azna"
2761: }
2762: },
2763: {
2764: "field": "locality",
2765: "key": "borujerd",
2766: "name": {
2767: "en": "Borujerd",
2768: "fa": "بروجرد",
2769: "de": "Borujerd"
2770: }
2771: },
2772: {
2773: "field": "locality",
2774: "key": "delfan",
2775: "name": {
2776: "en": "Delfan",
2777: "fa": "دلفان",
2778: "de": "Delfan"
2779: }
2780: },
2781: {
2782: "field": "locality",
2783: "key": "dorud",
2784: "name": {
2785: "en": "Dorud",
2786: "fa": "دورود",
2787: "de": "Dorud"
2788: }
2789: },
2790: {
2791: "field": "locality",
2792: "key": "dowreh",
2793: "name": {
2794: "en": "Dowreh",
2795: "fa": "دوره",
2796: "de": "Dowreh"
2797: }
2798: },
2799: {
2800: "field": "locality",
2801: "key": "khorramabad",
2802: "name": {
2803: "en": "Khorramabad",
2804: "fa": "خرمآباد",
2805: "de": "Khorramabad"
2806: }
2807: },
2808: {
2809: "field": "locality",
2810: "key": "kuhdasht",
2811: "name": {
2812: "en": "Kuhdasht",
2813: "fa": "کوهدشت",
2814: "de": "Kuhdasht"
2815: }
2816: },
2817: {
2818: "field": "locality",
2819: "key": "poledokhtar",
2820: "name": {
2821: "en": "Pol-e Dokhtar",
2822: "fa": "پلدختر",
2823: "de": "Pol-e Dokhtar"
2824: }
2825: },
2826: {
2827: "field": "locality",
2828: "key": "rumeshkan",
2829: "name": {
2830: "en": "Rumeshkan",
2831: "fa": "رومشکان",
2832: "de": "Rumeshkan"
2833: }
2834: },
2835: {
2836: "field": "locality",
2837: "key": "selseleh",
2838: "name": {
2839: "en": "Selseleh",
2840: "fa": "سلسله",
2841: "de": "Selseleh"
2842: }
2843: }
2844: ]
2845: },
2846: {
2847: "countryCode": "IR",
2848: "field": "administrative_area",
2849: "key": "markazi",
2850: "name": {
2851: "en": "Markazi",
2852: "fa": "مرکزی",
2853: "de": "Markazi"
2854: },
2855: "children": [
2856: {
2857: "field": "locality",
2858: "key": "arak",
2859: "name": {
2860: "en": "Arak",
2861: "fa": "اراک",
2862: "de": "Arak"
2863: }
2864: },
2865: {
2866: "field": "locality",
2867: "key": "ashtian",
2868: "name": {
2869: "en": "Ashtian",
2870: "fa": "آشتیان",
2871: "de": "Ashtian"
2872: }
2873: },
2874: {
2875: "field": "locality",
2876: "key": "delijan",
2877: "name": {
2878: "en": "Delijan",
2879: "fa": "دلیجان",
2880: "de": "Delijan"
2881: }
2882: },
2883: {
2884: "field": "locality",
2885: "key": "farahan",
2886: "name": {
2887: "en": "Farahan",
2888: "fa": "فراهان",
2889: "de": "Farahan"
2890: }
2891: },
2892: {
2893: "field": "locality",
2894: "key": "khomeyn",
2895: "name": {
2896: "en": "Khomeyn",
2897: "fa": "خمین",
2898: "de": "Khomeyn"
2899: }
2900: },
2901: {
2902: "field": "locality",
2903: "key": "khondab",
2904: "name": {
2905: "en": "Khondab",
2906: "fa": "خنداب",
2907: "de": "Khondab"
2908: }
2909: },
2910: {
2911: "field": "locality",
2912: "key": "komijan",
2913: "name": {
2914: "en": "Komijan",
2915: "fa": "کمیجان",
2916: "de": "Komijan"
2917: }
2918: },
2919: {
2920: "field": "locality",
2921: "key": "mahallat",
2922: "name": {
2923: "en": "Mahallat",
2924: "fa": "محلات",
2925: "de": "Mahallat"
2926: }
2927: },
2928: {
2929: "field": "locality",
2930: "key": "saveh",
2931: "name": {
2932: "en": "Saveh",
2933: "fa": "ساوه",
2934: "de": "Saveh"
2935: }
2936: },
2937: {
2938: "field": "locality",
2939: "key": "shazand",
2940: "name": {
2941: "en": "Shazand",
2942: "fa": "شازند",
2943: "de": "Shazand"
2944: }
2945: },
2946: {
2947: "field": "locality",
2948: "key": "tafresh",
2949: "name": {
2950: "en": "Tafresh",
2951: "fa": "تفرش",
2952: "de": "Tafresh"
2953: }
2954: },
2955: {
2956: "field": "locality",
2957: "key": "zarandiyeh",
2958: "name": {
2959: "en": "Zarandiyeh",
2960: "fa": "زرندیه",
2961: "de": "Zarandiyeh"
2962: }
2963: }
2964: ]
2965: },
2966: {
2967: "countryCode": "IR",
2968: "field": "administrative_area",
2969: "key": "mazandaran",
2970: "name": {
2971: "en": "Mazandaran",
2972: "fa": "مازندران",
2973: "de": "Mazandaran"
2974: },
2975: "children": [
2976: {
2977: "field": "locality",
2978: "key": "abbasabad",
2979: "name": {
2980: "en": "Abbasabad",
2981: "fa": "عباسآباد",
2982: "de": "Abbasabad"
2983: }
2984: },
2985: {
2986: "field": "locality",
2987: "key": "amol",
2988: "name": {
2989: "en": "Amol",
2990: "fa": "آمل",
2991: "de": "Amol"
2992: }
2993: },
2994: {
2995: "field": "locality",
2996: "key": "babol",
2997: "name": {
2998: "en": "Babol",
2999: "fa": "بابل",
3000: "de": "Babol"
3001: }
3002: },
3003: {
3004: "field": "locality",
3005: "key": "babolsar",
3006: "name": {
3007: "en": "Babolsar",
3008: "fa": "بابلسر",
3009: "de": "Babolsar"
3010: }
3011: },
3012: {
3013: "field": "locality",
3014: "key": "behshahr",
3015: "name": {
3016: "en": "Behshahr",
3017: "fa": "بهشهر",
3018: "de": "Behshahr"
3019: }
3020: },
3021: {
3022: "field": "locality",
3023: "key": "chalus",
3024: "name": {
3025: "en": "Chalus",
3026: "fa": "چالوس",
3027: "de": "Chalus"
3028: }
3029: },
3030: {
3031: "field": "locality",
3032: "key": "fereydunkenar",
3033: "name": {
3034: "en": "Fereydunkenar",
3035: "fa": "فریدونکنار",
3036: "de": "Fereydunkenar"
3037: }
3038: },
3039: {
3040: "field": "locality",
3041: "key": "galugah",
3042: "name": {
3043: "en": "Galugah",
3044: "fa": "گلوگاه",
3045: "de": "Galugah"
3046: }
3047: },
3048: {
3049: "field": "locality",
3050: "key": "juybar",
3051: "name": {
3052: "en": "Juybar",
3053: "fa": "جویبار",
3054: "de": "Juybar"
3055: }
3056: },
3057: {
3058: "field": "locality",
3059: "key": "kelardasht",
3060: "name": {
3061: "en": "Kelardasht",
3062: "fa": "کلاردشت",
3063: "de": "Kelardasht"
3064: }
3065: },
3066: {
3067: "field": "locality",
3068: "key": "mahmudabad",
3069: "name": {
3070: "en": "Mahmudabad",
3071: "fa": "محمودآباد",
3072: "de": "Mahmudabad"
3073: }
3074: },
3075: {
3076: "field": "locality",
3077: "key": "miandorud",
3078: "name": {
3079: "en": "Miandorud",
3080: "fa": "میاندورود",
3081: "de": "Miandorud"
3082: }
3083: },
3084: {
3085: "field": "locality",
3086: "key": "neka",
3087: "name": {
3088: "en": "Neka",
3089: "fa": "نکا",
3090: "de": "Neka"
3091: }
3092: },
3093: {
3094: "field": "locality",
3095: "key": "northsavadkuh",
3096: "name": {
3097: "en": "North Savadkuh",
3098: "fa": "سوادکوه شمالی",
3099: "de": "North Savadkuh"
3100: }
3101: },
3102: {
3103: "field": "locality",
3104: "key": "nowshahr",
3105: "name": {
3106: "en": "Nowshahr",
3107: "fa": "نوشهر",
3108: "de": "Nowshahr"
3109: }
3110: },
3111: {
3112: "field": "locality",
3113: "key": "nur",
3114: "name": {
3115: "en": "Nur",
3116: "fa": "نور",
3117: "de": "Nur"
3118: }
3119: },
3120: {
3121: "field": "locality",
3122: "key": "qaemshahr",
3123: "name": {
3124: "en": "Qaem Shahr",
3125: "fa": "قائمشهر",
3126: "de": "Qaem Shahr"
3127: }
3128: },
3129: {
3130: "field": "locality",
3131: "key": "ramsar",
3132: "name": {
3133: "en": "Ramsar",
3134: "fa": "رامسر",
3135: "de": "Ramsar"
3136: }
3137: },
3138: {
3139: "field": "locality",
3140: "key": "sari",
3141: "name": {
3142: "en": "Sari",
3143: "fa": "ساری",
3144: "de": "Sari"
3145: }
3146: },
3147: {
3148: "field": "locality",
3149: "key": "savadkuh",
3150: "name": {
3151: "en": "Savadkuh",
3152: "fa": "سوادکوه",
3153: "de": "Savadkuh"
3154: }
3155: },
3156: {
3157: "field": "locality",
3158: "key": "simorgh",
3159: "name": {
3160: "en": "Simorgh",
3161: "fa": "سیمرغ",
3162: "de": "Simorgh"
3163: }
3164: },
3165: {
3166: "field": "locality",
3167: "key": "tonekabon",
3168: "name": {
3169: "en": "Tonekabon",
3170: "fa": "تنکابن",
3171: "de": "Tonekabon"
3172: }
3173: }
3174: ]
3175: },
3176: {
3177: "countryCode": "IR",
3178: "field": "administrative_area",
3179: "key": "northkhorasan",
3180: "name": {
3181: "en": "North Khorasan",
3182: "fa": "خراسان شمالی",
3183: "de": "Nordchorasan"
3184: },
3185: "children": [
3186: {
3187: "field": "locality",
3188: "key": "bamandsafiabad",
3189: "name": {
3190: "en": "Bam and Safiabad",
3191: "fa": "بام و صفیآباد",
3192: "de": "Bam and Safiabad"
3193: }
3194: },
3195: {
3196: "field": "locality",
3197: "key": "bojnord",
3198: "name": {
3199: "en": "Bojnord",
3200: "fa": "بجنورد",
3201: "de": "Bojnord"
3202: }
3203: },
3204: {
3205: "field": "locality",
3206: "key": "esfarayen",
3207: "name": {
3208: "en": "Esfarayen",
3209: "fa": "اسفراین",
3210: "de": "Esfarayen"
3211: }
3212: },
3213: {
3214: "field": "locality",
3215: "key": "faruj",
3216: "name": {
3217: "en": "Faruj",
3218: "fa": "فاروج",
3219: "de": "Faruj"
3220: }
3221: },
3222: {
3223: "field": "locality",
3224: "key": "garmeh",
3225: "name": {
3226: "en": "Garmeh",
3227: "fa": "گرمه",
3228: "de": "Garmeh"
3229: }
3230: },
3231: {
3232: "field": "locality",
3233: "key": "jajrom",
3234: "name": {
3235: "en": "Jajrom",
3236: "fa": "جاجرم",
3237: "de": "Jajrom"
3238: }
3239: },
3240: {
3241: "field": "locality",
3242: "key": "maneh",
3243: "name": {
3244: "en": "Maneh",
3245: "fa": "مانه و سملقان",
3246: "de": "Maneh"
3247: }
3248: },
3249: {
3250: "field": "locality",
3251: "key": "razandjargalan",
3252: "name": {
3253: "en": "Raz and Jargalan",
3254: "fa": "راز و جرگلان",
3255: "de": "Raz and Jargalan"
3256: }
3257: },
3258: {
3259: "field": "locality",
3260: "key": "samalqan",
3261: "name": {
3262: "en": "Samalqan",
3263: "fa": "سملقان",
3264: "de": "Samalqan"
3265: }
3266: },
3267: {
3268: "field": "locality",
3269: "key": "shirvan",
3270: "name": {
3271: "en": "Shirvan",
3272: "fa": "شیروان",
3273: "de": "Shirvan"
3274: }
3275: }
3276: ]
3277: },
3278: {
3279: "countryCode": "IR",
3280: "field": "administrative_area",
3281: "key": "qazvin",
3282: "name": {
3283: "en": "Qazvin",
3284: "fa": "قزوین",
3285: "de": "Ghazvin"
3286: },
3287: "children": [
3288: {
3289: "field": "locality",
3290: "key": "abyek",
3291: "name": {
3292: "en": "Abyek",
3293: "fa": "آبیک",
3294: "de": "Abyek"
3295: }
3296: },
3297: {
3298: "field": "locality",
3299: "key": "alborz",
3300: "name": {
3301: "en": "Alborz",
3302: "fa": "البرز",
3303: "de": "Alborz"
3304: }
3305: },
3306: {
3307: "field": "locality",
3308: "key": "avaj",
3309: "name": {
3310: "en": "Avaj",
3311: "fa": "آوج",
3312: "de": "Avaj"
3313: }
3314: },
3315: {
3316: "field": "locality",
3317: "key": "buinzahra",
3318: "name": {
3319: "en": "Buin Zahra",
3320: "fa": "بوئینزهرا",
3321: "de": "Buin Zahra"
3322: }
3323: },
3324: {
3325: "field": "locality",
3326: "key": "qazvin",
3327: "name": {
3328: "en": "Qazvin",
3329: "fa": "قزوین",
3330: "de": "Ghazvin"
3331: }
3332: },
3333: {
3334: "field": "locality",
3335: "key": "takestan",
3336: "name": {
3337: "en": "Takestan",
3338: "fa": "تاکستان",
3339: "de": "Takestan"
3340: }
3341: }
3342: ]
3343: },
3344: {
3345: "countryCode": "IR",
3346: "field": "administrative_area",
3347: "key": "qom",
3348: "name": {
3349: "en": "Qom",
3350: "fa": "قم",
3351: "de": "Ghom"
3352: },
3353: "children": [
3354: {
3355: "field": "locality",
3356: "key": "jafarabad",
3357: "name": {
3358: "en": "Jafarabad",
3359: "fa": "جعفرآباد",
3360: "de": "Jafarabad"
3361: }
3362: },
3363: {
3364: "field": "locality",
3365: "key": "kahak",
3366: "name": {
3367: "en": "Kahak",
3368: "fa": "کهک",
3369: "de": "Kahak"
3370: }
3371: },
3372: {
3373: "field": "locality",
3374: "key": "qom",
3375: "name": {
3376: "en": "Qom",
3377: "fa": "قم",
3378: "de": "Ghom"
3379: }
3380: }
3381: ]
3382: },
3383: {
3384: "countryCode": "IR",
3385: "field": "administrative_area",
3386: "key": "razavikhorasan",
3387: "name": {
3388: "en": "Razavi Khorasan",
3389: "fa": "خراسان رضوی",
3390: "de": "Chorasan-e Razawi"
3391: },
3392: "children": [
3393: {
3394: "field": "locality",
3395: "key": "bajestan",
3396: "name": {
3397: "en": "Bajestan",
3398: "fa": "بجستان",
3399: "de": "Bajestan"
3400: }
3401: },
3402: {
3403: "field": "locality",
3404: "key": "bakharz",
3405: "name": {
3406: "en": "Bakharz",
3407: "fa": "باخرز",
3408: "de": "Bakharz"
3409: }
3410: },
3411: {
3412: "field": "locality",
3413: "key": "bardaskan",
3414: "name": {
3415: "en": "Bardaskan",
3416: "fa": "بردسکن",
3417: "de": "Bardaskan"
3418: }
3419: },
3420: {
3421: "field": "locality",
3422: "key": "chenaran",
3423: "name": {
3424: "en": "Chenaran",
3425: "fa": "چناران",
3426: "de": "Chenaran"
3427: }
3428: },
3429: {
3430: "field": "locality",
3431: "key": "dargaz",
3432: "name": {
3433: "en": "Dargaz",
3434: "fa": "درگز",
3435: "de": "Dargaz"
3436: }
3437: },
3438: {
3439: "field": "locality",
3440: "key": "davarzan",
3441: "name": {
3442: "en": "Davarzan",
3443: "fa": "داورزن",
3444: "de": "Davarzan"
3445: }
3446: },
3447: {
3448: "field": "locality",
3449: "key": "fariman",
3450: "name": {
3451: "en": "Fariman",
3452: "fa": "فریمان",
3453: "de": "Fariman"
3454: }
3455: },
3456: {
3457: "field": "locality",
3458: "key": "firuzeh",
3459: "name": {
3460: "en": "Firuzeh",
3461: "fa": "فیروزه",
3462: "de": "Firuzeh"
3463: }
3464: },
3465: {
3466: "field": "locality",
3467: "key": "golbahar",
3468: "name": {
3469: "en": "Golbahar",
3470: "fa": "گلبهار",
3471: "de": "Golbahar"
3472: }
3473: },
3474: {
3475: "field": "locality",
3476: "key": "gonabad",
3477: "name": {
3478: "en": "Gonabad",
3479: "fa": "گناباد",
3480: "de": "Gonabad"
3481: }
3482: },
3483: {
3484: "field": "locality",
3485: "key": "joghatai",
3486: "name": {
3487: "en": "Joghatai",
3488: "fa": "جغتای",
3489: "de": "Joghatai"
3490: }
3491: },
3492: {
3493: "field": "locality",
3494: "key": "joveyn",
3495: "name": {
3496: "en": "Joveyn",
3497: "fa": "جوین",
3498: "de": "Joveyn"
3499: }
3500: },
3501: {
3502: "field": "locality",
3503: "key": "kalat",
3504: "name": {
3505: "en": "Kalat",
3506: "fa": "کلات",
3507: "de": "Kalat"
3508: }
3509: },
3510: {
3511: "field": "locality",
3512: "key": "kashmar",
3513: "name": {
3514: "en": "Kashmar",
3515: "fa": "کاشمر",
3516: "de": "Kashmar"
3517: }
3518: },
3519: {
3520: "field": "locality",
3521: "key": "khaf",
3522: "name": {
3523: "en": "Khaf",
3524: "fa": "خواف",
3525: "de": "Khaf"
3526: }
3527: },
3528: {
3529: "field": "locality",
3530: "key": "khalilabad",
3531: "name": {
3532: "en": "Khalilabad",
3533: "fa": "خلیلآباد",
3534: "de": "Khalilabad"
3535: }
3536: },
3537: {
3538: "field": "locality",
3539: "key": "khoshab",
3540: "name": {
3541: "en": "Khoshab",
3542: "fa": "خوشاب",
3543: "de": "Khoshab"
3544: }
3545: },
3546: {
3547: "field": "locality",
3548: "key": "kuhsorkh",
3549: "name": {
3550: "en": "Kuhsorkh",
3551: "fa": "کوهسرخ",
3552: "de": "Kuhsorkh"
3553: }
3554: },
3555: {
3556: "field": "locality",
3557: "key": "mahvelat",
3558: "name": {
3559: "en": "Mahvelat",
3560: "fa": "مهولات",
3561: "de": "Mahvelat"
3562: }
3563: },
3564: {
3565: "field": "locality",
3566: "key": "mashhad",
3567: "name": {
3568: "en": "Mashhad",
3569: "fa": "مشهد",
3570: "de": "Mashhad"
3571: }
3572: },
3573: {
3574: "field": "locality",
3575: "key": "miyanjolgeh",
3576: "name": {
3577: "en": "Miyan Jolgeh",
3578: "fa": "میانجلگه",
3579: "de": "Miyan Jolgeh"
3580: }
3581: },
3582: {
3583: "field": "locality",
3584: "key": "nishapur",
3585: "name": {
3586: "en": "Nishapur",
3587: "fa": "نیشابور",
3588: "de": "Nishapur"
3589: }
3590: },
3591: {
3592: "field": "locality",
3593: "key": "quchan",
3594: "name": {
3595: "en": "Quchan",
3596: "fa": "قوچان",
3597: "de": "Quchan"
3598: }
3599: },
3600: {
3601: "field": "locality",
3602: "key": "roshtkhar",
3603: "name": {
3604: "en": "Roshtkhar",
3605: "fa": "رشتخوار",
3606: "de": "Roshtkhar"
3607: }
3608: },
3609: {
3610: "field": "locality",
3611: "key": "sabzevar",
3612: "name": {
3613: "en": "Sabzevar",
3614: "fa": "سبزوار",
3615: "de": "Sabzevar"
3616: }
3617: },
3618: {
3619: "field": "locality",
3620: "key": "salehabad",
3621: "name": {
3622: "en": "Salehabad",
3623: "fa": "صالحآباد",
3624: "de": "Salehabad"
3625: }
3626: },
3627: {
3628: "field": "locality",
3629: "key": "sarakhs",
3630: "name": {
3631: "en": "Sarakhs",
3632: "fa": "سرخس",
3633: "de": "Sarakhs"
3634: }
3635: },
3636: {
3637: "field": "locality",
3638: "key": "sheshtamad",
3639: "name": {
3640: "en": "Sheshtamad",
3641: "fa": "ششتمد",
3642: "de": "Sheshtamad"
3643: }
3644: },
3645: {
3646: "field": "locality",
3647: "key": "taybad",
3648: "name": {
3649: "en": "Taybad",
3650: "fa": "تایباد",
3651: "de": "Taybad"
3652: }
3653: },
3654: {
3655: "field": "locality",
3656: "key": "torbateheydarieh",
3657: "name": {
3658: "en": "Torbat-e Heydarieh",
3659: "fa": "تربت حیدریه",
3660: "de": "Torbat-e Heydarieh"
3661: }
3662: },
3663: {
3664: "field": "locality",
3665: "key": "torbatejam",
3666: "name": {
3667: "en": "Torbat-e Jam",
3668: "fa": "تربت جام",
3669: "de": "Torbat-e Jam"
3670: }
3671: },
3672: {
3673: "field": "locality",
3674: "key": "torqabehandshandiz",
3675: "name": {
3676: "en": "Torqabeh and Shandiz",
3677: "fa": "طرقبه و شاندیز",
3678: "de": "Torqabeh and Shandiz"
3679: }
3680: },
3681: {
3682: "field": "locality",
3683: "key": "zaveh",
3684: "name": {
3685: "en": "Zaveh",
3686: "fa": "زاوه",
3687: "de": "Zaveh"
3688: }
3689: },
3690: {
3691: "field": "locality",
3692: "key": "zeberkhan",
3693: "name": {
3694: "en": "Zeberkhan",
3695: "fa": "زبرخان",
3696: "de": "Zeberkhan"
3697: }
3698: }
3699: ]
3700: },
3701: {
3702: "countryCode": "IR",
3703: "field": "administrative_area",
3704: "key": "semnan",
3705: "name": {
3706: "en": "Semnan",
3707: "fa": "سمنان",
3708: "de": "Semnan"
3709: },
3710: "children": [
3711: {
3712: "field": "locality",
3713: "key": "aradan",
3714: "name": {
3715: "en": "Aradan",
3716: "fa": "آرادان",
3717: "de": "Aradan"
3718: }
3719: },
3720: {
3721: "field": "locality",
3722: "key": "damghan",
3723: "name": {
3724: "en": "Damghan",
3725: "fa": "دامغان",
3726: "de": "Damghan"
3727: }
3728: },
3729: {
3730: "field": "locality",
3731: "key": "garmsar",
3732: "name": {
3733: "en": "Garmsar",
3734: "fa": "گرمسار",
3735: "de": "Garmsar"
3736: }
3737: },
3738: {
3739: "field": "locality",
3740: "key": "mehdishahr",
3741: "name": {
3742: "en": "Mehdishahr",
3743: "fa": "مهدیشهر",
3744: "de": "Mehdishahr"
3745: }
3746: },
3747: {
3748: "field": "locality",
3749: "key": "meyami",
3750: "name": {
3751: "en": "Meyami",
3752: "fa": "میامی",
3753: "de": "Meyami"
3754: }
3755: },
3756: {
3757: "field": "locality",
3758: "key": "semnan",
3759: "name": {
3760: "en": "Semnan",
3761: "fa": "سمنان",
3762: "de": "Semnan"
3763: }
3764: },
3765: {
3766: "field": "locality",
3767: "key": "shahrud",
3768: "name": {
3769: "en": "Shahrud",
3770: "fa": "شاهرود",
3771: "de": "Shahrud"
3772: }
3773: },
3774: {
3775: "field": "locality",
3776: "key": "sorkheh",
3777: "name": {
3778: "en": "Sorkheh",
3779: "fa": "سرخه",
3780: "de": "Sorkheh"
3781: }
3782: }
3783: ]
3784: },
3785: {
3786: "countryCode": "IR",
3787: "field": "administrative_area",
3788: "key": "sistanandbaluchistan",
3789: "name": {
3790: "en": "Sistan and Baluchistan",
3791: "fa": "سیستان و بلوچستان",
3792: "de": "Sistan und Belutschistan"
3793: },
3794: "children": [
3795: {
3796: "field": "locality",
3797: "key": "bampur",
3798: "name": {
3799: "en": "Bampur",
3800: "fa": "بمپور",
3801: "de": "Bampur"
3802: }
3803: },
3804: {
3805: "field": "locality",
3806: "key": "chabahar",
3807: "name": {
3808: "en": "Chabahar",
3809: "fa": "چابهار",
3810: "de": "Chabahar"
3811: }
3812: },
3813: {
3814: "field": "locality",
3815: "key": "dalgan",
3816: "name": {
3817: "en": "Dalgan",
3818: "fa": "دلگان",
3819: "de": "Dalgan"
3820: }
3821: },
3822: {
3823: "field": "locality",
3824: "key": "dashtiari",
3825: "name": {
3826: "en": "Dashtiari",
3827: "fa": "دشتیاری",
3828: "de": "Dashtiari"
3829: }
3830: },
3831: {
3832: "field": "locality",
3833: "key": "fanuj",
3834: "name": {
3835: "en": "Fanuj",
3836: "fa": "فنوج",
3837: "de": "Fanuj"
3838: }
3839: },
3840: {
3841: "field": "locality",
3842: "key": "golshan",
3843: "name": {
3844: "en": "Golshan",
3845: "fa": "گلشن",
3846: "de": "Golshan"
3847: }
3848: },
3849: {
3850: "field": "locality",
3851: "key": "hamun",
3852: "name": {
3853: "en": "Hamun",
3854: "fa": "هامون",
3855: "de": "Hamun"
3856: }
3857: },
3858: {
3859: "field": "locality",
3860: "key": "hirmand",
3861: "name": {
3862: "en": "Hirmand",
3863: "fa": "هیرمند",
3864: "de": "Hirmand"
3865: }
3866: },
3867: {
3868: "field": "locality",
3869: "key": "iranshahr",
3870: "name": {
3871: "en": "Iranshahr",
3872: "fa": "ایرانشهر",
3873: "de": "Iranshahr"
3874: }
3875: },
3876: {
3877: "field": "locality",
3878: "key": "khash",
3879: "name": {
3880: "en": "Khash",
3881: "fa": "خاش",
3882: "de": "Khash"
3883: }
3884: },
3885: {
3886: "field": "locality",
3887: "key": "konarak",
3888: "name": {
3889: "en": "Konarak",
3890: "fa": "کنارک",
3891: "de": "Konarak"
3892: }
3893: },
3894: {
3895: "field": "locality",
3896: "key": "lashar",
3897: "name": {
3898: "en": "Lashar",
3899: "fa": "لاشار",
3900: "de": "Lashar"
3901: }
3902: },
3903: {
3904: "field": "locality",
3905: "key": "mehrestan",
3906: "name": {
3907: "en": "Mehrestan",
3908: "fa": "مهرستان",
3909: "de": "Mehrestan"
3910: }
3911: },
3912: {
3913: "field": "locality",
3914: "key": "mirjaveh",
3915: "name": {
3916: "en": "Mirjaveh",
3917: "fa": "میرجاوه",
3918: "de": "Mirjaveh"
3919: }
3920: },
3921: {
3922: "field": "locality",
3923: "key": "nikshahr",
3924: "name": {
3925: "en": "Nik Shahr",
3926: "fa": "نیکشهر",
3927: "de": "Nik Shahr"
3928: }
3929: },
3930: {
3931: "field": "locality",
3932: "key": "nimruz",
3933: "name": {
3934: "en": "Nimruz",
3935: "fa": "نیمروز",
3936: "de": "Nimruz"
3937: }
3938: },
3939: {
3940: "field": "locality",
3941: "key": "qasreqand",
3942: "name": {
3943: "en": "Qasr-e Qand",
3944: "fa": "قصرقند",
3945: "de": "Qasr-e Qand"
3946: }
3947: },
3948: {
3949: "field": "locality",
3950: "key": "rask",
3951: "name": {
3952: "en": "Rask",
3953: "fa": "راسک",
3954: "de": "Rask"
3955: }
3956: },
3957: {
3958: "field": "locality",
3959: "key": "saravan",
3960: "name": {
3961: "en": "Saravan",
3962: "fa": "سراوان",
3963: "de": "Saravan"
3964: }
3965: },
3966: {
3967: "field": "locality",
3968: "key": "sarbaz",
3969: "name": {
3970: "en": "Sarbaz",
3971: "fa": "سرباز",
3972: "de": "Sarbaz"
3973: }
3974: },
3975: {
3976: "field": "locality",
3977: "key": "sibandsuran",
3978: "name": {
3979: "en": "Sib and Suran",
3980: "fa": "سیب و سوران",
3981: "de": "Sib and Suran"
3982: }
3983: },
3984: {
3985: "field": "locality",
3986: "key": "taftan",
3987: "name": {
3988: "en": "Taftan",
3989: "fa": "تفتان",
3990: "de": "Taftan"
3991: }
3992: },
3993: {
3994: "field": "locality",
3995: "key": "zabol",
3996: "name": {
3997: "en": "Zabol",
3998: "fa": "زابل",
3999: "de": "Zabol"
4000: }
4001: },
4002: {
4003: "field": "locality",
4004: "key": "zahedan",
4005: "name": {
4006: "en": "Zahedan",
4007: "fa": "زاهدان",
4008: "de": "Zahedan"
4009: }
4010: },
4011: {
4012: "field": "locality",
4013: "key": "zarabad",
4014: "name": {
4015: "en": "Zarabad",
4016: "fa": "زرآباد",
4017: "de": "Zarabad"
4018: }
4019: },
4020: {
4021: "field": "locality",
4022: "key": "zehak",
4023: "name": {
4024: "en": "Zehak",
4025: "fa": "زهک",
4026: "de": "Zehak"
4027: }
4028: }
4029: ]
4030: },
4031: {
4032: "countryCode": "IR",
4033: "field": "administrative_area",
4034: "key": "southkhorasan",
4035: "name": {
4036: "en": "South Khorasan",
4037: "fa": "خراسان جنوبی",
4038: "de": "Südchorasan"
4039: },
4040: "children": [
4041: {
4042: "field": "locality",
4043: "key": "birjand",
4044: "name": {
4045: "en": "Birjand",
4046: "fa": "بیرجند",
4047: "de": "Birjand"
4048: }
4049: },
4050: {
4051: "field": "locality",
4052: "key": "boshruyeh",
4053: "name": {
4054: "en": "Boshruyeh",
4055: "fa": "بشرویه",
4056: "de": "Boshruyeh"
4057: }
4058: },
4059: {
4060: "field": "locality",
4061: "key": "darmian",
4062: "name": {
4063: "en": "Darmian",
4064: "fa": "درمیان",
4065: "de": "Darmian"
4066: }
4067: },
4068: {
4069: "field": "locality",
4070: "key": "ferdows",
4071: "name": {
4072: "en": "Ferdows",
4073: "fa": "فردوس",
4074: "de": "Ferdows"
4075: }
4076: },
4077: {
4078: "field": "locality",
4079: "key": "khusf",
4080: "name": {
4081: "en": "Khusf",
4082: "fa": "خوسف",
4083: "de": "Khusf"
4084: }
4085: },
4086: {
4087: "field": "locality",
4088: "key": "nehbandan",
4089: "name": {
4090: "en": "Nehbandan",
4091: "fa": "نهبندان",
4092: "de": "Nehbandan"
4093: }
4094: },
4095: {
4096: "field": "locality",
4097: "key": "qaen",
4098: "name": {
4099: "en": "Qaen",
4100: "fa": "قائنات",
4101: "de": "Qaen"
4102: }
4103: },
4104: {
4105: "field": "locality",
4106: "key": "sarayan",
4107: "name": {
4108: "en": "Sarayan",
4109: "fa": "سرایان",
4110: "de": "Sarayan"
4111: }
4112: },
4113: {
4114: "field": "locality",
4115: "key": "sarbisheh",
4116: "name": {
4117: "en": "Sarbisheh",
4118: "fa": "سربیشه",
4119: "de": "Sarbisheh"
4120: }
4121: },
4122: {
4123: "field": "locality",
4124: "key": "tabas",
4125: "name": {
4126: "en": "Tabas",
4127: "fa": "طبس",
4128: "de": "Tabas"
4129: }
4130: },
4131: {
4132: "field": "locality",
4133: "key": "zirkuh",
4134: "name": {
4135: "en": "Zirkuh",
4136: "fa": "زیرکوه",
4137: "de": "Zirkuh"
4138: }
4139: }
4140: ]
4141: },
4142: {
4143: "countryCode": "IR",
4144: "field": "administrative_area",
4145: "key": "tehran",
4146: "name": {
4147: "en": "Tehran",
4148: "fa": "تهران",
4149: "de": "Teheran"
4150: },
4151: "children": [
4152: {
4153: "field": "locality",
4154: "key": "baharestan",
4155: "name": {
4156: "en": "Baharestan",
4157: "fa": "بهارستان",
4158: "de": "Baharestan"
4159: }
4160: },
4161: {
4162: "field": "locality",
4163: "key": "damavand",
4164: "name": {
4165: "en": "Damavand",
4166: "fa": "دماوند",
4167: "de": "Damavand"
4168: }
4169: },
4170: {
4171: "field": "locality",
4172: "key": "eslamshahr",
4173: "name": {
4174: "en": "Eslamshahr",
4175: "fa": "اسلامشهر",
4176: "de": "Eslamshahr"
4177: }
4178: },
4179: {
4180: "field": "locality",
4181: "key": "firuzkuh",
4182: "name": {
4183: "en": "Firuzkuh",
4184: "fa": "فیروزکوه",
4185: "de": "Firuzkuh"
4186: }
4187: },
4188: {
4189: "field": "locality",
4190: "key": "malard",
4191: "name": {
4192: "en": "Malard",
4193: "fa": "ملارد",
4194: "de": "Malard"
4195: }
4196: },
4197: {
4198: "field": "locality",
4199: "key": "pakdasht",
4200: "name": {
4201: "en": "Pakdasht",
4202: "fa": "پاکدشت",
4203: "de": "Pakdasht"
4204: }
4205: },
4206: {
4207: "field": "locality",
4208: "key": "pardis",
4209: "name": {
4210: "en": "Pardis",
4211: "fa": "پردیس",
4212: "de": "Pardis"
4213: }
4214: },
4215: {
4216: "field": "locality",
4217: "key": "pishva",
4218: "name": {
4219: "en": "Pishva",
4220: "fa": "پیشوا",
4221: "de": "Pishva"
4222: }
4223: },
4224: {
4225: "field": "locality",
4226: "key": "qarchak",
4227: "name": {
4228: "en": "Qarchak",
4229: "fa": "قرچک",
4230: "de": "Qarchak"
4231: }
4232: },
4233: {
4234: "field": "locality",
4235: "key": "qods",
4236: "name": {
4237: "en": "Qods",
4238: "fa": "قدس",
4239: "de": "Qods"
4240: }
4241: },
4242: {
4243: "field": "locality",
4244: "key": "ray",
4245: "name": {
4246: "en": "Ray",
4247: "fa": "ری",
4248: "de": "Ray"
4249: }
4250: },
4251: {
4252: "field": "locality",
4253: "key": "robatkarim",
4254: "name": {
4255: "en": "Robat Karim",
4256: "fa": "رباطکریم",
4257: "de": "Robat Karim"
4258: }
4259: },
4260: {
4261: "field": "locality",
4262: "key": "shahriar",
4263: "name": {
4264: "en": "Shahriar",
4265: "fa": "شهریار",
4266: "de": "Shahriar"
4267: }
4268: },
4269: {
4270: "field": "locality",
4271: "key": "shemiranat",
4272: "name": {
4273: "en": "Shemiranat",
4274: "fa": "شمیرانات",
4275: "de": "Shemiranat"
4276: }
4277: },
4278: {
4279: "field": "locality",
4280: "key": "tehran",
4281: "name": {
4282: "en": "Tehran",
4283: "fa": "تهران",
4284: "de": "Teheran"
4285: }
4286: },
4287: {
4288: "field": "locality",
4289: "key": "varamin",
4290: "name": {
4291: "en": "Varamin",
4292: "fa": "ورامین",
4293: "de": "Varamin"
4294: }
4295: }
4296: ]
4297: },
4298: {
4299: "countryCode": "IR",
4300: "field": "administrative_area",
4301: "key": "westazerbaijan",
4302: "name": {
4303: "en": "West Azerbaijan",
4304: "fa": "آذربایجان غربی",
4305: "de": "West-Aserbaidschan"
4306: },
4307: "children": [
4308: {
4309: "field": "locality",
4310: "key": "baruq",
4311: "name": {
4312: "en": "Baruq",
4313: "fa": "باروق",
4314: "de": "Baruq"
4315: }
4316: },
4317: {
4318: "field": "locality",
4319: "key": "bukan",
4320: "name": {
4321: "en": "Bukan",
4322: "fa": "بوکان",
4323: "de": "Bukan"
4324: }
4325: },
4326: {
4327: "field": "locality",
4328: "key": "chaharborj",
4329: "name": {
4330: "en": "Chaharborj",
4331: "fa": "چهاربرج",
4332: "de": "Chaharborj"
4333: }
4334: },
4335: {
4336: "field": "locality",
4337: "key": "chaldoran",
4338: "name": {
4339: "en": "Chaldoran",
4340: "fa": "چالدران",
4341: "de": "Chaldoran"
4342: }
4343: },
4344: {
4345: "field": "locality",
4346: "key": "chaypareh",
4347: "name": {
4348: "en": "Chaypareh",
4349: "fa": "چایپاره",
4350: "de": "Chaypareh"
4351: }
4352: },
4353: {
4354: "field": "locality",
4355: "key": "khoy",
4356: "name": {
4357: "en": "Khoy",
4358: "fa": "خوی",
4359: "de": "Khoy"
4360: }
4361: },
4362: {
4363: "field": "locality",
4364: "key": "mahabad",
4365: "name": {
4366: "en": "Mahabad",
4367: "fa": "مهاباد",
4368: "de": "Mahabad"
4369: }
4370: },
4371: {
4372: "field": "locality",
4373: "key": "maku",
4374: "name": {
4375: "en": "Maku",
4376: "fa": "ماکو",
4377: "de": "Maku"
4378: }
4379: },
4380: {
4381: "field": "locality",
4382: "key": "miandoab",
4383: "name": {
4384: "en": "Miandoab",
4385: "fa": "میاندوآب",
4386: "de": "Miandoab"
4387: }
4388: },
4389: {
4390: "field": "locality",
4391: "key": "mirabad",
4392: "name": {
4393: "en": "Mirabad",
4394: "fa": "میرآباد",
4395: "de": "Mirabad"
4396: }
4397: },
4398: {
4399: "field": "locality",
4400: "key": "naqadeh",
4401: "name": {
4402: "en": "Naqadeh",
4403: "fa": "نقده",
4404: "de": "Naqadeh"
4405: }
4406: },
4407: {
4408: "field": "locality",
4409: "key": "oshnavieh",
4410: "name": {
4411: "en": "Oshnavieh",
4412: "fa": "اشنویه",
4413: "de": "Oshnavieh"
4414: }
4415: },
4416: {
4417: "field": "locality",
4418: "key": "piranshahr",
4419: "name": {
4420: "en": "Piranshahr",
4421: "fa": "پیرانشهر",
4422: "de": "Piranshahr"
4423: }
4424: },
4425: {
4426: "field": "locality",
4427: "key": "poldasht",
4428: "name": {
4429: "en": "Poldasht",
4430: "fa": "پلدشت",
4431: "de": "Poldasht"
4432: }
4433: },
4434: {
4435: "field": "locality",
4436: "key": "salmas",
4437: "name": {
4438: "en": "Salmas",
4439: "fa": "سلماس",
4440: "de": "Salmas"
4441: }
4442: },
4443: {
4444: "field": "locality",
4445: "key": "sardasht",
4446: "name": {
4447: "en": "Sardasht",
4448: "fa": "سردشت",
4449: "de": "Sardasht"
4450: }
4451: },
4452: {
4453: "field": "locality",
4454: "key": "shahindezh",
4455: "name": {
4456: "en": "Shahin Dezh",
4457: "fa": "شاهیندژ",
4458: "de": "Shahin Dezh"
4459: }
4460: },
4461: {
4462: "field": "locality",
4463: "key": "showt",
4464: "name": {
4465: "en": "Showt",
4466: "fa": "شوط",
4467: "de": "Showt"
4468: }
4469: },
4470: {
4471: "field": "locality",
4472: "key": "takab",
4473: "name": {
4474: "en": "Takab",
4475: "fa": "تکاب",
4476: "de": "Takab"
4477: }
4478: },
4479: {
4480: "field": "locality",
4481: "key": "urmia",
4482: "name": {
4483: "en": "Urmia",
4484: "fa": "ارومیه",
4485: "de": "Urmia"
4486: }
4487: }
4488: ]
4489: },
4490: {
4491: "countryCode": "IR",
4492: "field": "administrative_area",
4493: "key": "yazd",
4494: "name": {
4495: "en": "Yazd",
4496: "fa": "یزد",
4497: "de": "Yazd"
4498: },
4499: "children": [
4500: {
4501: "field": "locality",
4502: "key": "abarkuh",
4503: "name": {
4504: "en": "Abarkuh",
4505: "fa": "ابرکوه",
4506: "de": "Abarkuh"
4507: }
4508: },
4509: {
4510: "field": "locality",
4511: "key": "ardakan",
4512: "name": {
4513: "en": "Ardakan",
4514: "fa": "اردکان",
4515: "de": "Ardakan"
4516: }
4517: },
4518: {
4519: "field": "locality",
4520: "key": "ashkezar",
4521: "name": {
4522: "en": "Ashkezar",
4523: "fa": "اشکذر",
4524: "de": "Ashkezar"
4525: }
4526: },
4527: {
4528: "field": "locality",
4529: "key": "bafq",
4530: "name": {
4531: "en": "Bafq",
4532: "fa": "بافق",
4533: "de": "Bafq"
4534: }
4535: },
4536: {
4537: "field": "locality",
4538: "key": "behabad",
4539: "name": {
4540: "en": "Behabad",
4541: "fa": "بهاباد",
4542: "de": "Behabad"
4543: }
4544: },
4545: {
4546: "field": "locality",
4547: "key": "khatam",
4548: "name": {
4549: "en": "Khatam",
4550: "fa": "خاتم",
4551: "de": "Khatam"
4552: }
4553: },
4554: {
4555: "field": "locality",
4556: "key": "marvast",
4557: "name": {
4558: "en": "Marvast",
4559: "fa": "مروست",
4560: "de": "Marvast"
4561: }
4562: },
4563: {
4564: "field": "locality",
4565: "key": "mehriz",
4566: "name": {
4567: "en": "Mehriz",
4568: "fa": "مهریز",
4569: "de": "Mehriz"
4570: }
4571: },
4572: {
4573: "field": "locality",
4574: "key": "meybod",
4575: "name": {
4576: "en": "Meybod",
4577: "fa": "میبد",
4578: "de": "Meybod"
4579: }
4580: },
4581: {
4582: "field": "locality",
4583: "key": "taft",
4584: "name": {
4585: "en": "Taft",
4586: "fa": "تفت",
4587: "de": "Taft"
4588: }
4589: },
4590: {
4591: "field": "locality",
4592: "key": "yazd",
4593: "name": {
4594: "en": "Yazd",
4595: "fa": "یزد",
4596: "de": "Yazd"
4597: }
4598: },
4599: {
4600: "field": "locality",
4601: "key": "zarach",
4602: "name": {
4603: "en": "Zarach",
4604: "fa": "زارچ",
4605: "de": "Zarach"
4606: }
4607: }
4608: ]
4609: },
4610: {
4611: "countryCode": "IR",
4612: "field": "administrative_area",
4613: "key": "zanjan",
4614: "name": {
4615: "en": "Zanjan",
4616: "fa": "زنجان",
4617: "de": "Zanjan"
4618: },
4619: "children": [
4620: {
4621: "field": "locality",
4622: "key": "abhar",
4623: "name": {
4624: "en": "Abhar",
4625: "fa": "ابهر",
4626: "de": "Abhar"
4627: }
4628: },
4629: {
4630: "field": "locality",
4631: "key": "ijrud",
4632: "name": {
4633: "en": "Ijrud",
4634: "fa": "ایجرود",
4635: "de": "Ijrud"
4636: }
4637: },
4638: {
4639: "field": "locality",
4640: "key": "khodabandeh",
4641: "name": {
4642: "en": "Khodabandeh",
4643: "fa": "خدابنده",
4644: "de": "Khodabandeh"
4645: }
4646: },
4647: {
4648: "field": "locality",
4649: "key": "khorramdarreh",
4650: "name": {
4651: "en": "Khorramdarreh",
4652: "fa": "خرمدره",
4653: "de": "Khorramdarreh"
4654: }
4655: },
4656: {
4657: "field": "locality",
4658: "key": "mahneshan",
4659: "name": {
4660: "en": "Mahneshan",
4661: "fa": "ماهنشان",
4662: "de": "Mahneshan"
4663: }
4664: },
4665: {
4666: "field": "locality",
4667: "key": "soltaniyeh",
4668: "name": {
4669: "en": "Soltaniyeh",
4670: "fa": "سلطانیه",
4671: "de": "Soltaniyeh"
4672: }
4673: },
4674: {
4675: "field": "locality",
4676: "key": "tarom",
4677: "name": {
4678: "en": "Tarom",
4679: "fa": "طارم",
4680: "de": "Tarom"
4681: }
4682: },
4683: {
4684: "field": "locality",
4685: "key": "zanjan",
4686: "name": {
4687: "en": "Zanjan",
4688: "fa": "زنجان",
4689: "de": "Zanjan"
4690: }
4691: }
4692: ]
4693: }
4694: ]
1: [
2: {
3: "code": "IR",
4: "name": {
5: "en": "Iran",
6: "fa": "ایران",
7: "de": "Iran"
8: },
9: "phoneCode": "98",
10: "addressLabels": {
11: "administrativeArea": {
12: "en": "Province",
13: "fa": "استان",
14: "de": "Provinz"
15: },
16: "locality": {
17: "en": "County",
18: "fa": "شهرستان",
19: "de": "Landkreis"
20: },
21: "postalCode": {
22: "en": "Postal Code",
23: "fa": "کد پستی",
24: "de": "Postleitzahl"
25: }
26: }
27: },
28: {
29: "code": "TR",
30: "name": {
31: "en": "Turkey",
32: "fa": "ترکیه",
33: "de": "Türkei"
34: },
35: "phoneCode": "90"
36: },
37: {
38: "code": "SA",
39: "name": {
40: "en": "Saudi Arabia",
41: "fa": "عربستان سعودی",
42: "de": "Saudi-Arabien"
43: },
44: "phoneCode": "966"
45: },
46: {
47: "code": "AE",
48: "name": {
49: "en": "United Arab Emirates",
50: "fa": "امارات متحده عربی",
51: "de": "Vereinigte Arabische Emirate"
52: },
53: "phoneCode": "971"
54: },
55: {
56: "code": "IQ",
57: "name": {
58: "en": "Iraq",
59: "fa": "عراق",
60: "de": "Irak"
61: },
62: "phoneCode": "964"
63: },
64: {
65: "code": "AF",
66: "name": {
67: "en": "Afghanistan",
68: "fa": "افغانستان",
69: "de": "Afghanistan"
70: },
71: "phoneCode": "93"
72: },
73: {
74: "code": "PK",
75: "name": {
76: "en": "Pakistan",
77: "fa": "پاکستان",
78: "de": "Pakistan"
79: },
80: "phoneCode": "92"
81: },
82: {
83: "code": "KZ",
84: "name": {
85: "en": "Kazakhstan",
86: "fa": "قزاقستان",
87: "de": "Kasachstan"
88: },
89: "phoneCode": "7"
90: },
91: {
92: "code": "UZ",
93: "name": {
94: "en": "Uzbekistan",
95: "fa": "ازبکستان",
96: "de": "Usbekistan"
97: },
98: "phoneCode": "998"
99: },
100: {
101: "code": "TM",
102: "name": {
103: "en": "Turkmenistan",
104: "fa": "ترکمنستان",
105: "de": "Turkmenistan"
106: },
107: "phoneCode": "993"
108: },
109: {
110: "code": "TJ",
111: "name": {
112: "en": "Tajikistan",
113: "fa": "تاجیکستان",
114: "de": "Tadschikistan"
115: },
116: "phoneCode": "992"
117: },
118: {
119: "code": "KG",
120: "name": {
121: "en": "Kyrgyzstan",
122: "fa": "قرقیزستان",
123: "de": "Kirgisistan"
124: },
125: "phoneCode": "996"
126: },
127: {
128: "code": "US",
129: "name": {
130: "en": "United States",
131: "fa": "ایالات متحده آمریکا",
132: "de": "Vereinigte Staaten"
133: },
134: "phoneCode": "1"
135: },
136: {
137: "code": "CA",
138: "name": {
139: "en": "Canada",
140: "fa": "کانادا",
141: "de": "Kanada"
142: },
143: "phoneCode": "1"
144: },
145: {
146: "code": "MX",
147: "name": {
148: "en": "Mexico",
149: "fa": "مکزیک",
150: "de": "Mexiko"
151: },
152: "phoneCode": "52"
153: },
154: {
155: "code": "GB",
156: "name": {
157: "en": "United Kingdom",
158: "fa": "انگلستان",
159: "de": "Vereinigtes Königreich"
160: },
161: "phoneCode": "44"
162: },
163: {
164: "code": "DE",
165: "name": {
166: "en": "Germany",
167: "fa": "آلمان",
168: "de": "Deutschland"
169: },
170: "phoneCode": "49",
171: "addressLabels": {
172: "administrativeArea": {
173: "en": "State",
174: "fa": "ایالت",
175: "de": "Bundesland"
176: },
177: "locality": {
178: "en": "Ort",
179: "fa": "موقعیت مکانی (Ort)",
180: "de": "Ort"
181: },
182: "postalCode": {
183: "en": "PLZ Code",
184: "fa": "کد PLZ",
185: "de": "PLZ Code"
186: }
187: }
188: },
189: {
190: "code": "FR",
191: "name": {
192: "en": "France",
193: "fa": "فرانسه",
194: "de": "Frankreich"
195: },
196: "phoneCode": "33"
197: },
198: {
199: "code": "IT",
200: "name": {
201: "en": "Italy",
202: "fa": "ایتالیا",
203: "de": "Italien"
204: },
205: "phoneCode": "39"
206: },
207: {
208: "code": "ES",
209: "name": {
210: "en": "Spain",
211: "fa": "اسپانیا",
212: "de": "Spanien"
213: },
214: "phoneCode": "34"
215: },
216: {
217: "code": "NL",
218: "name": {
219: "en": "Netherlands",
220: "fa": "هلند",
221: "de": "Niederlande"
222: },
223: "phoneCode": "31"
224: },
225: {
226: "code": "SE",
227: "name": {
228: "en": "Sweden",
229: "fa": "سوئد",
230: "de": "Schweden"
231: },
232: "phoneCode": "46"
233: },
234: {
235: "code": "NO",
236: "name": {
237: "en": "Norway",
238: "fa": "نروژ",
239: "de": "Norwegen"
240: },
241: "phoneCode": "47"
242: },
243: {
244: "code": "DK",
245: "name": {
246: "en": "Denmark",
247: "fa": "دانمارک",
248: "de": "Dänemark"
249: },
250: "phoneCode": "45"
251: },
252: {
253: "code": "FI",
254: "name": {
255: "en": "Finland",
256: "fa": "فنلاند",
257: "de": "Finnland"
258: },
259: "phoneCode": "358"
260: },
261: {
262: "code": "CH",
263: "name": {
264: "en": "Switzerland",
265: "fa": "سوئیس",
266: "de": "Schweiz"
267: },
268: "phoneCode": "41"
269: },
270: {
271: "code": "AT",
272: "name": {
273: "en": "Austria",
274: "fa": "اتریش",
275: "de": "Österreich"
276: },
277: "phoneCode": "43"
278: },
279: {
280: "code": "BE",
281: "name": {
282: "en": "Belgium",
283: "fa": "بلژیک",
284: "de": "Belgien"
285: },
286: "phoneCode": "32"
287: },
288: {
289: "code": "PL",
290: "name": {
291: "en": "Poland",
292: "fa": "لهستان",
293: "de": "Polen"
294: },
295: "phoneCode": "48"
296: },
297: {
298: "code": "RU",
299: "name": {
300: "en": "Russia",
301: "fa": "روسیه",
302: "de": "Russland"
303: },
304: "phoneCode": "7"
305: },
306: {
307: "code": "UA",
308: "name": {
309: "en": "Ukraine",
310: "fa": "اوکراین",
311: "de": "Ukraine"
312: },
313: "phoneCode": "380"
314: },
315: {
316: "code": "CZ",
317: "name": {
318: "en": "Czech Republic",
319: "fa": "جمهوری چک",
320: "de": "Tschechien"
321: },
322: "phoneCode": "420"
323: },
324: {
325: "code": "HU",
326: "name": {
327: "en": "Hungary",
328: "fa": "مجارستان",
329: "de": "Ungarn"
330: },
331: "phoneCode": "36"
332: },
333: {
334: "code": "RO",
335: "name": {
336: "en": "Romania",
337: "fa": "رومانی",
338: "de": "Rumänien"
339: },
340: "phoneCode": "40"
341: },
342: {
343: "code": "BG",
344: "name": {
345: "en": "Bulgaria",
346: "fa": "بلغارستان",
347: "de": "Bulgarien"
348: },
349: "phoneCode": "359"
350: },
351: {
352: "code": "GR",
353: "name": {
354: "en": "Greece",
355: "fa": "یونان",
356: "de": "Griechenland"
357: },
358: "phoneCode": "30"
359: },
360: {
361: "code": "PT",
362: "name": {
363: "en": "Portugal",
364: "fa": "پرتغال",
365: "de": "Portugal"
366: },
367: "phoneCode": "351"
368: },
369: {
370: "code": "IE",
371: "name": {
372: "en": "Ireland",
373: "fa": "ایرلند",
374: "de": "Irland"
375: },
376: "phoneCode": "353"
377: },
378: {
379: "code": "AU",
380: "name": {
381: "en": "Australia",
382: "fa": "استرالیا",
383: "de": "Australien"
384: },
385: "phoneCode": "61"
386: },
387: {
388: "code": "NZ",
389: "name": {
390: "en": "New Zealand",
391: "fa": "نیوزیلند",
392: "de": "Neuseeland"
393: },
394: "phoneCode": "64"
395: },
396: {
397: "code": "JP",
398: "name": {
399: "en": "Japan",
400: "fa": "ژاپن",
401: "de": "Japan"
402: },
403: "phoneCode": "81"
404: },
405: {
406: "code": "KR",
407: "name": {
408: "en": "South Korea",
409: "fa": "کره جنوبی",
410: "de": "Südkorea"
411: },
412: "phoneCode": "82"
413: },
414: {
415: "code": "CN",
416: "name": {
417: "en": "China",
418: "fa": "چین",
419: "de": "China"
420: },
421: "phoneCode": "86"
422: },
423: {
424: "code": "IN",
425: "name": {
426: "en": "India",
427: "fa": "هند",
428: "de": "Indien"
429: },
430: "phoneCode": "91"
431: },
432: {
433: "code": "TH",
434: "name": {
435: "en": "Thailand",
436: "fa": "تایلند",
437: "de": "Thailand"
438: },
439: "phoneCode": "66"
440: },
441: {
442: "code": "VN",
443: "name": {
444: "en": "Vietnam",
445: "fa": "ویتنام",
446: "de": "Vietnam"
447: },
448: "phoneCode": "84"
449: },
450: {
451: "code": "MY",
452: "name": {
453: "en": "Malaysia",
454: "fa": "مالزی",
455: "de": "Malaysia"
456: },
457: "phoneCode": "60"
458: },
459: {
460: "code": "SG",
461: "name": {
462: "en": "Singapore",
463: "fa": "سنگاپور",
464: "de": "Singapur"
465: },
466: "phoneCode": "65"
467: },
468: {
469: "code": "ID",
470: "name": {
471: "en": "Indonesia",
472: "fa": "اندونزی",
473: "de": "Indonesien"
474: },
475: "phoneCode": "62"
476: },
477: {
478: "code": "PH",
479: "name": {
480: "en": "Philippines",
481: "fa": "فیلیپین",
482: "de": "Philippinen"
483: },
484: "phoneCode": "63"
485: },
486: {
487: "code": "BD",
488: "name": {
489: "en": "Bangladesh",
490: "fa": "بنگلادش",
491: "de": "Bangladesch"
492: },
493: "phoneCode": "880"
494: },
495: {
496: "code": "LK",
497: "name": {
498: "en": "Sri Lanka",
499: "fa": "سریلانکا",
500: "de": "Sri Lanka"
501: },
502: "phoneCode": "94"
503: },
504: {
505: "code": "NP",
506: "name": {
507: "en": "Nepal",
508: "fa": "نپال",
509: "de": "Nepal"
510: },
511: "phoneCode": "977"
512: },
513: {
514: "code": "BT",
515: "name": {
516: "en": "Bhutan",
517: "fa": "بوتان",
518: "de": "Bhutan"
519: },
520: "phoneCode": "975"
521: },
522: {
523: "code": "MV",
524: "name": {
525: "en": "Maldives",
526: "fa": "مالدیو",
527: "de": "Malediven"
528: },
529: "phoneCode": "960"
530: },
531: {
532: "code": "BR",
533: "name": {
534: "en": "Brazil",
535: "fa": "برزیل",
536: "de": "Brasilien"
537: },
538: "phoneCode": "55"
539: },
540: {
541: "code": "AR",
542: "name": {
543: "en": "Argentina",
544: "fa": "آرژانتین",
545: "de": "Argentinien"
546: },
547: "phoneCode": "54"
548: },
549: {
550: "code": "CL",
551: "name": {
552: "en": "Chile",
553: "fa": "شیلی",
554: "de": "Chile"
555: },
556: "phoneCode": "56"
557: },
558: {
559: "code": "CO",
560: "name": {
561: "en": "Colombia",
562: "fa": "کلمبیا",
563: "de": "Kolumbien"
564: },
565: "phoneCode": "57"
566: },
567: {
568: "code": "PE",
569: "name": {
570: "en": "Peru",
571: "fa": "پرو",
572: "de": "Peru"
573: },
574: "phoneCode": "51"
575: },
576: {
577: "code": "VE",
578: "name": {
579: "en": "Venezuela",
580: "fa": "ونزوئلا",
581: "de": "Venezuela"
582: },
583: "phoneCode": "58"
584: },
585: {
586: "code": "EC",
587: "name": {
588: "en": "Ecuador",
589: "fa": "اکوادور",
590: "de": "Ecuador"
591: },
592: "phoneCode": "593"
593: },
594: {
595: "code": "BO",
596: "name": {
597: "en": "Bolivia",
598: "fa": "بولیوی",
599: "de": "Bolivien"
600: },
601: "phoneCode": "591"
602: },
603: {
604: "code": "PY",
605: "name": {
606: "en": "Paraguay",
607: "fa": "پاراگوئه",
608: "de": "Paraguay"
609: },
610: "phoneCode": "595"
611: },
612: {
613: "code": "UY",
614: "name": {
615: "en": "Uruguay",
616: "fa": "اروگوئه",
617: "de": "Uruguay"
618: },
619: "phoneCode": "598"
620: },
621: {
622: "code": "GY",
623: "name": {
624: "en": "Guyana",
625: "fa": "گویان",
626: "de": "Guyana"
627: },
628: "phoneCode": "592"
629: },
630: {
631: "code": "SR",
632: "name": {
633: "en": "Suriname",
634: "fa": "سورینام",
635: "de": "Suriname"
636: },
637: "phoneCode": "597"
638: },
639: {
640: "code": "ZA",
641: "name": {
642: "en": "South Africa",
643: "fa": "آفریقای جنوبی",
644: "de": "Südafrika"
645: },
646: "phoneCode": "27"
647: },
648: {
649: "code": "NG",
650: "name": {
651: "en": "Nigeria",
652: "fa": "نیجریه",
653: "de": "Nigeria"
654: },
655: "phoneCode": "234"
656: },
657: {
658: "code": "KE",
659: "name": {
660: "en": "Kenya",
661: "fa": "کنیا",
662: "de": "Kenia"
663: },
664: "phoneCode": "254"
665: },
666: {
667: "code": "MA",
668: "name": {
669: "en": "Morocco",
670: "fa": "مراکش",
671: "de": "Marokko"
672: },
673: "phoneCode": "212"
674: },
675: {
676: "code": "TN",
677: "name": {
678: "en": "Tunisia",
679: "fa": "تونس",
680: "de": "Tunesien"
681: },
682: "phoneCode": "216"
683: },
684: {
685: "code": "DZ",
686: "name": {
687: "en": "Algeria",
688: "fa": "الجزایر",
689: "de": "Algerien"
690: },
691: "phoneCode": "213"
692: },
693: {
694: "code": "LY",
695: "name": {
696: "en": "Libya",
697: "fa": "لیبی",
698: "de": "Libyen"
699: },
700: "phoneCode": "218"
701: },
702: {
703: "code": "EG",
704: "name": {
705: "en": "Egypt",
706: "fa": "مصر",
707: "de": "Ägypten"
708: },
709: "phoneCode": "20"
710: },
711: {
712: "code": "SD",
713: "name": {
714: "en": "Sudan",
715: "fa": "سودان",
716: "de": "Sudan"
717: },
718: "phoneCode": "249"
719: },
720: {
721: "code": "ET",
722: "name": {
723: "en": "Ethiopia",
724: "fa": "اتیوپی",
725: "de": "Äthiopien"
726: },
727: "phoneCode": "251"
728: },
729: {
730: "code": "GH",
731: "name": {
732: "en": "Ghana",
733: "fa": "غنا",
734: "de": "Ghana"
735: },
736: "phoneCode": "233"
737: },
738: {
739: "code": "UG",
740: "name": {
741: "en": "Uganda",
742: "fa": "اوگاندا",
743: "de": "Uganda"
744: },
745: "phoneCode": "256"
746: },
747: {
748: "code": "TZ",
749: "name": {
750: "en": "Tanzania",
751: "fa": "تانزانیا",
752: "de": "Tansania"
753: },
754: "phoneCode": "255"
755: },
756: {
757: "code": "ZW",
758: "name": {
759: "en": "Zimbabwe",
760: "fa": "زیمبابوه",
761: "de": "Simbabwe"
762: },
763: "phoneCode": "263"
764: },
765: {
766: "code": "BW",
767: "name": {
768: "en": "Botswana",
769: "fa": "بوتسوانا",
770: "de": "Botswana"
771: },
772: "phoneCode": "267"
773: },
774: {
775: "code": "NA",
776: "name": {
777: "en": "Namibia",
778: "fa": "نامیبیا",
779: "de": "Namibia"
780: },
781: "phoneCode": "264"
782: },
783: {
784: "code": "ZM",
785: "name": {
786: "en": "Zambia",
787: "fa": "زامبیا",
788: "de": "Sambia"
789: },
790: "phoneCode": "260"
791: },
792: {
793: "code": "MW",
794: "name": {
795: "en": "Malawi",
796: "fa": "مالاوی",
797: "de": "Malawi"
798: },
799: "phoneCode": "265"
800: },
801: {
802: "code": "MZ",
803: "name": {
804: "en": "Mozambique",
805: "fa": "موزامبیک",
806: "de": "Mosambik"
807: },
808: "phoneCode": "258"
809: },
810: {
811: "code": "MG",
812: "name": {
813: "en": "Madagascar",
814: "fa": "ماداگاسکار",
815: "de": "Madagaskar"
816: },
817: "phoneCode": "261"
818: },
819: {
820: "code": "MU",
821: "name": {
822: "en": "Mauritius",
823: "fa": "موریس",
824: "de": "Mauritius"
825: },
826: "phoneCode": "230"
827: },
828: {
829: "code": "SC",
830: "name": {
831: "en": "Seychelles",
832: "fa": "سیشل",
833: "de": "Seychellen"
834: },
835: "phoneCode": "248"
836: },
837: {
838: "code": "RE",
839: "name": {
840: "en": "Réunion",
841: "fa": "رئونیون",
842: "de": "Réunion"
843: },
844: "phoneCode": "262"
845: },
846: {
847: "code": "YT",
848: "name": {
849: "en": "Mayotte",
850: "fa": "مایوت",
851: "de": "Mayotte"
852: },
853: "phoneCode": "262"
854: },
855: {
856: "code": "KM",
857: "name": {
858: "en": "Comoros",
859: "fa": "کومور",
860: "de": "Komoren"
861: },
862: "phoneCode": "269"
863: },
864: {
865: "code": "DJ",
866: "name": {
867: "en": "Djibouti",
868: "fa": "جیبوتی",
869: "de": "Dschibuti"
870: },
871: "phoneCode": "253"
872: },
873: {
874: "code": "SO",
875: "name": {
876: "en": "Somalia",
877: "fa": "سومالی",
878: "de": "Somalia"
879: },
880: "phoneCode": "252"
881: },
882: {
883: "code": "ER",
884: "name": {
885: "en": "Eritrea",
886: "fa": "اریتره",
887: "de": "Eritrea"
888: },
889: "phoneCode": "291"
890: },
891: {
892: "code": "SS",
893: "name": {
894: "en": "South Sudan",
895: "fa": "سودان جنوبی",
896: "de": "Südsudan"
897: },
898: "phoneCode": "211"
899: },
900: {
901: "code": "CF",
902: "name": {
903: "en": "Central African Republic",
904: "fa": "جمهوری آفریقای مرکزی",
905: "de": "Zentralafrikanische Republik"
906: },
907: "phoneCode": "236"
908: },
909: {
910: "code": "TD",
911: "name": {
912: "en": "Chad",
913: "fa": "چاد",
914: "de": "Tschad"
915: },
916: "phoneCode": "235"
917: },
918: {
919: "code": "NE",
920: "name": {
921: "en": "Niger",
922: "fa": "نیجر",
923: "de": "Niger"
924: },
925: "phoneCode": "227"
926: },
927: {
928: "code": "ML",
929: "name": {
930: "en": "Mali",
931: "fa": "مالی",
932: "de": "Mali"
933: },
934: "phoneCode": "223"
935: },
936: {
937: "code": "BF",
938: "name": {
939: "en": "Burkina Faso",
940: "fa": "بورکینافاسو",
941: "de": "Burkina Faso"
942: },
943: "phoneCode": "226"
944: },
945: {
946: "code": "CI",
947: "name": {
948: "en": "Côte d'Ivoire",
949: "fa": "ساحل عاج",
950: "de": "Elfenbeinküste"
951: },
952: "phoneCode": "225"
953: },
954: {
955: "code": "LR",
956: "name": {
957: "en": "Liberia",
958: "fa": "لیبریا",
959: "de": "Liberia"
960: },
961: "phoneCode": "231"
962: },
963: {
964: "code": "SL",
965: "name": {
966: "en": "Sierra Leone",
967: "fa": "سیرالئون",
968: "de": "Sierra Leone"
969: },
970: "phoneCode": "232"
971: },
972: {
973: "code": "GN",
974: "name": {
975: "en": "Guinea",
976: "fa": "گینه",
977: "de": "Guinea"
978: },
979: "phoneCode": "224"
980: },
981: {
982: "code": "GW",
983: "name": {
984: "en": "Guinea-Bissau",
985: "fa": "گینه بیسائو",
986: "de": "Guinea-Bissau"
987: },
988: "phoneCode": "245"
989: },
990: {
991: "code": "GM",
992: "name": {
993: "en": "Gambia",
994: "fa": "گامبیا",
995: "de": "Gambia"
996: },
997: "phoneCode": "220"
998: },
999: {
1000: "code": "SN",
1001: "name": {
1002: "en": "Senegal",
1003: "fa": "سنگال",
1004: "de": "Senegal"
1005: },
1006: "phoneCode": "221"
1007: },
1008: {
1009: "code": "MR",
1010: "name": {
1011: "en": "Mauritania",
1012: "fa": "موریتانی",
1013: "de": "Mauretanien"
1014: },
1015: "phoneCode": "222"
1016: },
1017: {
1018: "code": "CV",
1019: "name": {
1020: "en": "Cape Verde",
1021: "fa": "کیپورد",
1022: "de": "Kap Verde"
1023: },
1024: "phoneCode": "238"
1025: },
1026: {
1027: "code": "ST",
1028: "name": {
1029: "en": "São Tomé and Príncipe",
1030: "fa": "سائوتومه و پرنسیپ",
1031: "de": "São Tomé und Príncipe"
1032: },
1033: "phoneCode": "239"
1034: },
1035: {
1036: "code": "GQ",
1037: "name": {
1038: "en": "Equatorial Guinea",
1039: "fa": "گینه استوایی",
1040: "de": "Äquatorialguinea"
1041: },
1042: "phoneCode": "240"
1043: },
1044: {
1045: "code": "GA",
1046: "name": {
1047: "en": "Gabon",
1048: "fa": "گابن",
1049: "de": "Gabun"
1050: },
1051: "phoneCode": "241"
1052: },
1053: {
1054: "code": "CG",
1055: "name": {
1056: "en": "Republic of the Congo",
1057: "fa": "جمهوری کنگو",
1058: "de": "Republik Kongo"
1059: },
1060: "phoneCode": "242"
1061: },
1062: {
1063: "code": "CD",
1064: "name": {
1065: "en": "Democratic Republic of the Congo",
1066: "fa": "جمهوری دموکراتیک کنگو",
1067: "de": "Demokratische Republik Kongo"
1068: },
1069: "phoneCode": "243"
1070: },
1071: {
1072: "code": "AO",
1073: "name": {
1074: "en": "Angola",
1075: "fa": "آنگولا",
1076: "de": "Angola"
1077: },
1078: "phoneCode": "244"
1079: },
1080: {
1081: "code": "CM",
1082: "name": {
1083: "en": "Cameroon",
1084: "fa": "کامرون",
1085: "de": "Kamerun"
1086: },
1087: "phoneCode": "237"
1088: },
1089: {
1090: "code": "BI",
1091: "name": {
1092: "en": "Burundi",
1093: "fa": "بوروندی",
1094: "de": "Burundi"
1095: },
1096: "phoneCode": "257"
1097: },
1098: {
1099: "code": "RW",
1100: "name": {
1101: "en": "Rwanda",
1102: "fa": "رواندا",
1103: "de": "Ruanda"
1104: },
1105: "phoneCode": "250"
1106: },
1107: {
1108: "code": "LS",
1109: "name": {
1110: "en": "Lesotho",
1111: "fa": "لسوتو",
1112: "de": "Lesotho"
1113: },
1114: "phoneCode": "266"
1115: },
1116: {
1117: "code": "SZ",
1118: "name": {
1119: "en": "Eswatini",
1120: "fa": "اسواتینی",
1121: "de": "Eswatini"
1122: },
1123: "phoneCode": "268"
1124: },
1125: {
1126: "code": "GT",
1127: "name": {
1128: "en": "Guatemala",
1129: "fa": "گواتمالا",
1130: "de": "Guatemala"
1131: },
1132: "phoneCode": "502"
1133: },
1134: {
1135: "code": "HN",
1136: "name": {
1137: "en": "Honduras",
1138: "fa": "هندوراس",
1139: "de": "Honduras"
1140: },
1141: "phoneCode": "504"
1142: },
1143: {
1144: "code": "SV",
1145: "name": {
1146: "en": "El Salvador",
1147: "fa": "السالوادور",
1148: "de": "El Salvador"
1149: },
1150: "phoneCode": "503"
1151: },
1152: {
1153: "code": "NI",
1154: "name": {
1155: "en": "Nicaragua",
1156: "fa": "نیکاراگوئه",
1157: "de": "Nicaragua"
1158: },
1159: "phoneCode": "505"
1160: },
1161: {
1162: "code": "CR",
1163: "name": {
1164: "en": "Costa Rica",
1165: "fa": "کاستاریکا",
1166: "de": "Costa Rica"
1167: },
1168: "phoneCode": "506"
1169: },
1170: {
1171: "code": "PA",
1172: "name": {
1173: "en": "Panama",
1174: "fa": "پاناما",
1175: "de": "Panama"
1176: },
1177: "phoneCode": "507"
1178: },
1179: {
1180: "code": "BZ",
1181: "name": {
1182: "en": "Belize",
1183: "fa": "بلیز",
1184: "de": "Belize"
1185: },
1186: "phoneCode": "501"
1187: },
1188: {
1189: "code": "CU",
1190: "name": {
1191: "en": "Cuba",
1192: "fa": "کوبا",
1193: "de": "Kuba"
1194: },
1195: "phoneCode": "53"
1196: },
1197: {
1198: "code": "JM",
1199: "name": {
1200: "en": "Jamaica",
1201: "fa": "جامائیکا",
1202: "de": "Jamaika"
1203: },
1204: "phoneCode": "1"
1205: },
1206: {
1207: "code": "DO",
1208: "name": {
1209: "en": "Dominican Republic",
1210: "fa": "جمهوری دومینیکن",
1211: "de": "Dominikanische Republik"
1212: },
1213: "phoneCode": "1"
1214: },
1215: {
1216: "code": "HT",
1217: "name": {
1218: "en": "Haiti",
1219: "fa": "هائیتی",
1220: "de": "Haiti"
1221: },
1222: "phoneCode": "509"
1223: },
1224: {
1225: "code": "BS",
1226: "name": {
1227: "en": "Bahamas",
1228: "fa": "باهاما",
1229: "de": "Bahamas"
1230: },
1231: "phoneCode": "1"
1232: },
1233: {
1234: "code": "TT",
1235: "name": {
1236: "en": "Trinidad and Tobago",
1237: "fa": "ترینیداد و توباگو",
1238: "de": "Trinidad und Tobago"
1239: },
1240: "phoneCode": "1"
1241: },
1242: {
1243: "code": "BB",
1244: "name": {
1245: "en": "Barbados",
1246: "fa": "باربادوس",
1247: "de": "Barbados"
1248: },
1249: "phoneCode": "1"
1250: },
1251: {
1252: "code": "GD",
1253: "name": {
1254: "en": "Grenada",
1255: "fa": "گرنادا",
1256: "de": "Grenada"
1257: },
1258: "phoneCode": "1"
1259: },
1260: {
1261: "code": "LC",
1262: "name": {
1263: "en": "Saint Lucia",
1264: "fa": "سنت لوسیا",
1265: "de": "St. Lucia"
1266: },
1267: "phoneCode": "1"
1268: },
1269: {
1270: "code": "VC",
1271: "name": {
1272: "en": "Saint Vincent and the Grenadines",
1273: "fa": "سنت وینسنت و گرنادینها",
1274: "de": "St. Vincent und die Grenadinen"
1275: },
1276: "phoneCode": "1"
1277: },
1278: {
1279: "code": "AG",
1280: "name": {
1281: "en": "Antigua and Barbuda",
1282: "fa": "آنتیگوا و باربودا",
1283: "de": "Antigua und Barbuda"
1284: },
1285: "phoneCode": "1"
1286: },
1287: {
1288: "code": "DM",
1289: "name": {
1290: "en": "Dominica",
1291: "fa": "دومینیکا",
1292: "de": "Dominica"
1293: },
1294: "phoneCode": "1"
1295: },
1296: {
1297: "code": "KN",
1298: "name": {
1299: "en": "Saint Kitts and Nevis",
1300: "fa": "سنت کیتس و نویس",
1301: "de": "St. Kitts und Nevis"
1302: },
1303: "phoneCode": "1"
1304: },
1305: {
1306: "code": "FJ",
1307: "name": {
1308: "en": "Fiji",
1309: "fa": "فیجی",
1310: "de": "Fidschi"
1311: },
1312: "phoneCode": "679"
1313: },
1314: {
1315: "code": "PG",
1316: "name": {
1317: "en": "Papua New Guinea",
1318: "fa": "پاپوآ گینه نو",
1319: "de": "Papua-Neuguinea"
1320: },
1321: "phoneCode": "675"
1322: },
1323: {
1324: "code": "WS",
1325: "name": {
1326: "en": "Samoa",
1327: "fa": "ساموآ",
1328: "de": "Samoa"
1329: },
1330: "phoneCode": "685"
1331: },
1332: {
1333: "code": "TO",
1334: "name": {
1335: "en": "Tonga",
1336: "fa": "تونگا",
1337: "de": "Tonga"
1338: },
1339: "phoneCode": "676"
1340: },
1341: {
1342: "code": "VU",
1343: "name": {
1344: "en": "Vanuatu",
1345: "fa": "وانواتو",
1346: "de": "Vanuatu"
1347: },
1348: "phoneCode": "678"
1349: },
1350: {
1351: "code": "SB",
1352: "name": {
1353: "en": "Solomon Islands",
1354: "fa": "جزایر سلیمان",
1355: "de": "Salomonen"
1356: },
1357: "phoneCode": "677"
1358: },
1359: {
1360: "code": "KI",
1361: "name": {
1362: "en": "Kiribati",
1363: "fa": "کیریباتی",
1364: "de": "Kiribati"
1365: },
1366: "phoneCode": "686"
1367: },
1368: {
1369: "code": "FM",
1370: "name": {
1371: "en": "Micronesia",
1372: "fa": "میکرونزی",
1373: "de": "Mikronesien"
1374: },
1375: "phoneCode": "691"
1376: },
1377: {
1378: "code": "MH",
1379: "name": {
1380: "en": "Marshall Islands",
1381: "fa": "جزایر مارشال",
1382: "de": "Marshallinseln"
1383: },
1384: "phoneCode": "692"
1385: },
1386: {
1387: "code": "PW",
1388: "name": {
1389: "en": "Palau",
1390: "fa": "پالائو",
1391: "de": "Palau"
1392: },
1393: "phoneCode": "680"
1394: },
1395: {
1396: "code": "NR",
1397: "name": {
1398: "en": "Nauru",
1399: "fa": "نائورو",
1400: "de": "Nauru"
1401: },
1402: "phoneCode": "674"
1403: },
1404: {
1405: "code": "TV",
1406: "name": {
1407: "en": "Tuvalu",
1408: "fa": "تووالو",
1409: "de": "Tuvalu"
1410: },
1411: "phoneCode": "688"
1412: },
1413: {
1414: "code": "RS",
1415: "name": {
1416: "en": "Serbia",
1417: "fa": "صربستان",
1418: "de": "Serbien"
1419: },
1420: "phoneCode": "381"
1421: },
1422: {
1423: "code": "HR",
1424: "name": {
1425: "en": "Croatia",
1426: "fa": "کرواسی",
1427: "de": "Kroatien"
1428: },
1429: "phoneCode": "385"
1430: },
1431: {
1432: "code": "BA",
1433: "name": {
1434: "en": "Bosnia and Herzegovina",
1435: "fa": "بوسنی و هرزگوین",
1436: "de": "Bosnien und Herzegowina"
1437: },
1438: "phoneCode": "387"
1439: },
1440: {
1441: "code": "SI",
1442: "name": {
1443: "en": "Slovenia",
1444: "fa": "اسلوونی",
1445: "de": "Slowenien"
1446: },
1447: "phoneCode": "386"
1448: },
1449: {
1450: "code": "SK",
1451: "name": {
1452: "en": "Slovakia",
1453: "fa": "اسلواکی",
1454: "de": "Slowakei"
1455: },
1456: "phoneCode": "421"
1457: },
1458: {
1459: "code": "AL",
1460: "name": {
1461: "en": "Albania",
1462: "fa": "آلبانی",
1463: "de": "Albanien"
1464: },
1465: "phoneCode": "355"
1466: },
1467: {
1468: "code": "MK",
1469: "name": {
1470: "en": "North Macedonia",
1471: "fa": "مقدونیه شمالی",
1472: "de": "Nordmazedonien"
1473: },
1474: "phoneCode": "389"
1475: },
1476: {
1477: "code": "ME",
1478: "name": {
1479: "en": "Montenegro",
1480: "fa": "مونتهنگرو",
1481: "de": "Montenegro"
1482: },
1483: "phoneCode": "382"
1484: },
1485: {
1486: "code": "XK",
1487: "name": {
1488: "en": "Kosovo",
1489: "fa": "کوزوو",
1490: "de": "Kosovo"
1491: },
1492: "phoneCode": "383"
1493: },
1494: {
1495: "code": "EE",
1496: "name": {
1497: "en": "Estonia",
1498: "fa": "استونی",
1499: "de": "Estland"
1500: },
1501: "phoneCode": "372"
1502: },
1503: {
1504: "code": "LV",
1505: "name": {
1506: "en": "Latvia",
1507: "fa": "لتونی",
1508: "de": "Lettland"
1509: },
1510: "phoneCode": "371"
1511: },
1512: {
1513: "code": "LT",
1514: "name": {
1515: "en": "Lithuania",
1516: "fa": "لیتوانی",
1517: "de": "Litauen"
1518: },
1519: "phoneCode": "370"
1520: },
1521: {
1522: "code": "GE",
1523: "name": {
1524: "en": "Georgia",
1525: "fa": "گرجستان",
1526: "de": "Georgien"
1527: },
1528: "phoneCode": "995"
1529: },
1530: {
1531: "code": "AM",
1532: "name": {
1533: "en": "Armenia",
1534: "fa": "ارمنستان",
1535: "de": "Armenien"
1536: },
1537: "phoneCode": "374"
1538: },
1539: {
1540: "code": "AZ",
1541: "name": {
1542: "en": "Azerbaijan",
1543: "fa": "آذربایجان",
1544: "de": "Aserbaidschan"
1545: },
1546: "phoneCode": "994"
1547: },
1548: {
1549: "code": "YE",
1550: "name": {
1551: "en": "Yemen",
1552: "fa": "یمن",
1553: "de": "Jemen"
1554: },
1555: "phoneCode": "967"
1556: },
1557: {
1558: "code": "OM",
1559: "name": {
1560: "en": "Oman",
1561: "fa": "عمان",
1562: "de": "Oman"
1563: },
1564: "phoneCode": "968"
1565: },
1566: {
1567: "code": "QA",
1568: "name": {
1569: "en": "Qatar",
1570: "fa": "قطر",
1571: "de": "Katar"
1572: },
1573: "phoneCode": "974"
1574: },
1575: {
1576: "code": "KW",
1577: "name": {
1578: "en": "Kuwait",
1579: "fa": "کویت",
1580: "de": "Kuwait"
1581: },
1582: "phoneCode": "965"
1583: },
1584: {
1585: "code": "BH",
1586: "name": {
1587: "en": "Bahrain",
1588: "fa": "بحرین",
1589: "de": "Bahrain"
1590: },
1591: "phoneCode": "973"
1592: },
1593: {
1594: "code": "JO",
1595: "name": {
1596: "en": "Jordan",
1597: "fa": "اردن",
1598: "de": "Jordanien"
1599: },
1600: "phoneCode": "962"
1601: },
1602: {
1603: "code": "LB",
1604: "name": {
1605: "en": "Lebanon",
1606: "fa": "لبنان",
1607: "de": "Libanon"
1608: },
1609: "phoneCode": "961"
1610: },
1611: {
1612: "code": "SY",
1613: "name": {
1614: "en": "Syria",
1615: "fa": "سوریه",
1616: "de": "Syrien"
1617: },
1618: "phoneCode": "963"
1619: },
1620: {
1621: "code": "PS",
1622: "name": {
1623: "en": "Palestine",
1624: "fa": "فلسطین",
1625: "de": "Palästina"
1626: },
1627: "phoneCode": "970"
1628: },
1629: {
1630: "code": "IL",
1631: "name": {
1632: "en": "Israel",
1633: "fa": "اسرائیل",
1634: "de": "Israel"
1635: },
1636: "phoneCode": "972"
1637: },
1638: {
1639: "code": "CY",
1640: "name": {
1641: "en": "Cyprus",
1642: "fa": "قبرس",
1643: "de": "Zypern"
1644: },
1645: "phoneCode": "357"
1646: },
1647: {
1648: "code": "IS",
1649: "name": {
1650: "en": "Iceland",
1651: "fa": "ایسلند",
1652: "de": "Island"
1653: },
1654: "phoneCode": "354"
1655: },
1656: {
1657: "code": "LU",
1658: "name": {
1659: "en": "Luxembourg",
1660: "fa": "لوکزامبورگ",
1661: "de": "Luxemburg"
1662: },
1663: "phoneCode": "352"
1664: },
1665: {
1666: "code": "MT",
1667: "name": {
1668: "en": "Malta",
1669: "fa": "مالت",
1670: "de": "Malta"
1671: },
1672: "phoneCode": "356"
1673: },
1674: {
1675: "code": "MC",
1676: "name": {
1677: "en": "Monaco",
1678: "fa": "موناکو",
1679: "de": "Monaco"
1680: },
1681: "phoneCode": "377"
1682: },
1683: {
1684: "code": "SM",
1685: "name": {
1686: "en": "San Marino",
1687: "fa": "سان مارینو",
1688: "de": "San Marino"
1689: },
1690: "phoneCode": "378"
1691: },
1692: {
1693: "code": "VA",
1694: "name": {
1695: "en": "Vatican City",
1696: "fa": "واتیکان",
1697: "de": "Vatikanstadt"
1698: },
1699: "phoneCode": "379"
1700: },
1701: {
1702: "code": "AD",
1703: "name": {
1704: "en": "Andorra",
1705: "fa": "آندورا",
1706: "de": "Andorra"
1707: },
1708: "phoneCode": "376"
1709: },
1710: {
1711: "code": "LI",
1712: "name": {
1713: "en": "Liechtenstein",
1714: "fa": "لیختناشتاین",
1715: "de": "Liechtenstein"
1716: },
1717: "phoneCode": "423"
1718: },
1719: {
1720: "code": "MN",
1721: "name": {
1722: "en": "Mongolia",
1723: "fa": "مغولستان",
1724: "de": "Mongolei"
1725: },
1726: "phoneCode": "976"
1727: },
1728: {
1729: "code": "KP",
1730: "name": {
1731: "en": "North Korea",
1732: "fa": "کره شمالی",
1733: "de": "Nordkorea"
1734: },
1735: "phoneCode": "850"
1736: },
1737: {
1738: "code": "MM",
1739: "name": {
1740: "en": "Myanmar",
1741: "fa": "میانمار",
1742: "de": "Myanmar"
1743: },
1744: "phoneCode": "95"
1745: },
1746: {
1747: "code": "KH",
1748: "name": {
1749: "en": "Cambodia",
1750: "fa": "کامبوج",
1751: "de": "Kambodscha"
1752: },
1753: "phoneCode": "855"
1754: },
1755: {
1756: "code": "LA",
1757: "name": {
1758: "en": "Laos",
1759: "fa": "لائوس",
1760: "de": "Laos"
1761: },
1762: "phoneCode": "856"
1763: },
1764: {
1765: "code": "BN",
1766: "name": {
1767: "en": "Brunei",
1768: "fa": "برونئی",
1769: "de": "Brunei"
1770: },
1771: "phoneCode": "673"
1772: },
1773: {
1774: "code": "TL",
1775: "name": {
1776: "en": "Timor-Leste",
1777: "fa": "تیمور شرقی",
1778: "de": "Osttimor"
1779: },
1780: "phoneCode": "670"
1781: },
1782: {
1783: "code": "TG",
1784: "name": {
1785: "en": "Togo",
1786: "fa": "توگو",
1787: "de": "Togo"
1788: },
1789: "phoneCode": "228"
1790: },
1791: {
1792: "code": "BJ",
1793: "name": {
1794: "en": "Benin",
1795: "fa": "بنین",
1796: "de": "Benin"
1797: },
1798: "phoneCode": "229"
1799: }
1800: ]
1: import 'dotenv/config';
2: import { seedCountries } from './country.seeder';
3: import { seedAddressPredefined } from '@/server/database/seeders/address-predefined.seeder';
4: export const seeders = {
5: countries: seedCountries,
6: addressPredefined: seedAddressPredefined,
7: } satisfies Record Promise>;
8: type SeederName = keyof typeof seeders;
9: async function run(names: SeederName[]) {
10: for (const name of names) {
11: console.log(`\n▶ Running seeder: ${name}`);
12: await seeders[name]();
13: }
14: }
15: async function main() {
16: const seederArg = process.argv.find((arg) => arg.startsWith('--seeder='));
17: if (seederArg) {
18: const requested = seederArg.replace('--seeder=', '').split(',') as SeederName[];
19: for (const name of requested) {
20: if (!(name in seeders)) {
21: throw new Error(
22: `Unknown seeder "${name}". Available: ${Object.keys(seeders).join(', ')}`
23: );
24: }
25: }
26: await run(requested);
27: } else {
28: await run(Object.keys(seeders) as SeederName[]);
29: }
30: process.exit(0);
31: }
32: main().catch((err) => {
33: console.error(err);
34: process.exit(1);
35: });
1: import { z } from 'zod';
2: export const LocalizedLabelSchema = z.record(z.string(), z.string());
1: import 'dotenv/config';
2: import { is, sql } from 'drizzle-orm';
3: import { PgTable, getTableConfig } from 'drizzle-orm/pg-core';
4: import { db } from '@/server/database';
5: import * as schema from '@/server/database/schemas';
6: async function truncateAll() {
7: const tables = Object.values(schema).filter((value) => is(value, PgTable)) as unknown as PgTable[];
8: if (tables.length === 0) {
9: console.log('No tables found to truncate.');
10: return;
11: }
12: const tableNames = tables.map((t) => `"${getTableConfig(t).name}"`).join(', ');
13: await db.execute(sql.raw(`TRUNCATE TABLE ${tableNames} RESTART IDENTITY CASCADE`));
14: console.log(`Truncated: ${tableNames}`);
15: }
16: async function main() {
17: await truncateAll();
18: process.exit(0);
19: }
20: main().catch((err) => {
21: console.error(err);
22: process.exit(1);
23: });
1: import { drizzle } from 'drizzle-orm/node-postgres';
2: import { Pool } from 'pg';
3: import { relations } from '@/server/database/relations';
4: import {databaseConfig} from "@/config/database.config";
5: const pool = new Pool({
6: connectionString: databaseConfig.url,
7: options: `-c timezone=${databaseConfig.timezone}`,
8: });
9: export const postgres = drizzle({
10: client: pool,
11: relations,
12: });
1: import Redis from "ioredis";
2: import { redisConfig } from "@/config";
3: export const redis = new Redis(redisConfig.url);
1: import { cookies } from 'next/headers';
2: import { verifyCredentials } from '@/server/services/auth/credentials.service';
3: import { createSession, getSession, destroySession, refreshSession } from '@/server/services/session/session.service';
4: import type { LoginInput } from '@/server/validators/auth.validator';
5: import { cookieName as LOCALE_COOKIE, isLocale, type Locale } from '@/lib/i18n/settings';
6: const SESSION_PREFIX = 'backoffice-session';
7: const SESSION_TTL_SECONDS = 60 * 60 * 24 * 7;
8: export type BackofficeSessionData = {
9: userId: string;
10: name: string;
11: email: string | null;
12: phone: string | null;
13: locale?: Locale;
14: };
15: export async function login(input: LoginInput): Promise<{ sessionId: string; user: BackofficeSessionData }> {
16: const user = await verifyCredentials(input);
17: const cookieStore = await cookies();
18: const cookieLocale = cookieStore.get(LOCALE_COOKIE)?.value;
19: const locale = isLocale(cookieLocale) ? cookieLocale : undefined;
20: const sessionData: BackofficeSessionData = {
21: userId: user.id,
22: name: user.name,
23: email: user.email,
24: phone: user.phone,
25: locale,
26: };
27: const sessionId = await createSession(SESSION_PREFIX, sessionData, SESSION_TTL_SECONDS);
28: return { sessionId, user: sessionData };
29: }
30: export async function getCurrentSession(sessionId: string | undefined | null): Promise {
31: return getSession(SESSION_PREFIX, sessionId);
32: }
33: export async function logout(sessionId: string | undefined | null): Promise {
34: return destroySession(SESSION_PREFIX, sessionId);
35: }
36: export async function refreshCurrentSession(sessionId: string): Promise {
37: return refreshSession(SESSION_PREFIX, sessionId, SESSION_TTL_SECONDS);
38: }
1: export const BACKOFFICE_SESSION_COOKIE = 'backoffice_sid';
1: import bcrypt from 'bcrypt';
2: import { eq, or } from 'drizzle-orm';
3: import { db } from '@/server/database';
4: import { users, type User } from '@/server/database/schemas/user.schema';
5: import { loginSchema, type LoginInput } from '@/server/validators/auth.validator';
6: export class AuthError extends Error {}
7: export async function verifyCredentials(input: LoginInput): Promise {
8: const parsed = loginSchema.parse(input);
9: const conditions = [];
10: if (parsed.email) conditions.push(eq(users.email, parsed.email));
11: if (parsed.phone) conditions.push(eq(users.phone, parsed.phone));
12: const [user]: User[] = await db
13: .select()
14: .from(users)
15: .where(or(...conditions))
16: .limit(1);
17: if (!user || !user.password) {
18: throw new AuthError('invalid_credentials');
19: }
20: const passwordMatches = await bcrypt.compare(parsed.password, user.password);
21: if (!passwordMatches) {
22: throw new AuthError('invalid_credentials');
23: }
24: if (parsed.email && !user.emailVerifiedAt) {
25: throw new AuthError('email_not_verified');
26: }
27: if (parsed.phone && !user.phoneVerifiedAt) {
28: throw new AuthError('phone_not_verified');
29: }
30: return user;
31: }
1: import { randomBytes } from 'crypto';
2: import { redis } from '@/server/infra/redis';
3: const DEFAULT_TTL_SECONDS = 60 * 60 * 24 * 7;
4: function buildKey(prefix: string, sessionId: string) {
5: return `${prefix}:${sessionId}`;
6: }
7: export function generateSessionId(): string {
8: return randomBytes(32).toString('hex');
9: }
10: export async function createSession(
11: prefix: string,
12: data: T,
13: ttlSeconds: number = DEFAULT_TTL_SECONDS
14: ): Promise {
15: const sessionId = generateSessionId();
16: await redis.set(buildKey(prefix, sessionId), JSON.stringify(data), 'EX', ttlSeconds);
17: return sessionId;
18: }
19: export async function getSession(prefix: string, sessionId: string | undefined | null): Promise {
20: if (!sessionId) return null;
21: const raw = await redis.get(buildKey(prefix, sessionId));
22: if (!raw) return null;
23: return JSON.parse(raw) as T;
24: }
25: export async function destroySession(prefix: string, sessionId: string | undefined | null): Promise {
26: if (!sessionId) return;
27: await redis.del(buildKey(prefix, sessionId));
28: }
29: export async function refreshSession(
30: prefix: string,
31: sessionId: string,
32: ttlSeconds: number = DEFAULT_TTL_SECONDS
33: ): Promise {
34: await redis.expire(buildKey(prefix, sessionId), ttlSeconds);
35: }
36: export async function updateSession(
37: prefix: string,
38: sessionId: string | undefined | null,
39: patch: Partial
40: ): Promise {
41: if (!sessionId) return null;
42: const key = buildKey(prefix, sessionId);
43: const raw = await redis.get(key);
44: if (!raw) return null;
45: const current = JSON.parse(raw) as T;
46: const updated = { ...current, ...patch };
47: const ttl = await redis.ttl(key);
48: await redis.set(key, JSON.stringify(updated), 'EX', ttl > 0 ? ttl : DEFAULT_TTL_SECONDS);
49: return updated;
50: }
1: import { promises as fs } from 'fs';
2: import path from 'path';
3: import { TranslationTree } from './types';
4: const LOCALES_DIR = path.join(process.cwd(), 'locales');
5: const cache = new Map();
6: export async function loadTranslations(locale: string): Promise {
7: if (cache.has(locale)) return cache.get(locale)!;
8: const filePath = path.join(LOCALES_DIR, `${locale}.json`);
9: const raw = await fs.readFile(filePath, 'utf-8');
10: const json: TranslationTree = JSON.parse(raw);
11: cache.set(locale, json);
12: return json;
13: }
14: export function invalidateCache(locale: string) {
15: cache.delete(locale);
16: }
1: export type TranslationTree = { [key: string]: string | TranslationTree };
1: import { watch } from 'fs';
2: import path from 'path';
3: import { invalidateCache } from './load';
4: const LOCALES_DIR = path.join(process.cwd(), 'locales');
5: export function startTranslationWatcher() {
6: watch(LOCALES_DIR, (event, filename) => {
7: if (!filename || !filename.endsWith('.json')) return;
8: const locale = filename.replace('.json', '');
9: invalidateCache(locale);
10: });
11: }
1: export class UploadNotFoundError extends Error {
2: constructor(uploadId: string) {
3: super(`Upload not found: ${uploadId}`);
4: this.name = "UploadNotFoundError";
5: }
6: }
7: export class UploadReferencedError extends Error {
8: constructor(uploadId: string) {
9: super(`Upload ${uploadId} is still referenced elsewhere and cannot be hard-deleted`);
10: this.name = "UploadReferencedError";
11: }
12: }
13: export class UploadStorageError extends Error {
14: constructor(message: string, public readonly cause?: unknown) {
15: super(message);
16: this.name = "UploadStorageError";
17: }
18: }
1: import { createHash } from "node:crypto";
2: import path from "node:path";
3: const MIME_EXTENSION_MAP: Record = {
4: "image/jpeg": ".jpg",
5: "image/png": ".png",
6: "image/webp": ".webp",
7: "image/gif": ".gif",
8: "image/svg+xml": ".svg",
9: "application/pdf": ".pdf",
10: "application/zip": ".zip",
11: "text/plain": ".txt",
12: "text/csv": ".csv",
13: "application/json": ".json",
14: };
15: export function resolveExtension(originalName: string, mimeType: string): string {
16: const fromName = path.extname(originalName);
17: if (fromName) return fromName.toLowerCase();
18: return MIME_EXTENSION_MAP[mimeType] ?? "";
19: }
20: export function computeChecksum(buffer: Buffer): string {
21: return createHash("sha256").update(buffer).digest("hex");
22: }
23: export function buildStorageKey(uploadId: string, extension: string): string {
24: return `${uploadId}${extension}`;
25: }
1: import { eq } from "drizzle-orm";
2: import {
3: DeleteObjectCommand,
4: GetObjectCommand,
5: PutObjectCommand,
6: } from "@aws-sdk/client-s3";
7: import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
8: import { db } from "@/server/database";
9: import { uploads, type Upload } from "@/server/database/schemas/upload.schema";
10: import { s3Client } from "@/lib/s3-client";
11: import { storageConfig } from "@/config/storage.config";
12: import {
13: UploadNotFoundError,
14: UploadReferencedError,
15: UploadStorageError,
16: } from "./upload.errors";
17: import {
18: buildStorageKey,
19: computeChecksum,
20: resolveExtension,
21: } from "./upload.helpers";
22: import type { CreateUploadInput, GetUploadUrlOptions } from "./upload.types";
23: const DEFAULT_URL_EXPIRY_SECONDS = 15 * 60;
24: const PG_FOREIGN_KEY_VIOLATION = "23503";
25: export class UploadService {
26: async create(input: CreateUploadInput): Promise {
27: const bucket = input.bucket ?? storageConfig.defaultBucket;
28: const extension = resolveExtension(input.originalName, input.mimeType);
29: const checksum = computeChecksum(input.file);
30: const [pending] = await db
31: .insert(uploads)
32: .values({
33: bucket,
34: storageKey: "", // filled in once we know the generated id
35: checksum,
36: originalName: input.originalName,
37: mimeType: input.mimeType,
38: sizeBytes: input.file.byteLength,
39: status: "pending",
40: uploadedBy: input.uploadedBy,
41: })
42: .returning();
43: const storageKey = buildStorageKey(pending.id, extension);
44: try {
45: await s3Client.send(
46: new PutObjectCommand({
47: Bucket: bucket,
48: Key: storageKey,
49: Body: input.file,
50: ContentType: input.mimeType,
51: })
52: );
53: } catch (err) {
54: await db
55: .update(uploads)
56: .set({ status: "failed" })
57: .where(eq(uploads.id, pending.id));
58: throw new UploadStorageError(
59: `Failed to upload object for upload ${pending.id}`,
60: err
61: );
62: }
63: const [completed] = await db
64: .update(uploads)
65: .set({ storageKey, status: "completed" })
66: .where(eq(uploads.id, pending.id))
67: .returning();
68: return completed;
69: }
70: async rename(uploadId: string, newOriginalName: string): Promise {
71: const [updated] = await db
72: .update(uploads)
73: .set({ originalName: newOriginalName })
74: .where(eq(uploads.id, uploadId))
75: .returning();
76: if (!updated) throw new UploadNotFoundError(uploadId);
77: return updated;
78: }
79: async softDelete(uploadId: string): Promise {
80: const [updated] = await db
81: .update(uploads)
82: .set({ deletedAt: new Date() })
83: .where(eq(uploads.id, uploadId))
84: .returning();
85: if (!updated) throw new UploadNotFoundError(uploadId);
86: return updated;
87: }
88: async restore(uploadId: string): Promise {
89: const [updated] = await db
90: .update(uploads)
91: .set({ deletedAt: null })
92: .where(eq(uploads.id, uploadId))
93: .returning();
94: if (!updated) throw new UploadNotFoundError(uploadId);
95: return updated;
96: }
97: async hardDelete(uploadId: string): Promise {
98: const upload = await this.getByIdOrThrow(uploadId);
99: try {
100: await db.delete(uploads).where(eq(uploads.id, uploadId));
101: } catch (err) {
102: if (isForeignKeyViolation(err)) {
103: throw new UploadReferencedError(uploadId);
104: }
105: throw err;
106: }
107: try {
108: await s3Client.send(
109: new DeleteObjectCommand({
110: Bucket: upload.bucket,
111: Key: upload.storageKey,
112: })
113: );
114: } catch (err) {
115: throw new UploadStorageError(
116: `DB row for upload ${uploadId} was deleted, but removing the object from storage failed`,
117: err
118: );
119: }
120: }
121: async getUrl(uploadId: string, options: GetUploadUrlOptions): Promise {
122: const upload = await this.getByIdOrThrow(uploadId);
123: const command = new GetObjectCommand({
124: Bucket: upload.bucket,
125: Key: upload.storageKey,
126: ResponseContentDisposition:
127: options.mode === "download"
128: ? `attachment; filename="${encodeURIComponent(upload.originalName)}"`
129: : "inline",
130: ResponseContentType: upload.mimeType,
131: });
132: return getSignedUrl(s3Client, command, {
133: expiresIn: options.expiresInSeconds ?? DEFAULT_URL_EXPIRY_SECONDS,
134: });
135: }
136: private async getByIdOrThrow(uploadId: string): Promise {
137: const upload = await db.query.uploads.findFirst({
138: where: { id: uploadId },
139: });
140: if (!upload) throw new UploadNotFoundError(uploadId);
141: return upload;
142: }
143: }
144: function isForeignKeyViolation(err: unknown): boolean {
145: return (
146: typeof err === "object" &&
147: err !== null &&
148: "code" in err &&
149: (err as { code: unknown }).code === PG_FOREIGN_KEY_VIOLATION
150: );
151: }
152: export const uploadService = new UploadService();
1: export interface CreateUploadInput {
2: file: Buffer;
3: originalName: string;
4: mimeType: string;
5: uploadedBy: string;
6: bucket?: string;
7: }
8: export interface GetUploadUrlOptions {
9: mode: "read" | "download";
10: expiresInSeconds?: number;
11: }
1: import { drizzle } from 'drizzle-orm/node-postgres';
2: import { migrate } from 'drizzle-orm/node-postgres/migrator';
3: import { Pool } from 'pg';
4: import { relations } from '@/server/database/relations';
5: import {databaseConfig} from "@/config";
6: const pool = new Pool({ connectionString: databaseConfig.testUrl });
7: export const testDb = drizzle({
8: client: pool,
9: relations,
10: });
11: export async function runMigrations() {
12: await migrate(testDb, { migrationsFolder: './drizzle/migrations' });
13: }
14: export async function closeTestDb() {
15: await pool.end();
16: }
1: import { runMigrations } from './db';
2: import 'dotenv/config';
3: export default async function setup() {
4: await runMigrations();
5: }
1: import { sql } from 'drizzle-orm';
2: import { testDb } from './db';
3: export async function resetDb() {
4: await testDb.execute(sql`TRUNCATE TABLE users RESTART IDENTITY CASCADE`);
5: }
1: import { z } from 'zod';
2: export const loginSchema = z
3: .object({
4: email: z.email().optional(),
5: phone: z.string().min(6).optional(),
6: password: z.string().min(1, 'password_is_required'),
7: })
8: .superRefine((data, ctx) => {
9: if (!data.email && !data.phone) {
10: ctx.addIssue({
11: code: 'custom',
12: message: 'email_or_phone_is_required',
13: path: ['email'],
14: });
15: ctx.addIssue({
16: code: 'custom',
17: message: 'email_or_phone_is_required',
18: path: ['phone'],
19: });
20: }
21: });
22: export type LoginInput = z.infer;