nlbone 0.6.19__py3-none-any.whl → 0.7.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. nlbone/adapters/db/postgres/__init__.py +1 -1
  2. nlbone/adapters/db/postgres/base.py +2 -1
  3. nlbone/adapters/db/postgres/query_builder.py +1 -1
  4. nlbone/adapters/db/postgres/repository.py +254 -29
  5. nlbone/adapters/db/postgres/uow.py +36 -1
  6. nlbone/adapters/messaging/__init__.py +1 -1
  7. nlbone/adapters/messaging/event_bus.py +97 -17
  8. nlbone/adapters/messaging/rabbitmq.py +45 -0
  9. nlbone/adapters/outbox/__init__.py +1 -0
  10. nlbone/adapters/outbox/outbox_consumer.py +112 -0
  11. nlbone/adapters/outbox/outbox_repo.py +191 -0
  12. nlbone/adapters/ticketing/client.py +39 -0
  13. nlbone/config/settings.py +14 -5
  14. nlbone/container.py +1 -8
  15. nlbone/core/application/bus.py +169 -0
  16. nlbone/core/application/di.py +128 -0
  17. nlbone/core/application/registry.py +129 -0
  18. nlbone/core/domain/base.py +30 -9
  19. nlbone/core/domain/models.py +46 -3
  20. nlbone/core/ports/__init__.py +0 -2
  21. nlbone/core/ports/event_bus.py +23 -6
  22. nlbone/core/ports/outbox.py +73 -0
  23. nlbone/core/ports/repository.py +116 -0
  24. nlbone/core/ports/uow.py +20 -1
  25. nlbone/interfaces/api/additional_filed/field_registry.py +2 -0
  26. nlbone/interfaces/cli/crypto.py +22 -0
  27. nlbone/interfaces/cli/init_db.py +39 -2
  28. nlbone/interfaces/cli/main.py +4 -0
  29. nlbone/interfaces/cli/ticket.py +29 -0
  30. nlbone/interfaces/jobs/dispatch_outbox.py +3 -2
  31. nlbone/utils/crypto.py +32 -0
  32. nlbone/utils/normalize_mobile.py +33 -0
  33. {nlbone-0.6.19.dist-info → nlbone-0.7.0.dist-info}/METADATA +4 -2
  34. {nlbone-0.6.19.dist-info → nlbone-0.7.0.dist-info}/RECORD +38 -31
  35. nlbone/adapters/repositories/outbox_repo.py +0 -20
  36. nlbone/core/application/command_bus.py +0 -25
  37. nlbone/core/application/events.py +0 -20
  38. nlbone/core/application/services.py +0 -0
  39. nlbone/core/domain/events.py +0 -0
  40. nlbone/core/ports/messaging.py +0 -0
  41. nlbone/core/ports/repo.py +0 -19
  42. /nlbone/adapters/{messaging/redis.py → ticketing/__init__.py} +0 -0
  43. {nlbone-0.6.19.dist-info → nlbone-0.7.0.dist-info}/WHEEL +0 -0
  44. {nlbone-0.6.19.dist-info → nlbone-0.7.0.dist-info}/entry_points.txt +0 -0
  45. {nlbone-0.6.19.dist-info → nlbone-0.7.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,3 +1,7 @@
1
+ import importlib
2
+ import sys
3
+ from pathlib import Path
4
+
1
5
  import typer
2
6
 
3
7
  from nlbone.adapters.db import Base, init_sync_engine, sync_ping
@@ -5,9 +9,42 @@ from nlbone.adapters.db import Base, init_sync_engine, sync_ping
5
9
  init_db_command = typer.Typer(help="Database utilities")
6
10
 
7
11
 
12
+ def _import_target(target: str):
13
+ """Import a module or call a bootstrap function if using 'module:function' syntax."""
14
+ if ":" in target:
15
+ mod_name, attr = target.split(":", 1)
16
+ mod = importlib.import_module(mod_name)
17
+ getattr(mod, attr)()
18
+ else:
19
+ importlib.import_module(target)
20
+
21
+
8
22
  @init_db_command.command("init")
9
- def init_db(drop: bool = typer.Option(False, "--drop", help="Drop all tables before create")):
10
- """Create (and optionally drop) DB schema."""
23
+ def init_db(
24
+ drop: bool = typer.Option(False, "--drop", help="Drop all tables before creating them"),
25
+ models: list[str] = typer.Option(
26
+ None,
27
+ "--models",
28
+ "-m",
29
+ help=(
30
+ "List of modules or bootstrap functions to import before create_all. "
31
+ "For example: app.models or app.bootstrap:register_models"
32
+ ),
33
+ ),
34
+ add_cwd: bool = typer.Option(
35
+ True,
36
+ "--add-cwd/--no-add-cwd",
37
+ help=("Add the current working directory to sys.path so imports work relative to the host project root."),
38
+ ),
39
+ ):
40
+ """Create (and optionally drop) the database schema."""
41
+
42
+ if add_cwd:
43
+ sys.path.insert(0, str(Path.cwd()))
44
+
45
+ for target in models or []:
46
+ _import_target(target)
47
+
11
48
  engine = init_sync_engine()
12
49
  if drop:
13
50
  Base.metadata.drop_all(bind=engine)
@@ -4,11 +4,15 @@ import typer
4
4
 
5
5
  from nlbone.adapters.db import init_sync_engine
6
6
  from nlbone.config.settings import get_settings
7
+ from nlbone.interfaces.cli.crypto import crypto_command
7
8
  from nlbone.interfaces.cli.init_db import init_db_command
9
+ from nlbone.interfaces.cli.ticket import app as ticket_command
8
10
 
9
11
  app = typer.Typer(help="NLBone CLI")
10
12
 
11
13
  app.add_typer(init_db_command, name="db")
14
+ app.add_typer(crypto_command, name="crypto")
15
+ app.add_typer(ticket_command, name="ticket")
12
16
 
13
17
 
14
18
  @app.callback()
@@ -0,0 +1,29 @@
1
+ import asyncio
2
+ import typer
3
+
4
+ from nlbone.adapters.ticketing.client import TicketingClient, CreateTicketIn
5
+
6
+ app = typer.Typer(add_completion=False)
7
+
8
+ @app.command("create")
9
+ def send_sample():
10
+ payload = CreateTicketIn(
11
+ assignee_id= "153",
12
+ category_id= 2,
13
+ channel= "site_chat",
14
+ direction= "incoming",
15
+ entity_id= "153",
16
+ entity_type= "user",
17
+ message= "سلام خوبی",
18
+ priority= "medium",
19
+ product_id= 0,
20
+ status= "open",
21
+ title= "پشتیبانی فنی (ثبت نام و لاگین)",
22
+ user_id= 153,
23
+ )
24
+ client = TicketingClient()
25
+ asyncio.run(client.create_ticket(payload, created_by_id=995836))
26
+ print("Ticket message published (or logged if Noop).")
27
+
28
+ if __name__ == "__main__":
29
+ app()
@@ -1,6 +1,7 @@
1
1
  from nlbone.adapters.messaging.internal_router import internal_router
2
2
  from nlbone.core.ports.event_bus import IntegrationPublisher
3
3
 
4
+
4
5
  def run_dispatch_outbox(outbox_repo, publisher: IntegrationPublisher):
5
6
  batch = outbox_repo.fetch_pending(limit=200)
6
7
  for rec in batch:
@@ -12,8 +13,8 @@ def run_dispatch_outbox(outbox_repo, publisher: IntegrationPublisher):
12
13
  else:
13
14
  publisher.publish(topic, payload)
14
15
  outbox_repo.mark_sent(rec["id"])
15
- except TemporaryError:
16
- outbox_repo.schedule_retry(rec["id"], rec["retries"])
16
+ # except TemporaryError:
17
+ # outbox_repo.schedule_retry(rec["id"], rec["retries"])
17
18
  except Exception:
18
19
  # mark_failed یا retry policy
19
20
  outbox_repo.schedule_retry(rec["id"], rec["retries"])
nlbone/utils/crypto.py ADDED
@@ -0,0 +1,32 @@
1
+ import base64
2
+ import hashlib
3
+ from functools import lru_cache
4
+
5
+ from cryptography.fernet import Fernet
6
+
7
+ from nlbone.config.settings import get_settings
8
+
9
+
10
+ def _get_fernet_key() -> bytes:
11
+ settings = get_settings()
12
+ fernet_key = settings.FERNET_KEY
13
+
14
+ if not fernet_key or not fernet_key.strip():
15
+ raise Exception("❌ FERNET_KEY is required in .env")
16
+
17
+ digest = hashlib.sha256(fernet_key.encode()).digest()
18
+
19
+ return base64.urlsafe_b64encode(digest)
20
+
21
+
22
+ @lru_cache(maxsize=1)
23
+ def get_fernet():
24
+ return Fernet(_get_fernet_key())
25
+
26
+
27
+ def encrypt_text(plaintext: str) -> str:
28
+ return get_fernet().encrypt(plaintext.encode()).decode()
29
+
30
+
31
+ def decrypt_text(token: str) -> str:
32
+ return get_fernet().decrypt(token.encode()).decode()
@@ -0,0 +1,33 @@
1
+ import re
2
+ from typing import List
3
+
4
+
5
+ def normalize_mobile(mobile, strip_zero=True, add_country_code=True):
6
+ if not mobile:
7
+ return ""
8
+
9
+ mobile = re.sub(r"\D", "", str(mobile))
10
+
11
+ if mobile.startswith("0098"):
12
+ mobile = mobile[4:]
13
+ elif mobile.startswith("98") and len(mobile) > 10:
14
+ mobile = mobile[2:]
15
+
16
+ if strip_zero and mobile.startswith("0"):
17
+ mobile = mobile[1:]
18
+
19
+ if add_country_code:
20
+ if not mobile.startswith("98"):
21
+ mobile = f"98{mobile}"
22
+
23
+ return mobile
24
+
25
+
26
+ def remove_duplicates(items: List[str]) -> List[str]:
27
+ seen = set()
28
+ out = []
29
+ for x in items:
30
+ if x and x not in seen:
31
+ seen.add(x)
32
+ out.append(x)
33
+ return out
@@ -1,13 +1,15 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nlbone
3
- Version: 0.6.19
3
+ Version: 0.7.0
4
4
  Summary: Backbone package for interfaces and infrastructure in Python projects
5
5
  Author-email: Amir Hosein Kahkbazzadeh <a.khakbazzadeh@gmail.com>
6
6
  License: MIT
7
7
  License-File: LICENSE
8
8
  Requires-Python: >=3.10
9
+ Requires-Dist: aio-pika>=9.5.7
9
10
  Requires-Dist: anyio>=4.0
10
11
  Requires-Dist: cachetools>=6.2.0
12
+ Requires-Dist: cryptography~=45.0.4
11
13
  Requires-Dist: dependency-injector>=4.48.1
12
14
  Requires-Dist: elasticsearch==8.14.0
13
15
  Requires-Dist: fastapi>=0.116
@@ -22,7 +24,7 @@ Requires-Dist: redis~=6.4.0
22
24
  Requires-Dist: sqlalchemy>=2.0
23
25
  Requires-Dist: starlette>=0.47
24
26
  Requires-Dist: typer>=0.17.4
25
- Requires-Dist: uvicorn>=0.35
27
+ Requires-Dist: uvicorn==0.35
26
28
  Description-Content-Type: text/markdown
27
29
 
28
30
  # nlbone
@@ -1,5 +1,5 @@
1
1
  nlbone/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- nlbone/container.py,sha256=rVYzH-jIM8iCcefDOo29mNjvFdf3nJ4EtPNUws9SDnA,3089
2
+ nlbone/container.py,sha256=I3Ev5L-CvfOquR4cyueIiplRriZ-_q_QlH_Xne9lA0k,2698
3
3
  nlbone/types.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  nlbone/adapters/__init__.py,sha256=NzUmk4XPyp3GJOw7VSE86xkQMZLtG3MrOoXLeoB551M,41
5
5
  nlbone/adapters/auth/__init__.py,sha256=hkDHvsFhw_UiOHG9ZSMqjiAhK4wumEforitveSZswVw,42
@@ -11,14 +11,14 @@ nlbone/adapters/cache/memory.py,sha256=y8M4erHQXApiSMAqG6Qk4pxEb60hRdu1szPv6iqvO
11
11
  nlbone/adapters/cache/pubsub_listener.py,sha256=3vfK4O4EzuQQhTsbZ_bweP06o99kDSyHJ5PrfUotUaE,1460
12
12
  nlbone/adapters/cache/redis.py,sha256=2Y1DYHBLCrbHTO6O7pw85u3qY6OnCIFTYJ-HBvBs0FM,4608
13
13
  nlbone/adapters/db/__init__.py,sha256=0CDSySEk4jJsqmwI0eNuaaLJOJDt8_iSiHBsFdC-L3s,212
14
- nlbone/adapters/db/postgres/__init__.py,sha256=6JYJH0xZs3aR-zuyMpRhsdzFugmqz8nprwTQLprqhZc,313
14
+ nlbone/adapters/db/postgres/__init__.py,sha256=tvCpHOdZbpQ57o7k-plq7L0e1uZe5_Frbh7I-LxW7zM,313
15
15
  nlbone/adapters/db/postgres/audit.py,sha256=IuWkPitr70UyQ6-GkAedckp8U-Z4cTgzFbdt_bQv1VQ,4800
16
- nlbone/adapters/db/postgres/base.py,sha256=kha9xmklzhuQAK8QEkNBn-mAHq8dUKbOM-3abaBpWmQ,71
16
+ nlbone/adapters/db/postgres/base.py,sha256=I89PsEeR9ADEScG8D5pVSncPrPRBmf-KQQkjajl7Koo,132
17
17
  nlbone/adapters/db/postgres/engine.py,sha256=UCegauVB1gvo42ThytYnn5VIcQBwR-5xhcXYFApRFNk,3448
18
- nlbone/adapters/db/postgres/query_builder.py,sha256=wtOIsUJ3iM5-vFxIUfbkM6I13WE4fSw8pJKdVi4jgXY,12544
19
- nlbone/adapters/db/postgres/repository.py,sha256=J_DBE73JhHPYCk90c5-O7lQtZbxDgqjjN9OcWy4Omvs,1660
18
+ nlbone/adapters/db/postgres/query_builder.py,sha256=Qv_2oZ5OxZwtN3Ts-jaAX_8sLBzb1mpGBhlNF7aR6Wk,12543
19
+ nlbone/adapters/db/postgres/repository.py,sha256=n01TAzdKd-UbOhirE6KMosuvRdJG2l1cszwVHjTM-Ks,10345
20
20
  nlbone/adapters/db/postgres/schema.py,sha256=NlE7Rr8uXypsw4oWkdZhZwcIBHQEPIpoHLxcUo98i6s,1039
21
- nlbone/adapters/db/postgres/uow.py,sha256=nRxNpY-WoWHpym-XeZ8VHm0MYvtB9wuopOeNdV_ebk8,2088
21
+ nlbone/adapters/db/postgres/uow.py,sha256=2vRp4RBkh9RVniEY6CMXNHt-XXK9W2CDNKR1upT5EJE,3788
22
22
  nlbone/adapters/db/redis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
23
  nlbone/adapters/db/redis/client.py,sha256=5SUnwP2-GrueSFimUbiqDvrQsumvIE2aeozk8l-vOfQ,466
24
24
  nlbone/adapters/http_clients/__init__.py,sha256=w-Yr9CLuXMU71N0Ada5HbvP1DB53wqeP6B-i5rALlTo,150
@@ -27,36 +27,39 @@ nlbone/adapters/http_clients/pricing/pricing_service.py,sha256=fYfMQh3qW_YDNkBW1
27
27
  nlbone/adapters/http_clients/uploadchi/__init__.py,sha256=uBzEOuVtY22teWW2b36Pitkdk5yVdSqa6xbg22JfTNg,105
28
28
  nlbone/adapters/http_clients/uploadchi/uploadchi.py,sha256=erpjOees25FW0nuK1PkYS-oU0h8MeRV9Rhs1cf3gaEs,4881
29
29
  nlbone/adapters/http_clients/uploadchi/uploadchi_async.py,sha256=PQbVNeaYde5CmgT3vcnQoI1PGeSs9AxHlPFuB8biOmU,4717
30
- nlbone/adapters/messaging/__init__.py,sha256=UDAwu3s-JQmOZjWz2Nu0SgHhnkbeOhKDH_zLD75oWMY,40
31
- nlbone/adapters/messaging/event_bus.py,sha256=w-NPwDiPMLFPU_enRQCtfQXOALsXfg31u57R8sG_-1U,781
32
- nlbone/adapters/messaging/redis.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
+ nlbone/adapters/messaging/__init__.py,sha256=o6ZiMihm_MhRXfcEpcjHBB3JGQovQbg3pxe0qS6516c,41
31
+ nlbone/adapters/messaging/event_bus.py,sha256=MSM70JPHoDK17efWlh20ATT1O0KW7xWnwZ5D-gI6U_w,3773
32
+ nlbone/adapters/messaging/rabbitmq.py,sha256=jO58NvsZnAEoS3nvsfdjQgqnzraD8f5Op3PqDAVt0RM,2007
33
+ nlbone/adapters/outbox/__init__.py,sha256=S_5t-rI0e3Gj_IegkuMnvwwqkU8BUqLBazJ-nWlFDAM,117
34
+ nlbone/adapters/outbox/outbox_consumer.py,sha256=Pjc8gAKapR-JznhgLXfsDrk5_W2e7QSCQbKlU2nDU4I,3114
35
+ nlbone/adapters/outbox/outbox_repo.py,sha256=X8YOhbpB8zgxlBw8Na1I9lEfhI4cEhsYZVb2oIiYlGo,6708
33
36
  nlbone/adapters/percolation/__init__.py,sha256=0h1Bw7FzxgkDIHxeoyQXSfegrhP6VbpYV4QC8njYdRE,38
34
37
  nlbone/adapters/percolation/connection.py,sha256=1iJISSwMEh4r_6nJI7mYf_v64Q0eeU1eSI0wLIfOK14,415
35
38
  nlbone/adapters/repositories/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
- nlbone/adapters/repositories/outbox_repo.py,sha256=UdvAsasMOMA7M6fV8nEnxh7HXUWg_32ITNTZLIrUXug,433
39
+ nlbone/adapters/ticketing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
+ nlbone/adapters/ticketing/client.py,sha256=V5_u7cxV67eAG4jj4vUD23VWGiMXIXSAU362pNS6hYU,1289
37
41
  nlbone/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
42
  nlbone/config/logging.py,sha256=Ot6Ctf7EQZlW8YNB-uBdleqI6wixn5fH0Eo6QRgNkQk,4358
39
- nlbone/config/settings.py,sha256=S4Uw7oOmTQSbSDvNBzrpq0arEdhCxF9aZE1Cit2UXmM,3951
43
+ nlbone/config/settings.py,sha256=Zld9ie7X1v2xPZzNVbsHV-EXo6RICf9GIABHwTKuivQ,4332
40
44
  nlbone/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
45
  nlbone/core/application/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
46
  nlbone/core/application/base_worker.py,sha256=5brIToSd-vi6tw0ukhHnUZGZhOLq1SQ-NRRy-kp6D24,1193
43
- nlbone/core/application/command_bus.py,sha256=MxjlV5vbhxADB0xtifhPpTAytmLZHjKvEnnaaVbG520,705
44
- nlbone/core/application/events.py,sha256=eQGLE0aZHuWJsy9J-qRse4CMXOtweH9-2rQ7AIPRMEQ,614
45
- nlbone/core/application/services.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
+ nlbone/core/application/bus.py,sha256=bi40pu_-6bBllRxqvBNpf7ByHXPsfrUacs-JxM0d18Q,6432
48
+ nlbone/core/application/di.py,sha256=gfxSawmT7jV6fnvOSgZrNt4yIPUg2FSQsT7euShg774,4117
49
+ nlbone/core/application/registry.py,sha256=dTqV_4bkMsLJ60CesZuEel5xO36cD1qikiaCLJXIGOw,4660
46
50
  nlbone/core/application/use_case.py,sha256=3GMQZ3CFK5cbLoBNBgohPft6GBq2j9_wr8iKRq_osQA,247
47
51
  nlbone/core/application/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
52
  nlbone/core/domain/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
- nlbone/core/domain/base.py,sha256=5oUfbpaI8juJ28Api8J9IXOSm55VI2bp4QNhA0U8h2Y,1251
50
- nlbone/core/domain/events.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
- nlbone/core/domain/models.py,sha256=Zn_rwtlzfjOEJZo6HS9M8UsMk-HpMJrHAKn05UA-u2k,1461
52
- nlbone/core/ports/__init__.py,sha256=gx-Ubj7h-1vvnu56sNnRqmer7HHfW3rX2WLl-0AX5U0,214
53
+ nlbone/core/domain/base.py,sha256=6C_wsn4CfFlW7n6ACsyA4r-ZciF4xUv18y0LzhCqMq4,1434
54
+ nlbone/core/domain/models.py,sha256=VEIfzruBXcF5XrDrWEvh9q-Ba9-9x_JG20wZsBF5thc,3270
55
+ nlbone/core/ports/__init__.py,sha256=syJg3fAjQALD5Rjfm9wi9bQpkIvNTWjE9AURBmy587o,132
53
56
  nlbone/core/ports/auth.py,sha256=C-GmUqHNx4bAku6KbW_OTpPXCEfurBWWyDi9KxpTi9M,553
54
57
  nlbone/core/ports/cache.py,sha256=8pP_z4ta7PNNG8UiSrEF4xMZRm2wLPxISZvdPt7QnxQ,2351
55
- nlbone/core/ports/event_bus.py,sha256=_Om1GOOT-F325oV6_LJXtLdx4vu5i7KrpTDD3qPJXU0,325
58
+ nlbone/core/ports/event_bus.py,sha256=7iC8WRBg-EmcKJx7AVPkP-r823SLKGuDxGp9WF4q-_U,824
56
59
  nlbone/core/ports/files.py,sha256=7Ov2ITYRpPwwDTZGCeNVISg8e3A9l08jbOgpTImgfK8,1863
57
- nlbone/core/ports/messaging.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
58
- nlbone/core/ports/repo.py,sha256=zOw8CTMAu5DKKy2wZpT3_6JWWjaJCDt7q4dOiJYrCOQ,651
59
- nlbone/core/ports/uow.py,sha256=SmBdRf0NvSdIjQ3Le1QGz8kNGBk7jgNHtNguvXRwmgs,557
60
+ nlbone/core/ports/outbox.py,sha256=mjA3uHS_ycE1oD4Ht8uDUf8QbwoC8r7llb6gBoIbAZU,2274
61
+ nlbone/core/ports/repository.py,sha256=Ee8iSt4WxUIt113zLd7hq0HwtHc8r8qRSFBMTiGuJq4,2822
62
+ nlbone/core/ports/uow.py,sha256=VhqSc-Ryt9m-rlNMiXTzD3dPGz6mM_JxND8D0UJGRu4,962
60
63
  nlbone/interfaces/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
64
  nlbone/interfaces/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
62
65
  nlbone/interfaces/api/exception_handlers.py,sha256=vxNEBgAaQygLgAz1UNt3wHj0SdCJOwtLOv_BwTfir3o,4050
@@ -65,7 +68,7 @@ nlbone/interfaces/api/routers.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hS
65
68
  nlbone/interfaces/api/schemas.py,sha256=NIEKeTdJtwwIkIxL7WURNZF8g34I4TlRAqs-x1Uq7YI,108
66
69
  nlbone/interfaces/api/additional_filed/__init__.py,sha256=BWemliLSQV9iq1vdUaF733q0FOSipSWBOQk9eYj732Q,318
67
70
  nlbone/interfaces/api/additional_filed/assembler.py,sha256=80sFuNiquqdLPOcx7MoQ_ud9fAJtA327M77Z9V47pIU,1956
68
- nlbone/interfaces/api/additional_filed/field_registry.py,sha256=xrA-2pMqX6JA4vy7LliJv5btQdy-6AKctFxZZCpWVOI,5321
71
+ nlbone/interfaces/api/additional_filed/field_registry.py,sha256=IhIvzHWOMtKv8iTdFu7LzQboi4SFTLOyJqKdYPY8xFE,5418
69
72
  nlbone/interfaces/api/additional_filed/resolver.py,sha256=jv1TIBBHN4LBIMwHGipcy4iq0uP0r6udyaqvhRzb8Bk,4655
70
73
  nlbone/interfaces/api/additional_filed/default_field_rules/__init__.py,sha256=LUSAOO3xRUt5ptlraIx7H-7dSkdr1D-WprmnqXRB16g,48
71
74
  nlbone/interfaces/api/additional_filed/default_field_rules/image_field_rules.py,sha256=ecKqPeXZ-YiF14RK9PmK7ln3PCzpCUc18S5zm5IF3fw,339
@@ -84,21 +87,25 @@ nlbone/interfaces/api/schema/__init__.py,sha256=LAqgynfupeqOQ6u0I5ucrcYnojRMZUg9
84
87
  nlbone/interfaces/api/schema/adaptive_schema.py,sha256=bdWBNpP2NfOJ_in4btXn0lrZOK70x-OqfmZ-NpIJdoQ,3347
85
88
  nlbone/interfaces/api/schema/base_response_model.py,sha256=lkBs7k0IcQiSQdJ3KvqDQPr_zwqKNbwaQjcwAE_chnU,599
86
89
  nlbone/interfaces/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
87
- nlbone/interfaces/cli/init_db.py,sha256=C67n2MsJ1vzkJxC8zfUYOxFdd6mEB_vT9agxN6jWoG8,790
88
- nlbone/interfaces/cli/main.py,sha256=pNldsTgplVyXa-Hx96dySO2I9gFRi49nDXv7J_dO73s,686
90
+ nlbone/interfaces/cli/crypto.py,sha256=lh2uUbSYKT6XxAt9uP1-VksopqAgdxiSKoKgXwXB0aE,692
91
+ nlbone/interfaces/cli/init_db.py,sha256=Hk3aZ8w9KdfgQfDWaOnIgNEAegn2uNggkkSgDXQLgyc,1791
92
+ nlbone/interfaces/cli/main.py,sha256=wI6YQMTQ4wxH-5ncFgrKKk2uVoinqO70oaWziOkfsfw,895
93
+ nlbone/interfaces/cli/ticket.py,sha256=7-T-4VTh6X41C2EX_oNvAFCRpQOe9UOfXCmLy-07TqQ,798
89
94
  nlbone/interfaces/jobs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
90
- nlbone/interfaces/jobs/dispatch_outbox.py,sha256=Hke-DsCqE3ixtTbvCQfh0IB6nqm9XZGIu-qNcApnoA4,804
95
+ nlbone/interfaces/jobs/dispatch_outbox.py,sha256=yLZSC3nvkgxT2LL4Pq_DYzCyf_tZB-FknrjjgN89GFg,809
91
96
  nlbone/interfaces/jobs/sync_tokens.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
92
97
  nlbone/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
93
98
  nlbone/utils/cache.py,sha256=hVfkR62o5vllDrE_nY4At10wK0It6qpZ45K1xoj10cQ,5931
94
99
  nlbone/utils/cache_keys.py,sha256=Y2YSellHTbUOcoaNbl1jaD4r485VU_e4KXsfBWhYTBo,1075
95
100
  nlbone/utils/cache_registry.py,sha256=w28sEfUQZAhzCCqVH5TflWQY3nyDXyEcFWt8hkuHRHw,823
96
101
  nlbone/utils/context.py,sha256=MmclJ24BG2uvSTg1IK7J-Da9BhVFDQ5ag4Ggs2FF1_w,1600
102
+ nlbone/utils/crypto.py,sha256=PX0Tlf2nqXcGbuv16J26MoUPzo2c4xcD4sZBXxhBXgQ,746
97
103
  nlbone/utils/http.py,sha256=UXUoXgQdTRNT08ho8zl-C5ekfDsD8uf-JiMQ323ooqw,872
104
+ nlbone/utils/normalize_mobile.py,sha256=sGH4tV9gX-6eVKozviNWJhm1DN1J28Nj-ERldCYkS_E,732
98
105
  nlbone/utils/redactor.py,sha256=-V4HrHmHwPi3Kez587Ek1uJlgK35qGSrwBOvcbw8Jas,1279
99
106
  nlbone/utils/time.py,sha256=DjjyQ9GLsfXoT6NK8RDW2rOlJg3e6sF04Jw6PBUrSvg,1268
100
- nlbone-0.6.19.dist-info/METADATA,sha256=v185nm1R92gj7OAhj7HYUYlWJc3Dmn5b_mk1Hoxb8IM,2228
101
- nlbone-0.6.19.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
102
- nlbone-0.6.19.dist-info/entry_points.txt,sha256=CpIL45t5nbhl1dGQPhfIIDfqqak3teK0SxPGBBr7YCk,59
103
- nlbone-0.6.19.dist-info/licenses/LICENSE,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
104
- nlbone-0.6.19.dist-info/RECORD,,
107
+ nlbone-0.7.0.dist-info/METADATA,sha256=GGuW7XamhW1Bg6v2NX5E09NS5L4W41k6MikQane4Fq8,2294
108
+ nlbone-0.7.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
109
+ nlbone-0.7.0.dist-info/entry_points.txt,sha256=CpIL45t5nbhl1dGQPhfIIDfqqak3teK0SxPGBBr7YCk,59
110
+ nlbone-0.7.0.dist-info/licenses/LICENSE,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
111
+ nlbone-0.7.0.dist-info/RECORD,,
@@ -1,20 +0,0 @@
1
- from typing import List
2
-
3
- class OutboxRecord(dict):
4
- pass
5
-
6
- class OutboxRepository:
7
- def __init__(self, engine):
8
- self._engine = engine
9
-
10
- def add(self, msg) -> None:
11
- ...
12
-
13
- def fetch_pending(self, limit: int = 100) -> List[OutboxRecord]:
14
- ...
15
-
16
- def mark_sent(self, msg_id: int) -> None:
17
- ...
18
-
19
- def schedule_retry(self, msg_id: int, retries: int, backoff_base: int = 2) -> None:
20
- ...
@@ -1,25 +0,0 @@
1
- from dataclasses import dataclass
2
- from typing import Protocol, Type, Any, Dict
3
-
4
-
5
- @dataclass(frozen=True)
6
- class Command:
7
- pass
8
-
9
-
10
- class CommandHandler(Protocol):
11
- def __call__(self, command: Command) -> Any: ...
12
-
13
-
14
- class CommandBus:
15
- def __init__(self) -> None:
16
- self._handlers: Dict[Type[Command], CommandHandler] = {}
17
-
18
- def register(self, cmd_type: Type[Command], handler: CommandHandler) -> None:
19
- self._handlers[cmd_type] = handler
20
-
21
- def dispatch(self, command: Command) -> Any:
22
- handler = self._handlers.get(type(command))
23
- if handler is None:
24
- raise LookupError(f"No handler registered for {type(command).__name__}")
25
- return handler(command)
@@ -1,20 +0,0 @@
1
- from typing import Iterable, Sequence
2
-
3
- from nlbone.core.domain.base import AggregateRoot, DomainEvent
4
- from nlbone.core.ports.event_bus import EventBusPort
5
-
6
-
7
- def collect_events(*aggregates: Iterable[AggregateRoot]) -> list[DomainEvent]:
8
- events: list[DomainEvent] = []
9
- for agg in aggregates:
10
- if isinstance(agg, AggregateRoot):
11
- events.extend(agg.pull_events())
12
- else:
13
- for a in agg:
14
- events.extend(a.pull_events())
15
- return events
16
-
17
-
18
- def publish_events(bus: EventBusPort, events: Sequence[DomainEvent]) -> None:
19
- if events:
20
- bus.publish(events)
File without changes
File without changes
File without changes
nlbone/core/ports/repo.py DELETED
@@ -1,19 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import Iterable, List, Optional, Protocol, TypeVar
4
-
5
- T = TypeVar("T")
6
-
7
-
8
- class Repository(Protocol[T]): # ← نه Protocol, Generic[T]
9
- def get(self, id) -> Optional[T]: ...
10
- def add(self, obj: T) -> None: ...
11
- def remove(self, obj: T) -> None: ...
12
- def list(self, *, limit: int | None = None, offset: int = 0) -> Iterable[T]: ...
13
-
14
-
15
- class AsyncRepository(Protocol[T]):
16
- async def get(self, id) -> Optional[T]: ...
17
- def add(self, obj: T) -> None: ...
18
- async def remove(self, obj: T) -> None: ...
19
- async def list(self, *, limit: int | None = None, offset: int = 0) -> List[T]: ...