@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.
@@ -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
+ ```
@@ -1,4 +1,4 @@
1
- const APP_VERSION = "0.4.7-develop-74069040de";
1
+ const APP_VERSION = "0.4.7-develop-7116871242";
2
2
  const appVersion = APP_VERSION;
3
3
  export {
4
4
  APP_VERSION,
@@ -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-74069040de'\nexport const appVersion = APP_VERSION\n"],
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/shared",
3
- "version": "0.4.7-develop-74069040de",
3
+ "version": "0.4.7-develop-7116871242",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {