codymaster 4.6.0 → 5.2.0

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 (161) hide show
  1. package/CHANGELOG.md +74 -8
  2. package/README.md +192 -95
  3. package/dist/advisory-handoff.js +89 -0
  4. package/dist/advisory-report.js +105 -0
  5. package/dist/browse-server.js +251 -0
  6. package/dist/cli/command-registry.js +34 -0
  7. package/dist/cli/commands/agent.js +120 -0
  8. package/dist/cli/commands/bench.js +69 -0
  9. package/dist/cli/commands/brain.js +108 -0
  10. package/dist/cli/commands/dashboard.js +93 -0
  11. package/dist/cli/commands/design-studio.js +111 -0
  12. package/dist/cli/commands/distro.js +25 -0
  13. package/dist/cli/commands/engineering.js +596 -0
  14. package/dist/cli/commands/evolve.js +123 -0
  15. package/dist/cli/commands/mcp-serve.js +104 -0
  16. package/dist/cli/commands/project.js +324 -0
  17. package/dist/cli/commands/skill-chain.js +269 -0
  18. package/dist/cli/commands/system.js +89 -0
  19. package/dist/cli/commands/task.js +254 -0
  20. package/dist/cli/update-check.js +83 -0
  21. package/dist/cm-config.js +92 -0
  22. package/dist/cm-suggest.js +77 -0
  23. package/dist/codybench/judges/automated.js +31 -0
  24. package/dist/codybench/runners/claude-code.js +32 -0
  25. package/dist/codybench/suites/memory-retention.js +85 -0
  26. package/dist/codybench/suites/tdd-regression.js +35 -0
  27. package/dist/codybench/suites/token-efficiency.js +55 -0
  28. package/dist/codybench/types.js +2 -0
  29. package/dist/context-db.js +157 -0
  30. package/dist/continuity.js +2 -6
  31. package/dist/distro-validate.js +54 -0
  32. package/dist/execution-analyzer.js +138 -0
  33. package/dist/guardian-core.js +74 -0
  34. package/dist/index.js +36 -2759
  35. package/dist/indexer/skills-lib.js +533 -0
  36. package/dist/indexer/skills-map.js +1374 -0
  37. package/dist/indexer/skills.js +16 -0
  38. package/dist/learning-promoter.js +246 -0
  39. package/dist/mcp-context-server.js +289 -1
  40. package/dist/mcp-skills-tools.js +81 -0
  41. package/dist/retro-summary.js +70 -0
  42. package/dist/second-opinion-providers.js +79 -0
  43. package/dist/skill-chain.js +63 -1
  44. package/dist/skill-evolver.js +456 -0
  45. package/dist/skill-execution-cache.js +254 -0
  46. package/dist/smart-brain-router.js +184 -0
  47. package/dist/sprint-pipeline.js +228 -0
  48. package/dist/storage-backend.js +14 -67
  49. package/dist/token-budget.js +88 -0
  50. package/dist/utils/cli-utils.js +76 -0
  51. package/dist/utils/skill-utils.js +32 -0
  52. package/package.json +17 -7
  53. package/scripts/build-skills.mjs +51 -0
  54. package/scripts/gate-0-repo-hygiene.js +75 -0
  55. package/scripts/postinstall.js +34 -28
  56. package/scripts/security-scan.js +1 -1
  57. package/scripts/validate-skills.mjs +42 -0
  58. package/skills/CLAUDE.md +2 -7
  59. package/skills/_shared/helpers.md +2 -8
  60. package/skills/cm-ads-tracker/SKILL.md +3 -6
  61. package/skills/cm-browse/SKILL.md +34 -0
  62. package/skills/cm-conductor-worktrees/SKILL.md +28 -0
  63. package/skills/cm-content-factory/SKILL.md +1 -1
  64. package/skills/cm-content-factory/landing/docs/content/changelog.md +36 -0
  65. package/skills/cm-content-factory/landing/docs/content/deployment.md +46 -0
  66. package/skills/cm-content-factory/landing/docs/content/execution-flow.md +67 -0
  67. package/skills/cm-content-factory/landing/docs/content/memory-system.md +38 -0
  68. package/skills/cm-content-factory/landing/docs/content/openspace.md +27 -0
  69. package/skills/cm-content-factory/landing/docs/content/use-cases.md +26 -0
  70. package/skills/cm-content-factory/landing/docs/content/v5-intro.md +28 -0
  71. package/skills/cm-content-factory/landing/docs/index.html +240 -0
  72. package/skills/cm-content-factory/landing/index.html +100 -100
  73. package/skills/cm-content-factory/landing/script.js +42 -0
  74. package/skills/cm-content-factory/landing/translations.js +400 -400
  75. package/skills/cm-continuity/SKILL.md +32 -33
  76. package/skills/cm-design-studio/SKILL.md +34 -0
  77. package/skills/cm-ecosystem-roadmap/SKILL.md +15 -0
  78. package/skills/cm-engineering-meta/SKILL.md +73 -0
  79. package/skills/cm-growth-hacking/SKILL.md +1 -12
  80. package/skills/cm-guardian-runtime/SKILL.md +26 -0
  81. package/skills/cm-mcp-engineering/SKILL.md +22 -0
  82. package/skills/cm-notebooklm/SKILL.md +1 -17
  83. package/skills/cm-post-deploy-canary/SKILL.md +22 -0
  84. package/skills/cm-project-bootstrap/SKILL.md +11 -0
  85. package/skills/cm-qa-visual-cli/SKILL.md +22 -0
  86. package/skills/cm-retro-cli/SKILL.md +23 -0
  87. package/skills/cm-second-opinion-cli/SKILL.md +23 -0
  88. package/skills/cm-secret-shield/SKILL.md +2 -2
  89. package/skills/cm-security-gate/SKILL.md +1 -0
  90. package/skills/cm-skill-chain/SKILL.md +25 -4
  91. package/skills/cm-skill-evolution/SKILL.md +83 -0
  92. package/skills/cm-skill-health/SKILL.md +83 -0
  93. package/skills/cm-skill-index/SKILL.md +11 -3
  94. package/skills/cm-skill-search/SKILL.md +49 -0
  95. package/skills/cm-skill-share/SKILL.md +58 -0
  96. package/skills/cm-sprint-bus/SKILL.md +33 -0
  97. package/skills/cm-start/SKILL.md +0 -10
  98. package/skills/cm-tdd/SKILL.md +59 -72
  99. package/skills/profiles/README.md +21 -0
  100. package/skills/profiles/core.txt +23 -0
  101. package/skills/profiles/design.txt +6 -0
  102. package/skills/profiles/full.txt +62 -0
  103. package/skills/profiles/growth.txt +10 -0
  104. package/skills/profiles/knowledge.txt +7 -0
  105. package/install.sh +0 -901
  106. package/scripts/test-gemini.js +0 -13
  107. package/skills/cm-frappe-agent/SKILL.md +0 -134
  108. package/skills/cm-frappe-agent/agents/doctype-architect.md +0 -596
  109. package/skills/cm-frappe-agent/agents/erpnext-customizer.md +0 -643
  110. package/skills/cm-frappe-agent/agents/frappe-backend.md +0 -814
  111. package/skills/cm-frappe-agent/agents/frappe-custom-frontend.md +0 -557
  112. package/skills/cm-frappe-agent/agents/frappe-debugger.md +0 -625
  113. package/skills/cm-frappe-agent/agents/frappe-fixer.md +0 -275
  114. package/skills/cm-frappe-agent/agents/frappe-frontend.md +0 -660
  115. package/skills/cm-frappe-agent/agents/frappe-installer.md +0 -158
  116. package/skills/cm-frappe-agent/agents/frappe-performance.md +0 -307
  117. package/skills/cm-frappe-agent/agents/frappe-planner.md +0 -419
  118. package/skills/cm-frappe-agent/agents/frappe-remote-ops.md +0 -153
  119. package/skills/cm-frappe-agent/agents/github-workflow.md +0 -286
  120. package/skills/cm-frappe-agent/commands/frappe-app.md +0 -351
  121. package/skills/cm-frappe-agent/commands/frappe-backend.md +0 -162
  122. package/skills/cm-frappe-agent/commands/frappe-bench.md +0 -254
  123. package/skills/cm-frappe-agent/commands/frappe-debug.md +0 -263
  124. package/skills/cm-frappe-agent/commands/frappe-doctype-create.md +0 -272
  125. package/skills/cm-frappe-agent/commands/frappe-doctype-field.md +0 -310
  126. package/skills/cm-frappe-agent/commands/frappe-erpnext.md +0 -210
  127. package/skills/cm-frappe-agent/commands/frappe-fix.md +0 -59
  128. package/skills/cm-frappe-agent/commands/frappe-frontend.md +0 -210
  129. package/skills/cm-frappe-agent/commands/frappe-fullstack.md +0 -243
  130. package/skills/cm-frappe-agent/commands/frappe-github.md +0 -57
  131. package/skills/cm-frappe-agent/commands/frappe-install.md +0 -52
  132. package/skills/cm-frappe-agent/commands/frappe-plan.md +0 -442
  133. package/skills/cm-frappe-agent/commands/frappe-remote.md +0 -58
  134. package/skills/cm-frappe-agent/commands/frappe-test.md +0 -356
  135. package/skills/cm-frappe-agent/docs/README.md +0 -51
  136. package/skills/cm-frappe-agent/docs/agents-catalog.md +0 -113
  137. package/skills/cm-frappe-agent/docs/architecture.md +0 -149
  138. package/skills/cm-frappe-agent/docs/commands-catalog.md +0 -82
  139. package/skills/cm-frappe-agent/docs/resources-catalog.md +0 -66
  140. package/skills/cm-frappe-agent/docs/sitemap-urls.txt +0 -52
  141. package/skills/cm-frappe-agent/docs/sitemap.md +0 -81
  142. package/skills/cm-frappe-agent/docs/sop/user-guide.md +0 -178
  143. package/skills/cm-frappe-agent/docs/sop/vibe-coding-guide.md +0 -122
  144. package/skills/cm-frappe-agent/resources/7-layer-architecture.md +0 -985
  145. package/skills/cm-frappe-agent/resources/bench_commands.md +0 -73
  146. package/skills/cm-frappe-agent/resources/code-patterns-guide.md +0 -948
  147. package/skills/cm-frappe-agent/resources/common_pitfalls.md +0 -266
  148. package/skills/cm-frappe-agent/resources/doctype-registry.md +0 -158
  149. package/skills/cm-frappe-agent/resources/installation-guide.md +0 -289
  150. package/skills/cm-frappe-agent/resources/rest-api-patterns.md +0 -182
  151. package/skills/cm-frappe-agent/resources/scaffold_checklist.md +0 -82
  152. package/skills/cm-frappe-agent/resources/upgrade_patterns.md +0 -113
  153. package/skills/cm-frappe-agent/resources/web-form-patterns.md +0 -252
  154. package/skills/cm-frappe-agent/skills/bench-commands/SKILL.md +0 -621
  155. package/skills/cm-frappe-agent/skills/client-scripts/SKILL.md +0 -642
  156. package/skills/cm-frappe-agent/skills/doctype-patterns/SKILL.md +0 -576
  157. package/skills/cm-frappe-agent/skills/frappe-api/SKILL.md +0 -740
  158. package/skills/cm-frappe-agent/skills/remote-operations/SKILL.md +0 -47
  159. package/skills/cm-frappe-agent/skills/server-scripts/SKILL.md +0 -608
  160. package/skills/cm-frappe-agent/skills/web-forms/SKILL.md +0 -46
  161. package/skills/frappe-app-builder.zip +0 -0
@@ -1,740 +0,0 @@
1
- ---
2
- name: frappe-api
3
- description: Frappe Python and JavaScript API reference including document operations, database queries, utilities, and REST API patterns. Use when working with frappe.get_doc, frappe.db, frappe.call, or any Frappe API methods.
4
- ---
5
-
6
- # Frappe API Reference
7
-
8
- Complete reference for Frappe's Python and JavaScript APIs for document operations, database queries, utilities, and server communication.
9
-
10
- ## When to Use This Skill
11
-
12
- - Working with Document API (get_doc, new_doc, save)
13
- - Database operations (frappe.db.*)
14
- - Making API calls from client to server
15
- - Using Frappe utilities (date, number formatting)
16
- - Creating whitelisted API endpoints
17
- - Working with REST API
18
-
19
- ## Python API
20
-
21
- ### Document Operations
22
-
23
- #### Get Document
24
- ```python
25
- # Get existing document
26
- doc = frappe.get_doc("Customer", "CUST-001")
27
-
28
- # Get document with filters
29
- doc = frappe.get_doc("Customer", {"customer_name": "John"})
30
-
31
- # Get last document
32
- doc = frappe.get_last_doc("Customer", filters={"status": "Active"})
33
-
34
- # Get cached document (read-only, faster)
35
- doc = frappe.get_cached_doc("Customer", "CUST-001")
36
-
37
- # Check if document exists
38
- if frappe.db.exists("Customer", "CUST-001"):
39
- doc = frappe.get_doc("Customer", "CUST-001")
40
- ```
41
-
42
- #### Create Document
43
- ```python
44
- # Create new document
45
- doc = frappe.new_doc("Customer")
46
- doc.customer_name = "New Customer"
47
- doc.customer_type = "Company"
48
- doc.insert()
49
-
50
- # Create with dict
51
- doc = frappe.get_doc({
52
- "doctype": "Customer",
53
- "customer_name": "New Customer",
54
- "customer_type": "Company"
55
- })
56
- doc.insert()
57
-
58
- # Create and insert in one step
59
- doc = frappe.get_doc({
60
- "doctype": "Customer",
61
- "customer_name": "New Customer"
62
- }).insert()
63
-
64
- # Insert ignoring permissions
65
- doc.insert(ignore_permissions=True)
66
-
67
- # Insert ignoring mandatory fields
68
- doc.insert(ignore_mandatory=True)
69
- ```
70
-
71
- #### Update Document
72
- ```python
73
- # Update and save
74
- doc = frappe.get_doc("Customer", "CUST-001")
75
- doc.customer_name = "Updated Name"
76
- doc.save()
77
-
78
- # Save ignoring permissions
79
- doc.save(ignore_permissions=True)
80
-
81
- # Update single value
82
- frappe.db.set_value("Customer", "CUST-001", "customer_name", "New Name")
83
-
84
- # Update multiple values
85
- frappe.db.set_value("Customer", "CUST-001", {
86
- "customer_name": "New Name",
87
- "status": "Active"
88
- })
89
-
90
- # Bulk update
91
- frappe.db.set_value("Customer", {"status": "Inactive"}, "status", "Active")
92
- ```
93
-
94
- #### Delete Document
95
- ```python
96
- # Delete document
97
- frappe.delete_doc("Customer", "CUST-001")
98
-
99
- # Delete ignoring permissions
100
- frappe.delete_doc("Customer", "CUST-001", ignore_permissions=True)
101
-
102
- # Delete with linked documents
103
- frappe.delete_doc("Customer", "CUST-001", force=True)
104
-
105
- # Delete from controller
106
- doc.delete()
107
- ```
108
-
109
- ### Database API (frappe.db)
110
-
111
- #### Select Queries
112
- ```python
113
- # Get single value
114
- value = frappe.db.get_value("Customer", "CUST-001", "customer_name")
115
-
116
- # Get multiple fields
117
- values = frappe.db.get_value("Customer", "CUST-001",
118
- ["customer_name", "status"], as_dict=True)
119
-
120
- # Get with filters
121
- value = frappe.db.get_value("Customer",
122
- {"customer_type": "Company"}, "customer_name")
123
-
124
- # Get list of values
125
- names = frappe.db.get_all("Customer",
126
- filters={"status": "Active"},
127
- fields=["name", "customer_name"],
128
- order_by="creation desc",
129
- limit=10
130
- )
131
-
132
- # Get list with pluck (single field as list)
133
- names = frappe.db.get_all("Customer",
134
- filters={"status": "Active"},
135
- pluck="name"
136
- )
137
-
138
- # Complex filters
139
- docs = frappe.db.get_all("Sales Invoice",
140
- filters={
141
- "status": ["in", ["Paid", "Unpaid"]],
142
- "grand_total": [">", 1000],
143
- "posting_date": ["between", ["2024-01-01", "2024-12-31"]],
144
- "customer": ["like", "%Corp%"]
145
- },
146
- fields=["name", "customer", "grand_total"]
147
- )
148
-
149
- # Filter operators
150
- # =, !=, <, >, <=, >=
151
- # in, not in
152
- # like, not like
153
- # between
154
- # is, is not (for None)
155
- # descendants of, ancestors of (for tree doctypes)
156
-
157
- # Get count
158
- count = frappe.db.count("Customer", {"status": "Active"})
159
-
160
- # Check existence
161
- exists = frappe.db.exists("Customer", "CUST-001")
162
- exists = frappe.db.exists("Customer", {"customer_name": "John"})
163
- ```
164
-
165
- #### Raw SQL
166
- ```python
167
- # Execute SQL query
168
- result = frappe.db.sql("""
169
- SELECT name, customer_name, grand_total
170
- FROM `tabSales Invoice`
171
- WHERE status = %s AND grand_total > %s
172
- ORDER BY creation DESC
173
- LIMIT 10
174
- """, ("Paid", 1000), as_dict=True)
175
-
176
- # Single value
177
- total = frappe.db.sql("""
178
- SELECT SUM(grand_total) FROM `tabSales Invoice`
179
- WHERE status = 'Paid'
180
- """)[0][0]
181
-
182
- # With named parameters
183
- result = frappe.db.sql("""
184
- SELECT * FROM `tabCustomer`
185
- WHERE name = %(name)s
186
- """, {"name": "CUST-001"}, as_dict=True)
187
- ```
188
-
189
- #### Insert/Update
190
- ```python
191
- # Insert raw
192
- frappe.db.sql("""
193
- INSERT INTO `tabCustomer` (name, customer_name)
194
- VALUES (%s, %s)
195
- """, ("CUST-002", "New Customer"))
196
-
197
- # Commit transaction
198
- frappe.db.commit()
199
-
200
- # Rollback
201
- frappe.db.rollback()
202
- ```
203
-
204
- ### Whitelisted API
205
-
206
- ```python
207
- # Create API endpoint
208
- @frappe.whitelist()
209
- def get_customer_details(customer):
210
- """Get customer details
211
-
212
- Args:
213
- customer: Customer ID
214
-
215
- Returns:
216
- dict: Customer details
217
- """
218
- doc = frappe.get_doc("Customer", customer)
219
- return {
220
- "name": doc.name,
221
- "customer_name": doc.customer_name,
222
- "outstanding_amount": get_outstanding(customer)
223
- }
224
-
225
- # Allow guest access (no login required)
226
- @frappe.whitelist(allow_guest=True)
227
- def public_api():
228
- return {"status": "ok"}
229
-
230
- # With specific methods
231
- @frappe.whitelist(methods=["POST"])
232
- def create_record(data):
233
- doc = frappe.get_doc(data)
234
- doc.insert()
235
- return doc.name
236
- ```
237
-
238
- ### Utilities
239
-
240
- #### Date/Time
241
- ```python
242
- from frappe.utils import (
243
- now, nowdate, nowtime, now_datetime,
244
- today, getdate, get_datetime,
245
- add_days, add_months, add_years,
246
- date_diff, time_diff, time_diff_in_seconds,
247
- get_first_day, get_last_day,
248
- formatdate, format_datetime
249
- )
250
-
251
- # Current date/time
252
- current = nowdate() # "2024-01-15"
253
- current_dt = now_datetime() # datetime object
254
- timestamp = now() # "2024-01-15 10:30:00"
255
-
256
- # Date arithmetic
257
- next_week = add_days(nowdate(), 7)
258
- next_month = add_months(nowdate(), 1)
259
- last_year = add_years(nowdate(), -1)
260
-
261
- # Date difference
262
- days = date_diff(end_date, start_date)
263
- seconds = time_diff_in_seconds(end_time, start_time)
264
-
265
- # First/last day of month
266
- first = get_first_day(nowdate())
267
- last = get_last_day(nowdate())
268
-
269
- # Parse dates
270
- date_obj = getdate("2024-01-15")
271
- dt_obj = get_datetime("2024-01-15 10:30:00")
272
-
273
- # Format dates
274
- formatted = formatdate("2024-01-15", "dd-MM-yyyy")
275
- ```
276
-
277
- #### Numbers
278
- ```python
279
- from frappe.utils import (
280
- flt, cint, cstr,
281
- fmt_money, rounded,
282
- money_in_words
283
- )
284
-
285
- # Type conversion with defaults
286
- num = flt(value) # float, None -> 0.0
287
- num = flt(value, 2) # with precision
288
- integer = cint(value) # int, None -> 0
289
- string = cstr(value) # string, None -> ""
290
-
291
- # Formatting
292
- formatted = fmt_money(1234.56, currency="USD") # "$1,234.56"
293
- rounded_val = rounded(1234.567, 2) # 1234.57
294
- words = money_in_words(1234.56, "USD") # "One Thousand..."
295
- ```
296
-
297
- #### Strings
298
- ```python
299
- from frappe.utils import (
300
- strip_html, strip_html_tags,
301
- escape_html, sanitize_html,
302
- scrub, unscrub
303
- )
304
-
305
- # HTML handling
306
- plain = strip_html("<p>Hello</p>") # "Hello"
307
- safe = escape_html("<script>bad</script>")
308
-
309
- # Field name conversion
310
- field = scrub("My Field Name") # "my_field_name"
311
- label = unscrub("my_field_name") # "My Field Name"
312
- ```
313
-
314
- ### Messaging & Notifications
315
-
316
- ```python
317
- # Show message (appears as toast)
318
- frappe.msgprint("Document saved successfully")
319
-
320
- # With indicator
321
- frappe.msgprint("Error occurred", indicator="red", title="Error")
322
-
323
- # Throw error (stops execution)
324
- frappe.throw("Invalid data provided")
325
-
326
- # With exception type
327
- from frappe.exceptions import ValidationError
328
- frappe.throw("Validation failed", exc=ValidationError)
329
-
330
- # Send email
331
- frappe.sendmail(
332
- recipients=["user@example.com"],
333
- subject="Hello",
334
- message="Email body",
335
- template="email_template",
336
- args={"name": "John"}
337
- )
338
-
339
- # Create system notification
340
- frappe.publish_realtime(
341
- "msgprint",
342
- {"message": "Task completed"},
343
- user="user@example.com"
344
- )
345
- ```
346
-
347
- ### Background Jobs
348
-
349
- ```python
350
- # Enqueue background job
351
- frappe.enqueue(
352
- "myapp.tasks.heavy_task",
353
- queue="long",
354
- timeout=600,
355
- job_name="Heavy Task",
356
- customer="CUST-001"
357
- )
358
-
359
- # In tasks.py
360
- def heavy_task(customer):
361
- # Long running task
362
- process_customer(customer)
363
-
364
- # Enqueue with callback
365
- frappe.enqueue(
366
- method=process_data,
367
- queue="default",
368
- on_success=on_complete,
369
- on_failure=on_error
370
- )
371
-
372
- # Scheduled jobs (in hooks.py)
373
- scheduler_events = {
374
- "daily": [
375
- "myapp.tasks.daily_task"
376
- ],
377
- "hourly": [
378
- "myapp.tasks.hourly_task"
379
- ],
380
- "cron": {
381
- "0 0 * * *": [ # Midnight
382
- "myapp.tasks.midnight_task"
383
- ]
384
- }
385
- }
386
- ```
387
-
388
- ### Session & User
389
-
390
- ```python
391
- # Current user
392
- user = frappe.session.user
393
-
394
- # Check if logged in
395
- if frappe.session.user != "Guest":
396
- pass
397
-
398
- # Check permissions
399
- if frappe.has_permission("Customer", "write"):
400
- pass
401
-
402
- # Get user info
403
- user_doc = frappe.get_doc("User", frappe.session.user)
404
- full_name = frappe.utils.get_fullname(frappe.session.user)
405
-
406
- # Check roles
407
- if "System Manager" in frappe.get_roles():
408
- pass
409
-
410
- # Run as different user
411
- frappe.set_user("Administrator")
412
- # ... do operations
413
- frappe.set_user(original_user)
414
- ```
415
-
416
- ## JavaScript API
417
-
418
- ### Document Operations
419
-
420
- ```javascript
421
- // Get document
422
- frappe.call({
423
- method: 'frappe.client.get',
424
- args: {
425
- doctype: 'Customer',
426
- name: 'CUST-001'
427
- },
428
- callback: function(r) {
429
- console.log(r.message);
430
- }
431
- });
432
-
433
- // Create document
434
- frappe.call({
435
- method: 'frappe.client.insert',
436
- args: {
437
- doc: {
438
- doctype: 'Customer',
439
- customer_name: 'New Customer'
440
- }
441
- },
442
- callback: function(r) {
443
- console.log('Created:', r.message.name);
444
- }
445
- });
446
-
447
- // Save document
448
- frappe.call({
449
- method: 'frappe.client.save',
450
- args: {
451
- doc: cur_frm.doc
452
- }
453
- });
454
-
455
- // Delete document
456
- frappe.call({
457
- method: 'frappe.client.delete',
458
- args: {
459
- doctype: 'Customer',
460
- name: 'CUST-001'
461
- }
462
- });
463
- ```
464
-
465
- ### frappe.call (API Calls)
466
-
467
- ```javascript
468
- // Call whitelisted method
469
- frappe.call({
470
- method: 'myapp.api.get_customer_details',
471
- args: {
472
- customer: 'CUST-001'
473
- },
474
- freeze: true,
475
- freeze_message: 'Loading...',
476
- callback: function(r) {
477
- if (r.message) {
478
- console.log(r.message);
479
- }
480
- },
481
- error: function(r) {
482
- frappe.msgprint('Error occurred');
483
- }
484
- });
485
-
486
- // Async/await pattern
487
- async function getCustomer(name) {
488
- const response = await frappe.call({
489
- method: 'myapp.api.get_customer',
490
- args: { name }
491
- });
492
- return response.message;
493
- }
494
-
495
- // Call with promise
496
- frappe.call({
497
- method: 'myapp.api.process',
498
- args: { data: 'test' }
499
- }).then(r => {
500
- console.log(r.message);
501
- });
502
- ```
503
-
504
- ### Form API (cur_frm)
505
-
506
- ```javascript
507
- frappe.ui.form.on('Sales Invoice', {
508
- refresh: function(frm) {
509
- // Add custom button
510
- frm.add_custom_button('Process', function() {
511
- // Button action
512
- }, 'Actions');
513
-
514
- // Set field properties
515
- frm.set_df_property('field_name', 'read_only', 1);
516
- frm.set_df_property('field_name', 'hidden', 1);
517
- frm.set_df_property('field_name', 'reqd', 1);
518
-
519
- // Set query for link field
520
- frm.set_query('customer', function() {
521
- return {
522
- filters: {
523
- status: 'Active'
524
- }
525
- };
526
- });
527
-
528
- // Toggle fields
529
- frm.toggle_display('field_name', frm.doc.show_field);
530
- frm.toggle_reqd('field_name', frm.doc.is_required);
531
- },
532
-
533
- customer: function(frm) {
534
- // Field change handler
535
- if (frm.doc.customer) {
536
- frappe.call({
537
- method: 'myapp.api.get_customer_details',
538
- args: { customer: frm.doc.customer },
539
- callback: function(r) {
540
- frm.set_value('customer_name', r.message.name);
541
- }
542
- });
543
- }
544
- },
545
-
546
- validate: function(frm) {
547
- // Validate before save
548
- if (!frm.doc.customer) {
549
- frappe.throw('Customer is required');
550
- return false;
551
- }
552
- },
553
-
554
- before_save: function(frm) {
555
- // Before save actions
556
- frm.doc.modified_by_script = 1;
557
- },
558
-
559
- after_save: function(frm) {
560
- // After save actions
561
- frappe.show_alert('Document saved!');
562
- }
563
- });
564
-
565
- // Child table events
566
- frappe.ui.form.on('Sales Invoice Item', {
567
- qty: function(frm, cdt, cdn) {
568
- let row = locals[cdt][cdn];
569
- row.amount = row.qty * row.rate;
570
- frm.refresh_field('items');
571
- },
572
-
573
- items_add: function(frm, cdt, cdn) {
574
- // New row added
575
- let row = locals[cdt][cdn];
576
- row.warehouse = frm.doc.default_warehouse;
577
- },
578
-
579
- items_remove: function(frm) {
580
- // Row removed - recalculate totals
581
- calculate_totals(frm);
582
- }
583
- });
584
- ```
585
-
586
- ### Dialogs
587
-
588
- ```javascript
589
- // Simple prompt
590
- frappe.prompt(
591
- {fieldname: 'name', fieldtype: 'Data', label: 'Name', reqd: 1},
592
- function(values) {
593
- console.log(values.name);
594
- },
595
- 'Enter Name'
596
- );
597
-
598
- // Multiple fields
599
- frappe.prompt([
600
- {fieldname: 'name', fieldtype: 'Data', label: 'Name', reqd: 1},
601
- {fieldname: 'email', fieldtype: 'Data', label: 'Email', options: 'Email'},
602
- {fieldname: 'date', fieldtype: 'Date', label: 'Date', default: frappe.datetime.nowdate()}
603
- ], function(values) {
604
- console.log(values);
605
- }, 'Enter Details', 'Submit');
606
-
607
- // Custom dialog
608
- let dialog = new frappe.ui.Dialog({
609
- title: 'My Dialog',
610
- fields: [
611
- {fieldname: 'customer', fieldtype: 'Link', options: 'Customer', label: 'Customer'},
612
- {fieldname: 'amount', fieldtype: 'Currency', label: 'Amount'}
613
- ],
614
- primary_action_label: 'Submit',
615
- primary_action: function(values) {
616
- console.log(values);
617
- dialog.hide();
618
- }
619
- });
620
- dialog.show();
621
-
622
- // Confirmation
623
- frappe.confirm(
624
- 'Are you sure you want to proceed?',
625
- function() {
626
- // Yes
627
- process_action();
628
- },
629
- function() {
630
- // No
631
- }
632
- );
633
- ```
634
-
635
- ### Utilities
636
-
637
- ```javascript
638
- // Messages
639
- frappe.msgprint('Hello World');
640
- frappe.msgprint({
641
- title: 'Success',
642
- message: 'Operation completed',
643
- indicator: 'green'
644
- });
645
-
646
- frappe.throw('Error message'); // Stops execution
647
-
648
- frappe.show_alert('Quick notification', 5); // 5 seconds
649
-
650
- // Date/time
651
- frappe.datetime.nowdate(); // "2024-01-15"
652
- frappe.datetime.now_datetime(); // "2024-01-15 10:30:00"
653
- frappe.datetime.add_days('2024-01-15', 7);
654
- frappe.datetime.str_to_obj('2024-01-15');
655
-
656
- // Format
657
- frappe.format(1234.56, {fieldtype: 'Currency'});
658
- frappe.format('2024-01-15', {fieldtype: 'Date'});
659
-
660
- // Routing
661
- frappe.set_route('Form', 'Customer', 'CUST-001');
662
- frappe.set_route('List', 'Customer');
663
- frappe.set_route('query-report', 'Sales Report');
664
-
665
- // Current route
666
- let route = frappe.get_route();
667
- ```
668
-
669
- ## REST API
670
-
671
- ### Authentication
672
-
673
- ```bash
674
- # Token-based
675
- curl -X GET "https://site.com/api/resource/Customer" \
676
- -H "Authorization: token api_key:api_secret"
677
-
678
- # Session-based (login first)
679
- curl -X POST "https://site.com/api/method/login" \
680
- -d "usr=user&pwd=password"
681
- ```
682
-
683
- ### CRUD Operations
684
-
685
- ```bash
686
- # List
687
- GET /api/resource/Customer?filters=[["status","=","Active"]]&fields=["name","customer_name"]&limit_page_length=10
688
-
689
- # Get single
690
- GET /api/resource/Customer/CUST-001
691
-
692
- # Create
693
- POST /api/resource/Customer
694
- Content-Type: application/json
695
- {"customer_name": "New Customer", "customer_type": "Company"}
696
-
697
- # Update
698
- PUT /api/resource/Customer/CUST-001
699
- Content-Type: application/json
700
- {"customer_name": "Updated Name"}
701
-
702
- # Delete
703
- DELETE /api/resource/Customer/CUST-001
704
- ```
705
-
706
- ### Call Methods
707
-
708
- ```bash
709
- # Call whitelisted method
710
- POST /api/method/myapp.api.get_customer_details
711
- Content-Type: application/json
712
- {"customer": "CUST-001"}
713
- ```
714
-
715
- ### JavaScript Fetch
716
-
717
- ```javascript
718
- // Using fetch API
719
- async function getCustomers() {
720
- const response = await fetch('/api/resource/Customer?limit_page_length=10', {
721
- headers: {
722
- 'Content-Type': 'application/json'
723
- }
724
- });
725
- const data = await response.json();
726
- return data.data;
727
- }
728
-
729
- // POST request
730
- async function createCustomer(customerData) {
731
- const response = await fetch('/api/resource/Customer', {
732
- method: 'POST',
733
- headers: {
734
- 'Content-Type': 'application/json'
735
- },
736
- body: JSON.stringify(customerData)
737
- });
738
- return response.json();
739
- }
740
- ```