amsdal_cli 0.0.1__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 (65) hide show
  1. amsdal_cli/Third-Party Materials - AMSDAL Dependencies - License Notices.md +1099 -0
  2. amsdal_cli/__about__.py +4 -0
  3. amsdal_cli/__init__.py +0 -0
  4. amsdal_cli/app.py +8 -0
  5. amsdal_cli/commands/__init__.py +0 -0
  6. amsdal_cli/commands/build/__init__.py +0 -0
  7. amsdal_cli/commands/build/command.py +27 -0
  8. amsdal_cli/commands/build/constants.py +1 -0
  9. amsdal_cli/commands/build/utils/__init__.py +0 -0
  10. amsdal_cli/commands/build/utils/build_app.py +46 -0
  11. amsdal_cli/commands/build/utils/build_config_file.py +36 -0
  12. amsdal_cli/commands/callbacks.py +47 -0
  13. amsdal_cli/commands/generate/__init__.py +0 -0
  14. amsdal_cli/commands/generate/app.py +5 -0
  15. amsdal_cli/commands/generate/command.py +5 -0
  16. amsdal_cli/commands/generate/enums.py +52 -0
  17. amsdal_cli/commands/generate/sub_commands/__init__.py +13 -0
  18. amsdal_cli/commands/generate/sub_commands/generate_hook.py +35 -0
  19. amsdal_cli/commands/generate/sub_commands/generate_model.py +94 -0
  20. amsdal_cli/commands/generate/sub_commands/generate_modifier.py +32 -0
  21. amsdal_cli/commands/generate/sub_commands/generate_property.py +38 -0
  22. amsdal_cli/commands/generate/sub_commands/generate_transaction.py +38 -0
  23. amsdal_cli/commands/generate/templates/hook.pyt +3 -0
  24. amsdal_cli/commands/generate/templates/modifier/constructor.pyt +10 -0
  25. amsdal_cli/commands/generate/templates/modifier/display_name.pyt +4 -0
  26. amsdal_cli/commands/generate/templates/modifier/version_name.pyt +4 -0
  27. amsdal_cli/commands/generate/templates/property.pyt +4 -0
  28. amsdal_cli/commands/generate/templates/transaction.pyt +7 -0
  29. amsdal_cli/commands/generate/utils/__init__.py +0 -0
  30. amsdal_cli/commands/generate/utils/build_base_path.py +22 -0
  31. amsdal_cli/commands/generate/utils/cast_to_attribute_type.py +19 -0
  32. amsdal_cli/commands/generate/utils/model_attributes.py +131 -0
  33. amsdal_cli/commands/new/__init__.py +0 -0
  34. amsdal_cli/commands/new/command.py +54 -0
  35. amsdal_cli/commands/new/templates/.amsdal-cli +6 -0
  36. amsdal_cli/commands/new/templates/.gitignore +4 -0
  37. amsdal_cli/commands/new/templates/README.md +646 -0
  38. amsdal_cli/commands/new/templates/config.yml +19 -0
  39. amsdal_cli/commands/serve/__init__.py +0 -0
  40. amsdal_cli/commands/serve/command.py +38 -0
  41. amsdal_cli/commands/serve/filters/__init__.py +0 -0
  42. amsdal_cli/commands/serve/filters/models_watch_filter.py +6 -0
  43. amsdal_cli/commands/serve/filters/static_files_watch_filter.py +21 -0
  44. amsdal_cli/commands/serve/services/__init__.py +0 -0
  45. amsdal_cli/commands/serve/services/supervisor.py +373 -0
  46. amsdal_cli/commands/serve/utils.py +16 -0
  47. amsdal_cli/commands/verify/__init__.py +0 -0
  48. amsdal_cli/commands/verify/command.py +74 -0
  49. amsdal_cli/commands/verify/models.py +10 -0
  50. amsdal_cli/commands/verify/utils/__init__.py +0 -0
  51. amsdal_cli/commands/verify/utils/verify_json_model.py +31 -0
  52. amsdal_cli/commands/verify/utils/verify_python_file.py +21 -0
  53. amsdal_cli/config/__init__.py +0 -0
  54. amsdal_cli/config/main.py +38 -0
  55. amsdal_cli/main.py +7 -0
  56. amsdal_cli/py.typed +0 -0
  57. amsdal_cli/utils/__init__.py +0 -0
  58. amsdal_cli/utils/cli_config.py +27 -0
  59. amsdal_cli/utils/copier.py +103 -0
  60. amsdal_cli/utils/render_template.py +12 -0
  61. amsdal_cli-0.0.1.dist-info/METADATA +353 -0
  62. amsdal_cli-0.0.1.dist-info/RECORD +65 -0
  63. amsdal_cli-0.0.1.dist-info/WHEEL +4 -0
  64. amsdal_cli-0.0.1.dist-info/entry_points.txt +2 -0
  65. amsdal_cli-0.0.1.dist-info/licenses/LICENSE.txt +107 -0
@@ -0,0 +1,646 @@
1
+ # {{ ctx.application_name }}
2
+
3
+ This application describes the model schemas, properties, transactions, hooks and modifiers which can be used within AMSDAL Framework to manage data.
4
+
5
+ # AMSDAL CLI Guide
6
+
7
+ AMSDAL CLI is a tool that enables the creation of AMSDAL-based applications. With this CLI, you can easily generate the skeletons of the main entities such as models, transactions, properties, and more. Additionally, it allows you to verify your code, apply code formatting, and build the end models.
8
+
9
+ One of the most useful features of the AMSDAL CLI is the ability to run a local test HTTP server. This server allows you to preview your changes before releasing them to production, ensuring that your code works as expected.
10
+
11
+ While not yet implemented, the AMSDAL CLI will also allow you to write and run unit tests for your code, making it easier to identify and fix any issues.
12
+
13
+ Overall, the AMSDAL CLI is a powerful tool for anyone looking to develop AMSDAL-based applications quickly and efficiently.
14
+
15
+ ## About This Guide
16
+
17
+ This guide is designed to help you get started with the AMSDAL CLI and create a sample application using it. We will walk you through the entire process of developing an application using the CLI, from installing the tool to generating the necessary entities and running a local test server.
18
+
19
+ By the end of this guide, you should have a good understanding of how to use the AMSDAL CLI for your own projects and be able to create AMSDAL-based applications with ease.
20
+
21
+ ## Installing AMSDAL CLI
22
+
23
+ TBD
24
+
25
+ ## Creating a new application
26
+
27
+ Now that you have installed the AMSDAL CLI, it's time to create your first application using it.
28
+
29
+ Try to open terminal in any place or folder and enter the `amsdal --help` command. You should see something like:
30
+
31
+ ```
32
+ Usage: amsdal [OPTIONS] COMMAND [ARGS]...
33
+
34
+ AMSDAL CLI - a tool that provides the ability to create a new app, generate
35
+ models, transactions, build, serve, and other useful features for the
36
+ efficient building of new apps using AMSDAL Framework.
37
+
38
+ ╭─ Options ────────────────────────────────────────────────────────────────────╮
39
+ │ --install-completion Install completion for the current shell. │
40
+ │ --show-completion Show completion for the current shell, to copy │
41
+ │ it or customize the installation. │
42
+ │ --help Show this message and exit. │
43
+ ╰──────────────────────────────────────────────────────────────────────────────╯
44
+ ╭─ Commands ───────────────────────────────────────────────────────────────────╮
45
+ │ build Build the app and generate the models and other files. │
46
+ │ generate Generates application's files such as models, properties, │
47
+ │ transactions, etc. │
48
+ │ new Generates a new AMSDAL application. │
49
+ │ serve Starts a test FastAPI server based on your app's models. │
50
+ │ verify Verifies all application's files such as models, properties, │
51
+ │ transactions, etc. │
52
+ ╰──────────────────────────────────────────────────────────────────────────────╯
53
+ ```
54
+
55
+ Note, the list of supported commands can differ due to extending the CLI.
56
+
57
+ First of all, we recommend to run `amsdal --install-completion` command. It might require to re-open the terminal or even re-login on your machine, but it will provide you ability to use auto-completion for all arguments and options supported by `amsdal` tool.
58
+
59
+ In order to create a new application we can use the `new` command, let’s take a look help for this command, type `amsdal new --help` in the terminal and press enter. You should see something like:
60
+
61
+ ```
62
+ Usage: amsdal new [OPTIONS] APP_NAME OUTPUT_PATH
63
+
64
+ Generates a new AMSDAL application.
65
+
66
+ ╭─ Arguments ──────────────────────────────────────────────────────────────────╮
67
+ │ * app_name TEXT The Application name. For example: MyApplication │
68
+ │ [default: None] │
69
+ │ [required] │
70
+ │ * output_path PATH Output path, where the app will be created. │
71
+ │ [default: None] │
72
+ │ [required] │
73
+ ╰──────────────────────────────────────────────────────────────────────────────╯
74
+ ╭─ Options ────────────────────────────────────────────────────────────────────╮
75
+ │ --help Show this message and exit. │
76
+ ╰──────────────────────────────────────────────────────────────────────────────╯
77
+ ```
78
+
79
+ OK, so we need to specify two arguments:
80
+
81
+ - `app_name` - the application name
82
+ - `output_path` - the path where the app will be create
83
+
84
+ Let’s create our first application using `amsdal new DataManager ~/` command. After executing this command you should see something like:
85
+
86
+ ```
87
+ The application is successfully created in /home/user/data_manager
88
+ ```
89
+
90
+ Let’s check out what is inside this folder. First of all, navigate to this directory:
91
+
92
+ ```bash
93
+ cd ~/data_manager
94
+ ```
95
+
96
+ And using `ls -la` let’s see what we have there:
97
+
98
+ ```
99
+ - 📄 .amsdal-cli
100
+ - 📄 config.yml
101
+ - 📄 .gitignore
102
+ - 📄 README.md
103
+ ```
104
+
105
+ Not so much but don’t worry we will generate everything else later.
106
+
107
+ The `.amsdal-cli` it is configuration for AMSDAL CLI for you current app. It stores the configuration in JSON format and should looks like:
108
+
109
+ ```
110
+ {
111
+ "config_path": "./config.yml",
112
+ "http_port": 8080,
113
+ "check_model_exists": true,
114
+ "json_indent": 4
115
+ }
116
+ ```
117
+
118
+ Where the `config_path` it’s a path to the default AMSDAL `config.yml` that was also generated automatically. The `http_port` is the port where will be hosted the test server. The `check_model_exists` stores a boolean value and affects the generate commands. The `json_indent` stores the indentation configuration (how many spaces) for formatting JSON files. These options we will learn more deeply below. For now, you need to know that this file is essential for AMSDAL CLI. By this file, CLI detects the application. You should not remove or rename this file.
119
+
120
+ The `README.md` contains this guide. You can change this file as you wish.
121
+
122
+ OK, it’s time to create our first model.
123
+
124
+ ## Generating models
125
+
126
+ Now that we have created a new AMSDAL application, let's generate a first model using the AMSDAL CLI. Run the following command:
127
+
128
+ ```
129
+ amsdal generate model Person --format json
130
+ ```
131
+
132
+ <aside>
133
+ ⚠️ Note any other commands except the `new` should be executed only from the folder of your application. So make sure you are inside the `~/data_manager` folder.
134
+
135
+ </aside>
136
+
137
+ <aside>
138
+ ⚠️ The `--format` option is required and currently it supports only `json`. It means the models will be generated in JSON format.
139
+
140
+ </aside>
141
+
142
+ Perfect! If we will check the directory of our application we will se that now we have there new folders and files:
143
+
144
+ ```
145
+ - 📁 models
146
+ - 📁 person
147
+ - 📄 model.json
148
+ ```
149
+
150
+ The `model.json` will have the following JSON content:
151
+
152
+ ```
153
+ {
154
+ "title": "Person",
155
+ "type": "object",
156
+ "properties": {},
157
+ "required": [],
158
+ "indexed": []
159
+ }
160
+ ```
161
+
162
+ You should be familiar with this file if you have already worked with AMSDAL.
163
+
164
+ The `amsdal generate model` also provides ability to generate the properties. Let’s re-generate this model and add some properties to our model:
165
+
166
+ ```
167
+ amsdal generate model Person -attrs "first_name:string last_name:string email:string:required:index age:number:default=21" --format json
168
+ ```
169
+
170
+ If we will run this command you will see the confirmation message:
171
+
172
+ ```
173
+ The file "~/data_manager/models/person/model.json" already exists. Would you like to overwrite it? [y/N]:
174
+ ```
175
+
176
+ Type `y` and press enter. Now, if will check our model `cat models/person/model.json` it will contain the following:
177
+
178
+ ```json
179
+ {
180
+ "title": "Person",
181
+ "type": "object",
182
+ "properties": {
183
+ "first_name": {
184
+ "title": "first_name",
185
+ "type": "string"
186
+ },
187
+ "last_name": {
188
+ "title": "last_name",
189
+ "type": "string"
190
+ },
191
+ "email": {
192
+ "title": "email",
193
+ "type": "string"
194
+ },
195
+ "age": {
196
+ "title": "age",
197
+ "type": "number",
198
+ "default": 21.0
199
+ }
200
+ },
201
+ "required": [
202
+ "email"
203
+ ],
204
+ "indexed": [
205
+ "email"
206
+ ]
207
+ }
208
+ ```
209
+
210
+ You can change this models manually as usually by adding new properties etc.
211
+
212
+ Let’s generate a new model using the following command:
213
+
214
+ ```
215
+ amsdal generate model PersonProfile -attrs "bio:string phone:string person:belongs-to:Person:required friends:dict:string:Person family:has-many:Person" --format json
216
+ ```
217
+
218
+ Let’s check out what we have in generated file by `cat models/person_profile/model.json`:
219
+
220
+ ```json
221
+ {
222
+ "title": "PersonProfile",
223
+ "type": "object",
224
+ "properties": {
225
+ "bio": {
226
+ "title": "bio",
227
+ "type": "string"
228
+ },
229
+ "phone": {
230
+ "title": "phone",
231
+ "type": "string"
232
+ },
233
+ "person": {
234
+ "title": "person",
235
+ "type": "Person"
236
+ },
237
+ "friends": {
238
+ "title": "friends",
239
+ "type": "dict",
240
+ "items": {
241
+ "key_type": "string",
242
+ "value_type": "Person"
243
+ }
244
+ },
245
+ "family": {
246
+ "title": "family",
247
+ "type": "array",
248
+ "items": {
249
+ "type": "Person"
250
+ }
251
+ }
252
+ },
253
+ "required": [
254
+ "person"
255
+ ],
256
+ "indexed": []
257
+ }
258
+ ```
259
+
260
+ Perfect!
261
+
262
+ Let’s now generate a custom property.
263
+
264
+ ## Generating custom properties
265
+
266
+ Run `amsdal generate property --model Person full_name` command.
267
+
268
+ It will generate a new file `models/person/properties/full_name.py` with following content:
269
+
270
+ ```python
271
+ @property
272
+ def full_name(self):
273
+ # TODO: implementation here
274
+ ...
275
+ ```
276
+
277
+ Cool, let’s add implementation for this property. Change it to the following:
278
+
279
+ ```python
280
+ @property
281
+ def full_name(self):
282
+ return f"{self.first_name} {self.last_name}"
283
+ ```
284
+
285
+ Now we have custom property `full_name` for Person model. We can generate the properties as much as we won't for any of our models.
286
+
287
+ Moreover, if you remember, we have `check_model_exists` in `.amsdal-cli` configuration file. If we will set it to `false`, we will be able to generate properties (and other entities) even if we don’t have the model JSON field yet. Let’s try it, make sure you have this configuration:
288
+
289
+ ```json
290
+ {
291
+ "config_path": "./config.yml",
292
+ "http_port": 8080,
293
+ "check_model_exists": false,
294
+ "json_indent": 4
295
+ }
296
+ ```
297
+
298
+ And try to generate property for non-existing model:
299
+
300
+ ```bash
301
+ amsdal generate property --model Address country_name
302
+ ```
303
+
304
+ It will successfully create `./models/address/properties/country_name.py` file.
305
+
306
+ Let’s try now generate a modifier!
307
+
308
+ ## Generating modifiers
309
+
310
+ The modifier, it’s predefined methods that allows you to override some specific built-in methods or properties of you end models. Currently we support these modifiers:
311
+
312
+ - constructor
313
+ - display_name
314
+ - version_name
315
+
316
+ Let’s try to generate the constructor modifier for PersonProfile model:
317
+
318
+ ```bash
319
+ amsdal generate modifier --model PersonProfile constructor
320
+ ```
321
+
322
+ It will generate the `./models/person_profile/modifiers/constructor.py` file with the following content:
323
+
324
+ ```python
325
+ def __init__(self, *args, **kwargs):
326
+ # TODO: implementation here
327
+ super().__init__(*args, **kwargs)
328
+ ```
329
+
330
+ Let’s implement the business logic that will make sure the age cannot be less the 21:
331
+
332
+ ```python
333
+ def __init__(self, *args, **kwargs):
334
+ age = kwargs.get("age") or 0
335
+
336
+ if age < 21:
337
+ kwargs["age"] = 21
338
+
339
+ super().__init__(*args, **kwargs)
340
+ ```
341
+
342
+ Perfect! You can generate any of available modifiers for your models.
343
+
344
+ Now, let’s generate a hook.
345
+
346
+ ## Generating hooks
347
+
348
+ Hooks are actions that are triggered before or after certain events occur in the AMSDAL framework. They allow you to customize the behavior of your application by executing custom code in response to specific events, such as creating or updating a model instance. Hooks can be used to perform a variety of tasks, such as validating data, sending notifications, or updating related models.
349
+
350
+ Currently we support the following hooks:
351
+
352
+ - on_create
353
+ - on_update
354
+ - on_migrate
355
+
356
+ Let’s create our first hook for Person model:
357
+
358
+ ```bash
359
+ amsdal generate hook --model Person on_create
360
+ ```
361
+
362
+ It will generate the `./models/person/hooks/on_create.py`:
363
+
364
+ ```python
365
+ async def on_create(self):
366
+ # TODO: implementation here
367
+ ...
368
+ ```
369
+
370
+ Let’s implement this hook and add the following business logic:
371
+
372
+ ```python
373
+ async def on_create(self):
374
+ from models.user.PersonProfile import PersonProfile
375
+
376
+ # Create automatically PersonProfile for each new Person
377
+ PersonProfile(
378
+ person=self,
379
+ bio="",
380
+ phone="",
381
+ friends={},
382
+ family=[],
383
+ )
384
+ ```
385
+
386
+ Note, `from models.user.PersonProfile import PersonProfile` it is how we can import our models, although it is not yet generated (we have only schema of the future model in JSON format).
387
+
388
+ Cool, now each time the new person will be created, the corresponding profile will be created for this person as well.
389
+
390
+ Now, let’s try to generate transaction!
391
+
392
+ ## Generating transactions
393
+
394
+ Run the following command:
395
+
396
+ ```bash
397
+ amsdal generate transaction MarkBestFriends
398
+ ```
399
+
400
+ It will generate the `./transactions/mark_best_friends.py` file:
401
+
402
+ ```python
403
+ from amsdal.core.classes.base import transaction
404
+
405
+
406
+ @transaction(name='MarkBestFriends')
407
+ async def mark_best_friends():
408
+ # TODO: implementation here
409
+ ...
410
+ ```
411
+
412
+ Let’s assume we need to have a migration that accepts two persons and make them as a best friends. So we need to add the following implementation for our transaction:
413
+
414
+ ```python
415
+ from models.user.Person import Person
416
+ from models.user.PersonProfile import PersonProfile
417
+
418
+ from amsdal.amsdal_core.connection.connection_filter import Filter, FilterType
419
+ from amsdal.amsdal_core.objects.service import AmsdalObjectsApi
420
+ from amsdal.core.classes.base import transaction
421
+
422
+
423
+ @transaction(name='MarkBestFriends')
424
+ async def mark_best_friends(
425
+ first_person: Person,
426
+ second_person: Person,
427
+ ):
428
+ first_profile = await get_profile_by_person(person=first_person)
429
+ second_profile = await get_profile_by_person(person=second_person)
430
+
431
+ if not first_profile or not second_profile:
432
+ return
433
+
434
+ await first_profile.async_new_version(friends={"best": second_person})
435
+ await second_profile.async_new_version(friends={"best": first_person})
436
+
437
+ async def get_profile_by_person(person: Person):
438
+ api = AmsdalObjectsApi()
439
+ profiles: list[PersonProfile] = await api.async_get_amsdal_objects_basemodel(
440
+ PersonProfile.__name__,
441
+ [
442
+ Filter(
443
+ key="person",
444
+ filter_type=FilterType.eq,
445
+ target=str(person.build_reference(is_latest=person.get_metadata().is_latest)),
446
+ ),
447
+ ],
448
+ )
449
+
450
+ return next(iter(profile for profile in profiles if profile._metadata.is_latest), None)
451
+ ```
452
+
453
+ Perfect! We are ready to verify our files.
454
+
455
+ ## Verifying the application
456
+
457
+ AMSDAL CLI provides the command that allows to verify your create files. Let’s run `amsdal verify`. This command only checks syntax errors in your python and JSON files. We also can verify building of end models by using the following option:
458
+
459
+ ```bash
460
+ amsdal verify --building
461
+ ```
462
+
463
+ You will see something like this:
464
+
465
+ ```
466
+ Syntax checking... OK!
467
+ Pre-building app...
468
+ Building model "PersonProfile"... OK!
469
+ Building modifiers...
470
+ Processing ./data_manager/models/person_profile/modifiers/constructor.py...
471
+ OK!
472
+ Building model "Person"... OK!
473
+ Building properties...
474
+ Processing ./data_manager/models/person/properties/full_name.py...
475
+ OK!
476
+ Building hooks...
477
+ Processing ./data_manager/models/person/hooks/on_create.py...
478
+ OK!
479
+ Neither Python nor JSON model was not found in "./data_manager/models/address". Skipped!
480
+ Building transactions... OK!
481
+ OK!
482
+ Verifying models... OK!
483
+ ```
484
+
485
+ As you can see, now it checks syntax and also building of your all models, properties and other entities.
486
+
487
+ <aside>
488
+ 🔥 Note, the `./data_manager/models/address` directory was skipped due to missing the model itself.
489
+
490
+ </aside>
491
+
492
+ Let’s adjust our Person model and add into, for example, `indexes` undefined property `is_active`:
493
+
494
+ ```json
495
+ {
496
+ "title": "Person",
497
+ "type": "object",
498
+ "properties": {
499
+ "first_name": {
500
+ "title": "first_name",
501
+ "type": "string"
502
+ },
503
+ "last_name": {
504
+ "title": "last_name",
505
+ "type": "string"
506
+ },
507
+ "email": {
508
+ "title": "email",
509
+ "type": "string"
510
+ },
511
+ "age": {
512
+ "title": "age",
513
+ "type": "number",
514
+ "default": 21.0
515
+ }
516
+ },
517
+ "required": [
518
+ "email"
519
+ ],
520
+ "indexed": [
521
+ "email",
522
+ "is_active"
523
+ ]
524
+ }
525
+ ```
526
+
527
+ And try to run verify command with building again:
528
+
529
+ ```bash
530
+ amsdal verify --building
531
+ ```
532
+
533
+ You will see the corresponding error message:
534
+
535
+ ```
536
+ Verifying models... Failed: Property is_active marked as indexed but wasn't found in class schema's properties.
537
+ ```
538
+
539
+ Let’s fix it and add this property by changing the schema of Person model to the following:
540
+
541
+ ```json
542
+ {
543
+ "title": "Person",
544
+ "type": "object",
545
+ "properties": {
546
+ "first_name": {
547
+ "title": "first_name",
548
+ "type": "string"
549
+ },
550
+ "last_name": {
551
+ "title": "last_name",
552
+ "type": "string"
553
+ },
554
+ "email": {
555
+ "title": "email",
556
+ "type": "string"
557
+ },
558
+ "age": {
559
+ "title": "age",
560
+ "type": "number",
561
+ "default": 21.0
562
+ },
563
+ "is_active": {
564
+ "title": "is_active",
565
+ "type": "boolean",
566
+ "default": true
567
+ }
568
+ },
569
+ "required": [
570
+ "email"
571
+ ],
572
+ "indexed": [
573
+ "email",
574
+ "is_active"
575
+ ]
576
+ }
577
+ ```
578
+
579
+ Run the verify command again. You should see that verification was done successfully.
580
+
581
+ Perfect! Now it’s time to run test server to test our models manually using the frontend app.
582
+
583
+ ## Running the test server
584
+
585
+ Just run the following command from the root directory of our project:
586
+
587
+ ```bash
588
+ amsdal serve
589
+ ```
590
+
591
+ You will see something like this:
592
+
593
+ ```
594
+ INFO: Started server process [149586]
595
+ INFO: Waiting for application startup.
596
+ INFO: Application startup complete.
597
+ INFO: Uvicorn running on http://localhost:8080 (Press CTRL+C to quit)
598
+ ```
599
+
600
+ It means everything were generated properly and the test server was started successfully.
601
+
602
+ Now you can navigate to [http://localhost:8080/docs](http://localhost:8080/docs) in you browser to view API documentation.
603
+
604
+ <aside>
605
+ ⚠️ Currently, it does not support the hot-reloading. So each time you make changes in your application you need to re-run the test server.
606
+
607
+ </aside>
608
+
609
+ Now we are also able to use [https://localhost.portal.amsdal.com/](https://localhost.portal.amsdal.com/) portal that links to our locally running test server and try to create Person record.
610
+
611
+ <aside>
612
+ ⚠️ By default, it will create the following user credentials that you can use for signing in on [https://localhost.portal.amsdal.com/](https://localhost.portal.amsdal.com/):
613
+ Email: **admin@amsdal.com**
614
+ Password: **adminpassword**
615
+
616
+ </aside>
617
+
618
+ ## Building the end models
619
+
620
+ Now, after manual testing we are ready to build our end models and files for production. AMSDAL CLI provide the build command that you can use for this.
621
+
622
+ Let’s run the following command:
623
+
624
+ ```bash
625
+ amsdal build ~/release
626
+ ```
627
+
628
+ This command will create the folder `release` in you `$HOME` directory and place there all necessary models and files. Let’s see what we have there right now using `ls ~/release/` command:
629
+
630
+ ```bash
631
+ - 📄 config.yml
632
+ - 📄 data-manager.sqlite
633
+ - 📁 models
634
+ - - 📄 __init__.py
635
+ - - 📁 core
636
+ - - - ...
637
+ - - 📁 user
638
+ - - - 📄 __init__.py
639
+ - - - 📄 Person.py
640
+ - - - 📄 PersonProfile.py
641
+ - - - 📄 transactions.py
642
+ ```
643
+
644
+ The `./models/core` will contain all built-in generated models that are required for AMSDAL core framework.
645
+
646
+ Your models and transactions.py will be placed into `./models/user` directory.
@@ -0,0 +1,19 @@
1
+ application_name: {{ ctx.application_name_slugify }}
2
+ connections:
3
+ - name: iceberg
4
+ backend: amsdal_data.connections.implementations.iceberg_history.IcebergHistoricalConnection
5
+ credentials:
6
+ - spark.sql.catalog.amsdal.warehouse: ./warehouse
7
+ - spark.sql.warehouse.dir: ./warehouse_sql
8
+ - spark.sql.catalog.amsdal.uri: jdbc:sqlite:./warehouse/amsdal.db
9
+ - name: sqlite
10
+ backend: amsdal_data.connections.implementations.sqlite_state.SqliteStateConnection
11
+ credentials:
12
+ - db_path: ./warehouse/amsdal_state.db
13
+ - name: lock
14
+ backend: amsdal_data.lock.implementations.thread_lock.ThreadLock
15
+ resources_config:
16
+ lakehouse: iceberg
17
+ lock: lock
18
+ repository:
19
+ default: sqlite
File without changes
@@ -0,0 +1,38 @@
1
+ from pathlib import Path
2
+
3
+ import typer
4
+
5
+ from amsdal_cli.app import app
6
+ from amsdal_cli.commands.generate.enums import SOURCES_DIR
7
+ from amsdal_cli.commands.serve.services.supervisor import Supervisor
8
+ from amsdal_cli.commands.serve.utils import cleanup_app
9
+ from amsdal_cli.utils.cli_config import CliConfig
10
+
11
+
12
+ @app.command(name='serve')
13
+ def serve_command(
14
+ ctx: typer.Context,
15
+ *,
16
+ cleanup: bool = typer.Option(
17
+ False,
18
+ help='Cleanup the generated models, warehouse and files after stopping',
19
+ ),
20
+ config: Path = typer.Option(None, help='Path to custom config.yml file'), # noqa: B008
21
+ ) -> None:
22
+ """
23
+ Build the app and generate the models and other files.
24
+ """
25
+ cli_config: CliConfig = ctx.meta['config']
26
+ app_source_path = cli_config.app_directory / SOURCES_DIR
27
+ supervisor = Supervisor(
28
+ app_source_path=app_source_path,
29
+ output_path=cli_config.app_directory,
30
+ config_path=config or cli_config.config_path,
31
+ )
32
+ try:
33
+ supervisor.run()
34
+ finally:
35
+ supervisor.wait()
36
+
37
+ if cleanup:
38
+ cleanup_app(output_path=cli_config.app_directory)
File without changes