@open-mercato/shared 0.4.7-develop-74069040de → 0.4.7-develop-7116871242
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.
- package/agentic/standalone-guide.md +108 -0
- package/dist/lib/version.js +1 -1
- package/dist/lib/version.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Shared Package — Standalone Developer Guide
|
|
2
|
+
|
|
3
|
+
`@open-mercato/shared` provides cross-cutting utilities, types, and DSL helpers. Import from here for infrastructure concerns — never from `@open-mercato/core`.
|
|
4
|
+
|
|
5
|
+
## Import Map
|
|
6
|
+
|
|
7
|
+
| Need | Import |
|
|
8
|
+
|------|--------|
|
|
9
|
+
| Client-side translations | `import { useT } from '@open-mercato/shared/lib/i18n/context'` |
|
|
10
|
+
| Server-side translations | `import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'` |
|
|
11
|
+
| Encrypted queries | `import { findWithDecryption, findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'` |
|
|
12
|
+
| Boolean parsing | `import { parseBooleanToken, parseBooleanWithDefault } from '@open-mercato/shared/lib/boolean'` |
|
|
13
|
+
| Command pattern | `import { registerCommand } from '@open-mercato/shared/lib/commands'` |
|
|
14
|
+
| Safe entity flush | `import { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'` |
|
|
15
|
+
| Data/Query engine types | `import type { DataEngine, QueryEngine } from '@open-mercato/shared/lib/data/engine'` |
|
|
16
|
+
| CRUD multi-ID filtering | `import { parseIdsParam, mergeIdFilter } from '@open-mercato/shared/lib/crud/ids'` |
|
|
17
|
+
| CRUD OpenAPI factory | `import { createCrudOpenApiFactory } from '@open-mercato/shared/lib/openapi/crud'` |
|
|
18
|
+
| Scoped API payloads | `import { withScopedPayload } from '@open-mercato/shared/lib/api/scoped'` |
|
|
19
|
+
| DI setup (Awilix) | `import { ... } from '@open-mercato/shared/lib/di'` |
|
|
20
|
+
| Custom field helpers | `import { splitCustomFieldPayload, normalizeCustomFieldValues } from '@open-mercato/shared/lib/custom-fields'` |
|
|
21
|
+
| DSL helpers | `import { defineLink, entityId, cf } from '@open-mercato/shared/modules/dsl'` |
|
|
22
|
+
| Event declarations | `import { createModuleEvents } from '@open-mercato/shared/modules/events'` |
|
|
23
|
+
| Module setup types | `import type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'` |
|
|
24
|
+
| Search config types | `import type { SearchModuleConfig } from '@open-mercato/shared/modules/search'` |
|
|
25
|
+
| Widget injection position | `import { InjectionPosition } from '@open-mercato/shared/modules/widgets/injection-position'` |
|
|
26
|
+
| API interceptor types | `import type { ApiInterceptor } from '@open-mercato/shared/lib/crud/api-interceptor'` |
|
|
27
|
+
| Response enricher types | `import type { ResponseEnricher } from '@open-mercato/shared/lib/crud/response-enricher'` |
|
|
28
|
+
| Broadcast event check | `import { isBroadcastEvent } from '@open-mercato/shared/modules/events'` |
|
|
29
|
+
|
|
30
|
+
## i18n — All User-Facing Strings
|
|
31
|
+
|
|
32
|
+
Never hard-code user-facing text. Use locale files and translation helpers.
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
// Client-side (React components)
|
|
36
|
+
const t = useT()
|
|
37
|
+
return <span>{t('my_module.labels.title')}</span>
|
|
38
|
+
|
|
39
|
+
// Server-side (API routes, commands)
|
|
40
|
+
const { t } = await resolveTranslations()
|
|
41
|
+
const label = t('my_module.labels.title')
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Add translations to `i18n/<locale>.json` files in your module.
|
|
45
|
+
|
|
46
|
+
## Encryption — Query Encrypted Entities
|
|
47
|
+
|
|
48
|
+
MUST use these instead of raw `em.find`/`em.findOne` when the entity may contain encrypted fields:
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
const results = await findWithDecryption(em, 'Entity', filter, { tenantId, organizationId })
|
|
52
|
+
const record = await findOneWithDecryption(em, 'Entity', filter, { tenantId, organizationId })
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Boolean Parsing
|
|
56
|
+
|
|
57
|
+
For env vars and query params, never use `=== 'true'`:
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
const isEnabled = parseBooleanToken(process.env.MY_FLAG) // true | false | undefined
|
|
61
|
+
const withDefault = parseBooleanWithDefault(query.active, true) // defaults to true
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Safe Entity Flush
|
|
65
|
+
|
|
66
|
+
When a command mutates entities across phases that include queries on the same `EntityManager`, use `withAtomicFlush` to prevent silent data loss:
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
import { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'
|
|
70
|
+
|
|
71
|
+
await withAtomicFlush(em, [
|
|
72
|
+
() => { record.name = 'New'; record.status = 'active' },
|
|
73
|
+
() => syncEntityTags(em, record, tags), // internal em.find() won't lose changes
|
|
74
|
+
], { transaction: true })
|
|
75
|
+
|
|
76
|
+
// Side effects AFTER the atomic flush
|
|
77
|
+
await emitCrudSideEffects({ ... })
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**Never** run `em.find`/`em.findOne` between scalar mutations and `em.flush()` without `withAtomicFlush`.
|
|
81
|
+
|
|
82
|
+
## CRUD Multi-ID Filtering
|
|
83
|
+
|
|
84
|
+
Filter list APIs by multiple IDs using `?ids=uuid1,uuid2`:
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
import { parseIdsParam, mergeIdFilter } from '@open-mercato/shared/lib/crud/ids'
|
|
88
|
+
const ids = parseIdsParam(query.ids) // string[] | undefined
|
|
89
|
+
const filter = mergeIdFilter(existingFilter, ids) // intersects with existing id filter
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Custom Field Helpers
|
|
93
|
+
|
|
94
|
+
When your entity uses custom fields:
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
import { splitCustomFieldPayload, normalizeCustomFieldValues, normalizeCustomFieldResponse }
|
|
98
|
+
from '@open-mercato/shared/lib/custom-fields'
|
|
99
|
+
|
|
100
|
+
// In create/update: split cf:* fields from standard fields
|
|
101
|
+
const { standard, custom } = splitCustomFieldPayload(body)
|
|
102
|
+
|
|
103
|
+
// Normalize for storage
|
|
104
|
+
const normalized = normalizeCustomFieldValues(custom, fieldDefinitions)
|
|
105
|
+
|
|
106
|
+
// Normalize for API response
|
|
107
|
+
const response = normalizeCustomFieldResponse(record, customFields)
|
|
108
|
+
```
|
package/dist/lib/version.js
CHANGED
package/dist/lib/version.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/version.ts"],
|
|
4
|
-
"sourcesContent": ["// Build-time generated version\nexport const APP_VERSION = '0.4.7-develop-
|
|
4
|
+
"sourcesContent": ["// Build-time generated version\nexport const APP_VERSION = '0.4.7-develop-7116871242'\nexport const appVersion = APP_VERSION\n"],
|
|
5
5
|
"mappings": "AACO,MAAM,cAAc;AACpB,MAAM,aAAa;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|