@praxisui/crud 9.0.17 → 9.0.19
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/README.md +42 -0
- package/ai/component-registry.json +11 -4
- package/fesm2022/praxisui-crud.mjs +312 -3
- package/package.json +7 -7
- package/types/praxisui-crud.d.ts +12 -1
package/README.md
CHANGED
|
@@ -17,6 +17,48 @@ Use this package to combine `@praxisui/table`, `@praxisui/dynamic-form`, governe
|
|
|
17
17
|
- Quickstart app: https://github.com/codexrodrigues/praxis-ui-quickstart
|
|
18
18
|
- API quickstart: https://github.com/codexrodrigues/praxis-api-quickstart-public
|
|
19
19
|
|
|
20
|
+
## Public sandbox status
|
|
21
|
+
|
|
22
|
+
CRUD supports untrusted public JSON only through the owner-authored
|
|
23
|
+
`public-local-inspect-only` runtime profile. The profile requires
|
|
24
|
+
`metadata.interactionMode: 'inspect-only'`, inline data, volatile table config,
|
|
25
|
+
and a closed presentation-only table shape. The runtime suppresses implicit and
|
|
26
|
+
explicit CRUD actions, resource discovery, routes, dialogs, drawers, surfaces,
|
|
27
|
+
remote refresh, export, plugins, and operational renderers.
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
const inputs = {
|
|
31
|
+
crudId: 'public-customer-inspection',
|
|
32
|
+
tableConfigPersistenceStrategy: 'volatile',
|
|
33
|
+
enableCustomization: false,
|
|
34
|
+
metadata: {
|
|
35
|
+
component: 'praxis-crud',
|
|
36
|
+
interactionMode: 'inspect-only',
|
|
37
|
+
data: [{ id: 1, name: 'Ada Lovelace', status: 'Ready' }],
|
|
38
|
+
table: {
|
|
39
|
+
columns: [
|
|
40
|
+
{ field: 'name', header: 'Name', sortable: true, filterable: true },
|
|
41
|
+
{ field: 'status', header: 'Status' },
|
|
42
|
+
],
|
|
43
|
+
behavior: {
|
|
44
|
+
localDataMode: { enabled: true },
|
|
45
|
+
pagination: { enabled: true, pageSize: 10, strategy: 'client' },
|
|
46
|
+
sorting: { enabled: true, strategy: 'client' },
|
|
47
|
+
filtering: {
|
|
48
|
+
enabled: true,
|
|
49
|
+
strategy: 'client',
|
|
50
|
+
columnFilters: { enabled: true },
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
toolbar: { visible: true, position: 'top', title: 'Local inspection' },
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
See the accepted runtime decision and adversarial proof matrix in
|
|
60
|
+
[`docs/rfc-public-inspect-only-runtime-profile.md`](docs/rfc-public-inspect-only-runtime-profile.md).
|
|
61
|
+
|
|
20
62
|
## Install
|
|
21
63
|
|
|
22
64
|
```bash
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "1.0.0",
|
|
3
|
-
"generatedAt": "2026-08-
|
|
3
|
+
"generatedAt": "2026-08-25T03:30:16.706Z",
|
|
4
4
|
"packageName": "@praxisui/crud",
|
|
5
|
-
"packageVersion": "9.0.
|
|
5
|
+
"packageVersion": "9.0.19",
|
|
6
6
|
"sourceRegistry": "praxis-component-registry-ingestion",
|
|
7
7
|
"sourceRegistryVersion": "1.0.0",
|
|
8
8
|
"componentCount": 2,
|
|
@@ -17,6 +17,13 @@
|
|
|
17
17
|
"required": false,
|
|
18
18
|
"description": "Metadados de configuração do CRUD (fonte remota via resource.path ou local via metadata.data)."
|
|
19
19
|
},
|
|
20
|
+
{
|
|
21
|
+
"name": "metadata.interactionMode",
|
|
22
|
+
"type": "'interactive' | 'inspect-only'",
|
|
23
|
+
"required": false,
|
|
24
|
+
"description": "Decisão canônica de interação. inspect-only exige dados locais e bloqueia ações, resource binding, surfaces e authoring no próprio runtime.",
|
|
25
|
+
"default": "interactive"
|
|
26
|
+
},
|
|
20
27
|
{
|
|
21
28
|
"name": "crudId",
|
|
22
29
|
"type": "string",
|
|
@@ -7265,9 +7272,9 @@
|
|
|
7265
7272
|
{
|
|
7266
7273
|
"chunkIndex": 0,
|
|
7267
7274
|
"chunkKind": "summary",
|
|
7268
|
-
"content": "Component ID: praxis-crud\nSelector: praxis-crud\nFriendly Name: Praxis CRUD\nDescription: Tabela com operações de CRUD via metadados.\nLib/Package: @praxisui/crud\nTags: widget, crud, configurable, hasWizard, stable\nInputs:\n - metadata (CrudMetadata | string)\n - crudId (string)\n - componentInstanceId (string)\n - tableConfigPersistenceStrategy ('local-first' | 'input-first' | 'volatile')\n - context (Record<string, unknown>)\n - metadata.queryContext (PraxisDataQueryContext | null)\n - metadata.resource.schemaPath (string | null)\n - metadata.resource.title (string | null)\n - metadata.resource.formTitle (string | null)\n - metadata.filterCriteria (Record<string, unknown> | null)\n - metadata.form (FormConfig)\n - metadata.actions[].form (CrudActionFormContract)\n - enableCustomization (boolean)\n - showResourceIdentityKey (boolean)\n - authoringCapability (string | null)\nOutputs:\n - afterOpen ({ mode: FormOpenMode; action: string })\n - afterClose (void)\n - afterSave ({ id: string | number; data: unknown })\n - afterDelete ({ id: string | number })\n - reactiveDeterminationExecuted ({ action: string; event: ReactiveDeterminationExecutionEvent })\n - reactiveDeterminationPendingChange ({ action: string; pending: boolean })\n - reactiveDeterminationStabilityChange (CrudReactiveDeterminationStabilityChange)\n - rowClick ({ row: unknown; index: number })\n - rowAction (CrudActionRuntimeEvent)\n - selectionChange (unknown)\n - resourceEvent (PraxisResourceEvent<unknown>)\n - error (unknown)\n - configureRequested (void)\n - crudAuthoringDocumentApplied (CrudAuthoringWidgetPersistenceEvent)\n - crudAuthoringDocumentSaved (CrudAuthoringWidgetPersistenceEvent)\n",
|
|
7275
|
+
"content": "Component ID: praxis-crud\nSelector: praxis-crud\nFriendly Name: Praxis CRUD\nDescription: Tabela com operações de CRUD via metadados.\nLib/Package: @praxisui/crud\nTags: widget, crud, configurable, hasWizard, stable\nInputs:\n - metadata (CrudMetadata | string)\n - metadata.interactionMode ('interactive' | 'inspect-only')\n - crudId (string)\n - componentInstanceId (string)\n - tableConfigPersistenceStrategy ('local-first' | 'input-first' | 'volatile')\n - context (Record<string, unknown>)\n - metadata.queryContext (PraxisDataQueryContext | null)\n - metadata.resource.schemaPath (string | null)\n - metadata.resource.title (string | null)\n - metadata.resource.formTitle (string | null)\n - metadata.filterCriteria (Record<string, unknown> | null)\n - metadata.form (FormConfig)\n - metadata.actions[].form (CrudActionFormContract)\n - enableCustomization (boolean)\n - showResourceIdentityKey (boolean)\n - authoringCapability (string | null)\nOutputs:\n - afterOpen ({ mode: FormOpenMode; action: string })\n - afterClose (void)\n - afterSave ({ id: string | number; data: unknown })\n - afterDelete ({ id: string | number })\n - reactiveDeterminationExecuted ({ action: string; event: ReactiveDeterminationExecutionEvent })\n - reactiveDeterminationPendingChange ({ action: string; pending: boolean })\n - reactiveDeterminationStabilityChange (CrudReactiveDeterminationStabilityChange)\n - rowClick ({ row: unknown; index: number })\n - rowAction (CrudActionRuntimeEvent)\n - selectionChange (unknown)\n - resourceEvent (PraxisResourceEvent<unknown>)\n - error (unknown)\n - configureRequested (void)\n - crudAuthoringDocumentApplied (CrudAuthoringWidgetPersistenceEvent)\n - crudAuthoringDocumentSaved (CrudAuthoringWidgetPersistenceEvent)\n",
|
|
7269
7276
|
"sourcePointer": "projects/praxis-crud/src/lib/praxis-crud.metadata.ts",
|
|
7270
|
-
"contentHash": "
|
|
7277
|
+
"contentHash": "d9956416f9b8b3d9cbab9a84a3b979a013a31d5ec46c62ec634d8985676b07d6",
|
|
7271
7278
|
"sourceKind": "component_definition",
|
|
7272
7279
|
"sourceId": "praxis-crud",
|
|
7273
7280
|
"corpusVersion": "1.0.0"
|
|
@@ -3870,6 +3870,70 @@ function openCrudMetadataEditor(settings, opts) {
|
|
|
3870
3870
|
});
|
|
3871
3871
|
}
|
|
3872
3872
|
|
|
3873
|
+
const OPERATIONAL_RENDERERS = new Set([
|
|
3874
|
+
'image',
|
|
3875
|
+
'avatar',
|
|
3876
|
+
'link',
|
|
3877
|
+
'button',
|
|
3878
|
+
'menu',
|
|
3879
|
+
'toggle',
|
|
3880
|
+
'html',
|
|
3881
|
+
'compose',
|
|
3882
|
+
]);
|
|
3883
|
+
/** Materializes the effect-free Table projection owned by inspect-only CRUD. */
|
|
3884
|
+
function hardenCrudInspectOnlyTableConfig(config) {
|
|
3885
|
+
const safe = config;
|
|
3886
|
+
safe.behavior = {
|
|
3887
|
+
...(safe.behavior || {}),
|
|
3888
|
+
localDataMode: { ...(safe.behavior?.localDataMode || {}), enabled: true },
|
|
3889
|
+
expansion: { ...(safe.behavior?.expansion || {}), enabled: false },
|
|
3890
|
+
};
|
|
3891
|
+
safe.toolbar = safe.toolbar
|
|
3892
|
+
? { ...safe.toolbar, actions: [] }
|
|
3893
|
+
: { visible: false, position: 'top', actions: [] };
|
|
3894
|
+
safe.actions = {
|
|
3895
|
+
...(safe.actions || {}),
|
|
3896
|
+
row: {
|
|
3897
|
+
position: 'end',
|
|
3898
|
+
display: 'menu',
|
|
3899
|
+
trigger: 'always',
|
|
3900
|
+
...(safe.actions?.row || {}),
|
|
3901
|
+
enabled: false,
|
|
3902
|
+
actions: [],
|
|
3903
|
+
},
|
|
3904
|
+
bulk: {
|
|
3905
|
+
position: 'toolbar',
|
|
3906
|
+
...(safe.actions?.bulk || {}),
|
|
3907
|
+
enabled: false,
|
|
3908
|
+
actions: [],
|
|
3909
|
+
},
|
|
3910
|
+
};
|
|
3911
|
+
safe.export = { formats: [], ...(safe.export || {}), enabled: false };
|
|
3912
|
+
safe.ai = {
|
|
3913
|
+
...(safe.ai || {}),
|
|
3914
|
+
assistant: { ...(safe.ai?.assistant || {}), enabled: false },
|
|
3915
|
+
};
|
|
3916
|
+
safe.columnProjection = undefined;
|
|
3917
|
+
safe.analyticsProjection = undefined;
|
|
3918
|
+
safe.plugins = [];
|
|
3919
|
+
safe.columns = (safe.columns || []).map((column) => {
|
|
3920
|
+
const next = { ...column };
|
|
3921
|
+
if (isOperationalRenderer(next.renderer))
|
|
3922
|
+
next.renderer = undefined;
|
|
3923
|
+
if (Array.isArray(next.conditionalRenderers)) {
|
|
3924
|
+
next.conditionalRenderers = next.conditionalRenderers.map((conditional) => isOperationalRenderer(conditional?.renderer)
|
|
3925
|
+
? { ...conditional, renderer: undefined }
|
|
3926
|
+
: conditional);
|
|
3927
|
+
}
|
|
3928
|
+
return next;
|
|
3929
|
+
});
|
|
3930
|
+
delete safe.resourcePath;
|
|
3931
|
+
return safe;
|
|
3932
|
+
}
|
|
3933
|
+
function isOperationalRenderer(renderer) {
|
|
3934
|
+
return OPERATIONAL_RENDERERS.has(String(renderer?.type || '').trim());
|
|
3935
|
+
}
|
|
3936
|
+
|
|
3873
3937
|
class PraxisCrudComponent {
|
|
3874
3938
|
metadata;
|
|
3875
3939
|
crudId;
|
|
@@ -3970,7 +4034,13 @@ class PraxisCrudComponent {
|
|
|
3970
4034
|
collectionCapabilitiesRequestSeq = 0;
|
|
3971
4035
|
currentAuthoringDocument;
|
|
3972
4036
|
selectedRow = null;
|
|
4037
|
+
get resolvedTableConfigPersistenceStrategy() {
|
|
4038
|
+
return this.isInspectOnly() ? 'volatile' : this.tableConfigPersistenceStrategy;
|
|
4039
|
+
}
|
|
3973
4040
|
onTableRowAction(event) {
|
|
4041
|
+
if (this.isInspectOnly()) {
|
|
4042
|
+
return;
|
|
4043
|
+
}
|
|
3974
4044
|
this.rowAction.emit(event);
|
|
3975
4045
|
void this.onAction(event.action || '', event.row, event);
|
|
3976
4046
|
}
|
|
@@ -3987,6 +4057,9 @@ class PraxisCrudComponent {
|
|
|
3987
4057
|
return assigned ?? (this.surfaceOpenAdapterInstance ??= this.injector.get(ResourceSurfaceOpenAdapterService));
|
|
3988
4058
|
}
|
|
3989
4059
|
onResetPreferences() {
|
|
4060
|
+
if (this.isInspectOnly()) {
|
|
4061
|
+
return;
|
|
4062
|
+
}
|
|
3990
4063
|
try {
|
|
3991
4064
|
const keyId = this.componentKeyId();
|
|
3992
4065
|
if (!keyId)
|
|
@@ -4011,9 +4084,15 @@ class PraxisCrudComponent {
|
|
|
4011
4084
|
this.selectionChange.emit(event);
|
|
4012
4085
|
}
|
|
4013
4086
|
onTableResourceEvent(event) {
|
|
4087
|
+
if (this.isInspectOnly()) {
|
|
4088
|
+
return;
|
|
4089
|
+
}
|
|
4014
4090
|
this.resourceEvent.emit(event);
|
|
4015
4091
|
}
|
|
4016
4092
|
async onBulkAction(event) {
|
|
4093
|
+
if (this.isInspectOnly()) {
|
|
4094
|
+
return;
|
|
4095
|
+
}
|
|
4017
4096
|
const action = String(event?.action || '').trim();
|
|
4018
4097
|
if (!action) {
|
|
4019
4098
|
return;
|
|
@@ -4025,6 +4104,9 @@ class PraxisCrudComponent {
|
|
|
4025
4104
|
await this.onAction(action, row ?? undefined, event);
|
|
4026
4105
|
}
|
|
4027
4106
|
async onToolbarAction(event) {
|
|
4107
|
+
if (this.isInspectOnly()) {
|
|
4108
|
+
return;
|
|
4109
|
+
}
|
|
4028
4110
|
const action = String(event?.action || '').trim();
|
|
4029
4111
|
if (!action)
|
|
4030
4112
|
return;
|
|
@@ -4045,7 +4127,7 @@ class PraxisCrudComponent {
|
|
|
4045
4127
|
? JSON.parse(this.metadata)
|
|
4046
4128
|
: this.metadata;
|
|
4047
4129
|
this.resolvedMetadata = parsed;
|
|
4048
|
-
const externalAuthoringSeed = this.context && typeof this.context === 'object'
|
|
4130
|
+
const externalAuthoringSeed = parsed.interactionMode !== 'inspect-only' && this.context && typeof this.context === 'object'
|
|
4049
4131
|
? (this.context['authoringDocument'] ?? this.context['authoringMetadata'])
|
|
4050
4132
|
: undefined;
|
|
4051
4133
|
this.currentAuthoringDocument = externalAuthoringSeed
|
|
@@ -4057,6 +4139,7 @@ class PraxisCrudComponent {
|
|
|
4057
4139
|
assertCrudMetadata(this.resolvedMetadata, {
|
|
4058
4140
|
allowDeferredActionBindings: true,
|
|
4059
4141
|
});
|
|
4142
|
+
this.emitInspectOnlyDiagnostics(this.resolvedMetadata);
|
|
4060
4143
|
this.tableQueryContext = this.resolveQueryContext(this.resolvedMetadata);
|
|
4061
4144
|
this.tableFilterCriteria = this.resolveFilterCriteria(this.resolvedMetadata);
|
|
4062
4145
|
this.tableCollectionLinks = null;
|
|
@@ -4071,6 +4154,9 @@ class PraxisCrudComponent {
|
|
|
4071
4154
|
}
|
|
4072
4155
|
}
|
|
4073
4156
|
async onAction(action, row, runtimeEvent) {
|
|
4157
|
+
if (this.isInspectOnly()) {
|
|
4158
|
+
return;
|
|
4159
|
+
}
|
|
4074
4160
|
if (this.openingActionLabel()) {
|
|
4075
4161
|
return;
|
|
4076
4162
|
}
|
|
@@ -4248,13 +4334,22 @@ class PraxisCrudComponent {
|
|
|
4248
4334
|
}
|
|
4249
4335
|
}
|
|
4250
4336
|
onTableConfigChange(config) {
|
|
4337
|
+
if (this.isInspectOnly()) {
|
|
4338
|
+
return;
|
|
4339
|
+
}
|
|
4251
4340
|
this.lastTableRuntimeConfigSnapshot = this.cloneTableConfigSnapshot(config);
|
|
4252
4341
|
this.emitTableRuntimeConfigSnapshot(this.lastTableRuntimeConfigSnapshot);
|
|
4253
4342
|
}
|
|
4254
4343
|
onTableMetadataChange() {
|
|
4344
|
+
if (this.isInspectOnly()) {
|
|
4345
|
+
return;
|
|
4346
|
+
}
|
|
4255
4347
|
this.emitTableRuntimeConfigSnapshot();
|
|
4256
4348
|
}
|
|
4257
4349
|
onTableLoadingStateChange(state) {
|
|
4350
|
+
if (this.isInspectOnly()) {
|
|
4351
|
+
return;
|
|
4352
|
+
}
|
|
4258
4353
|
if (!state || state.status !== 'success')
|
|
4259
4354
|
return;
|
|
4260
4355
|
if (state.phase !== 'render' && state.phase !== 'data' && state.phase !== 'schema') {
|
|
@@ -4263,6 +4358,14 @@ class PraxisCrudComponent {
|
|
|
4263
4358
|
this.emitTableRuntimeConfigSnapshot();
|
|
4264
4359
|
}
|
|
4265
4360
|
onCollectionLinksChange(links) {
|
|
4361
|
+
if (this.isInspectOnly()) {
|
|
4362
|
+
this.tableCollectionLinks = null;
|
|
4363
|
+
this.collectionCapabilities = null;
|
|
4364
|
+
this.collectionCapabilitiesRequestSeq += 1;
|
|
4365
|
+
this.collectionCapabilitiesRequestHref = null;
|
|
4366
|
+
this.collectionCapabilitiesResolvedHref = null;
|
|
4367
|
+
return;
|
|
4368
|
+
}
|
|
4266
4369
|
this.tableCollectionLinks = links || null;
|
|
4267
4370
|
const capabilitiesHref = this.resolveCollectionCapabilitiesHref(links);
|
|
4268
4371
|
if (!capabilitiesHref) {
|
|
@@ -4308,6 +4411,9 @@ class PraxisCrudComponent {
|
|
|
4308
4411
|
});
|
|
4309
4412
|
}
|
|
4310
4413
|
resolveResourcePath(meta) {
|
|
4414
|
+
if (this.isInspectOnly(meta)) {
|
|
4415
|
+
return '';
|
|
4416
|
+
}
|
|
4311
4417
|
return (meta?.resource?.path ||
|
|
4312
4418
|
meta?.table?.resourcePath ||
|
|
4313
4419
|
'').trim();
|
|
@@ -4510,6 +4616,9 @@ class PraxisCrudComponent {
|
|
|
4510
4616
|
this.resolveResourcePath(this.resolvedMetadata).length === 0);
|
|
4511
4617
|
}
|
|
4512
4618
|
resolveMaterializedReadUrl() {
|
|
4619
|
+
if (this.isInspectOnly()) {
|
|
4620
|
+
return '';
|
|
4621
|
+
}
|
|
4513
4622
|
const materialization = this.context?.['materialization'];
|
|
4514
4623
|
return String(materialization?.['readUrl'] || '').trim();
|
|
4515
4624
|
}
|
|
@@ -5071,6 +5180,9 @@ class PraxisCrudComponent {
|
|
|
5071
5180
|
? JSON.parse(JSON.stringify(base))
|
|
5072
5181
|
: createDefaultTableConfig();
|
|
5073
5182
|
let changed = false;
|
|
5183
|
+
if (this.isInspectOnly(meta)) {
|
|
5184
|
+
return this.buildInspectOnlyTableConfig(cfg);
|
|
5185
|
+
}
|
|
5074
5186
|
if (nextResourceIdentity !== null &&
|
|
5075
5187
|
nextResourceIdentity === this.lastAppliedResourceIdentity &&
|
|
5076
5188
|
(cfg.columns?.length ?? 0) === 0 &&
|
|
@@ -5271,6 +5383,9 @@ class PraxisCrudComponent {
|
|
|
5271
5383
|
buildTableCrudContext(meta, capabilities) {
|
|
5272
5384
|
if (!meta)
|
|
5273
5385
|
return undefined;
|
|
5386
|
+
if (this.isInspectOnly(meta)) {
|
|
5387
|
+
return undefined;
|
|
5388
|
+
}
|
|
5274
5389
|
const baseActions = this.resolveContextCrudActions(meta, capabilities);
|
|
5275
5390
|
return {
|
|
5276
5391
|
tableId: this.crudId || 'default',
|
|
@@ -5327,6 +5442,9 @@ class PraxisCrudComponent {
|
|
|
5327
5442
|
});
|
|
5328
5443
|
};
|
|
5329
5444
|
isCustomizationAvailable() {
|
|
5445
|
+
if (this.isInspectOnly()) {
|
|
5446
|
+
return false;
|
|
5447
|
+
}
|
|
5330
5448
|
if (!this.enableCustomization) {
|
|
5331
5449
|
return false;
|
|
5332
5450
|
}
|
|
@@ -5368,6 +5486,9 @@ class PraxisCrudComponent {
|
|
|
5368
5486
|
};
|
|
5369
5487
|
}
|
|
5370
5488
|
resolveCreateToolbarAction(meta, capabilities) {
|
|
5489
|
+
if (this.isInspectOnly(meta)) {
|
|
5490
|
+
return null;
|
|
5491
|
+
}
|
|
5371
5492
|
if (capabilities && !this.supportsCreateCapability(capabilities)) {
|
|
5372
5493
|
return null;
|
|
5373
5494
|
}
|
|
@@ -5378,6 +5499,9 @@ class PraxisCrudComponent {
|
|
|
5378
5499
|
return capabilities ? { action: 'create', label: this.getCrudActionLabel('create') } : null;
|
|
5379
5500
|
}
|
|
5380
5501
|
resolveContextCrudActions(meta, capabilities) {
|
|
5502
|
+
if (this.isInspectOnly(meta)) {
|
|
5503
|
+
return [];
|
|
5504
|
+
}
|
|
5381
5505
|
const declaredActions = (meta.actions || []).filter(Boolean);
|
|
5382
5506
|
if (!capabilities) {
|
|
5383
5507
|
return declaredActions.length
|
|
@@ -5431,6 +5555,38 @@ class PraxisCrudComponent {
|
|
|
5431
5555
|
}
|
|
5432
5556
|
return runtimeActions;
|
|
5433
5557
|
}
|
|
5558
|
+
isInspectOnly(meta) {
|
|
5559
|
+
return (meta ?? this.resolvedMetadata)?.interactionMode === 'inspect-only';
|
|
5560
|
+
}
|
|
5561
|
+
buildInspectOnlyTableConfig(config) {
|
|
5562
|
+
return hardenCrudInspectOnlyTableConfig(this.cloneTableConfigSnapshot(config));
|
|
5563
|
+
}
|
|
5564
|
+
emitInspectOnlyDiagnostics(meta) {
|
|
5565
|
+
if (!this.isInspectOnly(meta)) {
|
|
5566
|
+
return;
|
|
5567
|
+
}
|
|
5568
|
+
const incompatiblePaths = [];
|
|
5569
|
+
if (String(meta.resource?.path || '').trim())
|
|
5570
|
+
incompatiblePaths.push('metadata.resource.path');
|
|
5571
|
+
if (String(meta.table?.resourcePath || '').trim()) {
|
|
5572
|
+
incompatiblePaths.push('metadata.table.resourcePath');
|
|
5573
|
+
}
|
|
5574
|
+
if (!Array.isArray(meta.data))
|
|
5575
|
+
incompatiblePaths.push('metadata.data');
|
|
5576
|
+
if ((meta.actions?.length || 0) > 0)
|
|
5577
|
+
incompatiblePaths.push('metadata.actions');
|
|
5578
|
+
if (meta.form)
|
|
5579
|
+
incompatiblePaths.push('metadata.form');
|
|
5580
|
+
if (meta.defaults?.openMode)
|
|
5581
|
+
incompatiblePaths.push('metadata.defaults.openMode');
|
|
5582
|
+
if (incompatiblePaths.length) {
|
|
5583
|
+
this.error.emit({
|
|
5584
|
+
code: 'CRUD_INSPECT_ONLY_INCOMPATIBLE_METADATA',
|
|
5585
|
+
interactionMode: 'inspect-only',
|
|
5586
|
+
paths: incompatiblePaths,
|
|
5587
|
+
});
|
|
5588
|
+
}
|
|
5589
|
+
}
|
|
5434
5590
|
resolveCollectionWorkflowCrudActions(capabilities) {
|
|
5435
5591
|
if (!capabilities) {
|
|
5436
5592
|
return [];
|
|
@@ -5653,7 +5809,7 @@ class PraxisCrudComponent {
|
|
|
5653
5809
|
[queryContext]="tableQueryContext"
|
|
5654
5810
|
[filterCriteria]="tableFilterCriteria"
|
|
5655
5811
|
[tableId]="crudId || 'default'"
|
|
5656
|
-
[configPersistenceStrategy]="
|
|
5812
|
+
[configPersistenceStrategy]="resolvedTableConfigPersistenceStrategy"
|
|
5657
5813
|
[crudContext]="tableCrudContext"
|
|
5658
5814
|
[enableCustomization]="enableCustomization"
|
|
5659
5815
|
[authoringCapability]="authoringCapability"
|
|
@@ -5703,7 +5859,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
5703
5859
|
[queryContext]="tableQueryContext"
|
|
5704
5860
|
[filterCriteria]="tableFilterCriteria"
|
|
5705
5861
|
[tableId]="crudId || 'default'"
|
|
5706
|
-
[configPersistenceStrategy]="
|
|
5862
|
+
[configPersistenceStrategy]="resolvedTableConfigPersistenceStrategy"
|
|
5707
5863
|
[crudContext]="tableCrudContext"
|
|
5708
5864
|
[enableCustomization]="enableCustomization"
|
|
5709
5865
|
[authoringCapability]="authoringCapability"
|
|
@@ -6852,6 +7008,153 @@ const PRAXIS_CRUD_COMPONENT_METADATA = {
|
|
|
6852
7008
|
friendlyName: 'Praxis CRUD',
|
|
6853
7009
|
description: 'Tabela com operações de CRUD via metadados.',
|
|
6854
7010
|
icon: 'table_chart',
|
|
7011
|
+
runtimeProfiles: [
|
|
7012
|
+
{
|
|
7013
|
+
id: 'public-local-inspect-only',
|
|
7014
|
+
audience: 'public-untrusted',
|
|
7015
|
+
description: 'CRUD local somente para inspeção, sem resource binding, persistência, authoring ou ações operacionais.',
|
|
7016
|
+
constraints: [
|
|
7017
|
+
{
|
|
7018
|
+
path: '$',
|
|
7019
|
+
operator: 'keys-subset',
|
|
7020
|
+
values: [
|
|
7021
|
+
'metadata',
|
|
7022
|
+
'crudId',
|
|
7023
|
+
'tableConfigPersistenceStrategy',
|
|
7024
|
+
'enableCustomization',
|
|
7025
|
+
],
|
|
7026
|
+
},
|
|
7027
|
+
{ path: 'crudId', operator: 'present' },
|
|
7028
|
+
{ path: 'tableConfigPersistenceStrategy', operator: 'equals', value: 'volatile' },
|
|
7029
|
+
{ path: 'enableCustomization', operator: 'not-true' },
|
|
7030
|
+
{ path: 'metadata.component', operator: 'equals', value: 'praxis-crud' },
|
|
7031
|
+
{ path: 'metadata.interactionMode', operator: 'equals', value: 'inspect-only' },
|
|
7032
|
+
{ path: 'metadata.data', operator: 'array' },
|
|
7033
|
+
{
|
|
7034
|
+
path: 'metadata',
|
|
7035
|
+
operator: 'keys-subset',
|
|
7036
|
+
values: ['component', 'interactionMode', 'data', 'table'],
|
|
7037
|
+
},
|
|
7038
|
+
{ path: 'metadata.resource', operator: 'absent-or-empty' },
|
|
7039
|
+
{ path: 'metadata.queryContext', operator: 'absent-or-empty' },
|
|
7040
|
+
{ path: 'metadata.filterCriteria', operator: 'absent-or-empty' },
|
|
7041
|
+
{ path: 'metadata.form', operator: 'absent-or-empty' },
|
|
7042
|
+
{ path: 'metadata.defaults', operator: 'absent-or-empty' },
|
|
7043
|
+
{ path: 'metadata.actions', operator: 'empty-array-or-absent' },
|
|
7044
|
+
{ path: 'metadata.i18n', operator: 'absent-or-empty' },
|
|
7045
|
+
{ path: 'metadata.table.columns', operator: 'array' },
|
|
7046
|
+
{
|
|
7047
|
+
path: 'metadata.table',
|
|
7048
|
+
operator: 'keys-subset',
|
|
7049
|
+
values: ['columns', 'behavior', 'toolbar'],
|
|
7050
|
+
},
|
|
7051
|
+
{
|
|
7052
|
+
path: 'metadata.table.columns[*]',
|
|
7053
|
+
operator: 'keys-subset',
|
|
7054
|
+
values: [
|
|
7055
|
+
'field',
|
|
7056
|
+
'header',
|
|
7057
|
+
'type',
|
|
7058
|
+
'width',
|
|
7059
|
+
'visible',
|
|
7060
|
+
'sortable',
|
|
7061
|
+
'filterable',
|
|
7062
|
+
'resizable',
|
|
7063
|
+
'sticky',
|
|
7064
|
+
'align',
|
|
7065
|
+
'order',
|
|
7066
|
+
'sortField',
|
|
7067
|
+
'format',
|
|
7068
|
+
'valueMapping',
|
|
7069
|
+
],
|
|
7070
|
+
},
|
|
7071
|
+
{ path: 'metadata.table.columns[*].renderer', operator: 'absent-or-empty' },
|
|
7072
|
+
{
|
|
7073
|
+
path: 'metadata.table.columns[*].conditionalRenderers',
|
|
7074
|
+
operator: 'absent-or-empty',
|
|
7075
|
+
},
|
|
7076
|
+
{
|
|
7077
|
+
path: 'metadata.table.behavior',
|
|
7078
|
+
operator: 'keys-subset',
|
|
7079
|
+
values: ['localDataMode', 'pagination', 'sorting', 'filtering'],
|
|
7080
|
+
},
|
|
7081
|
+
{ path: 'metadata.table.behavior.localDataMode.enabled', operator: 'equals', value: true },
|
|
7082
|
+
{
|
|
7083
|
+
path: 'metadata.table.behavior.pagination.strategy',
|
|
7084
|
+
operator: 'none-of',
|
|
7085
|
+
values: ['server'],
|
|
7086
|
+
},
|
|
7087
|
+
{
|
|
7088
|
+
path: 'metadata.table.behavior.pagination',
|
|
7089
|
+
operator: 'keys-subset',
|
|
7090
|
+
values: [
|
|
7091
|
+
'enabled',
|
|
7092
|
+
'pageSize',
|
|
7093
|
+
'pageSizeOptions',
|
|
7094
|
+
'showFirstLastButtons',
|
|
7095
|
+
'showPageNumbers',
|
|
7096
|
+
'showPageInfo',
|
|
7097
|
+
'position',
|
|
7098
|
+
'style',
|
|
7099
|
+
'totalItems',
|
|
7100
|
+
'strategy',
|
|
7101
|
+
],
|
|
7102
|
+
},
|
|
7103
|
+
{ path: 'metadata.table.behavior.pagination.advanced', operator: 'absent-or-empty' },
|
|
7104
|
+
{
|
|
7105
|
+
path: 'metadata.table.behavior.sorting.strategy',
|
|
7106
|
+
operator: 'none-of',
|
|
7107
|
+
values: ['server'],
|
|
7108
|
+
},
|
|
7109
|
+
{
|
|
7110
|
+
path: 'metadata.table.behavior.sorting',
|
|
7111
|
+
operator: 'keys-subset',
|
|
7112
|
+
values: [
|
|
7113
|
+
'enabled',
|
|
7114
|
+
'defaultSort',
|
|
7115
|
+
'multiSort',
|
|
7116
|
+
'strategy',
|
|
7117
|
+
'showSortIndicators',
|
|
7118
|
+
'indicatorPosition',
|
|
7119
|
+
'allowClearSort',
|
|
7120
|
+
],
|
|
7121
|
+
},
|
|
7122
|
+
{ path: 'metadata.table.behavior.sorting.advanced', operator: 'absent-or-empty' },
|
|
7123
|
+
{
|
|
7124
|
+
path: 'metadata.table.behavior.filtering.strategy',
|
|
7125
|
+
operator: 'none-of',
|
|
7126
|
+
values: ['server'],
|
|
7127
|
+
},
|
|
7128
|
+
{
|
|
7129
|
+
path: 'metadata.table.behavior.filtering',
|
|
7130
|
+
operator: 'keys-subset',
|
|
7131
|
+
values: ['enabled', 'columnFilters', 'strategy', 'debounceTime'],
|
|
7132
|
+
},
|
|
7133
|
+
{
|
|
7134
|
+
path: 'metadata.table.behavior.filtering.columnFilters',
|
|
7135
|
+
operator: 'keys-subset',
|
|
7136
|
+
values: ['enabled', 'defaultType', 'position'],
|
|
7137
|
+
},
|
|
7138
|
+
{
|
|
7139
|
+
path: 'metadata.table.behavior.filtering.advancedFilters',
|
|
7140
|
+
operator: 'absent-or-empty',
|
|
7141
|
+
},
|
|
7142
|
+
{
|
|
7143
|
+
path: 'metadata.table.toolbar',
|
|
7144
|
+
operator: 'keys-subset',
|
|
7145
|
+
values: ['visible', 'position', 'title', 'subtitle', 'icon', 'textAlign'],
|
|
7146
|
+
},
|
|
7147
|
+
{ path: 'metadata.table.toolbar.actions', operator: 'empty-array-or-absent' },
|
|
7148
|
+
{ path: 'metadata.table.actions', operator: 'absent-or-empty' },
|
|
7149
|
+
{ path: 'metadata.table.export', operator: 'absent-or-empty' },
|
|
7150
|
+
{ path: 'metadata.table.ai', operator: 'absent-or-empty' },
|
|
7151
|
+
{ path: 'metadata.table.columnProjection', operator: 'absent-or-empty' },
|
|
7152
|
+
{ path: 'metadata.table.analyticsProjection', operator: 'absent-or-empty' },
|
|
7153
|
+
{ path: 'metadata.table.plugins', operator: 'empty-array-or-absent' },
|
|
7154
|
+
],
|
|
7155
|
+
effects: [],
|
|
7156
|
+
},
|
|
7157
|
+
],
|
|
6855
7158
|
authoringManifestRef: {
|
|
6856
7159
|
componentId: 'praxis-crud',
|
|
6857
7160
|
source: 'PRAXIS_CRUD_AUTHORING_MANIFEST',
|
|
@@ -6866,6 +7169,12 @@ const PRAXIS_CRUD_COMPONENT_METADATA = {
|
|
|
6866
7169
|
type: 'CrudMetadata | string',
|
|
6867
7170
|
description: 'Metadados de configuração do CRUD (fonte remota via resource.path ou local via metadata.data).',
|
|
6868
7171
|
},
|
|
7172
|
+
{
|
|
7173
|
+
name: 'metadata.interactionMode',
|
|
7174
|
+
type: "'interactive' | 'inspect-only'",
|
|
7175
|
+
default: 'interactive',
|
|
7176
|
+
description: 'Decisão canônica de interação. inspect-only exige dados locais e bloqueia ações, resource binding, surfaces e authoring no próprio runtime.',
|
|
7177
|
+
},
|
|
6869
7178
|
{
|
|
6870
7179
|
name: 'crudId',
|
|
6871
7180
|
type: 'string',
|
package/package.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@praxisui/crud",
|
|
3
|
-
"version": "9.0.
|
|
3
|
+
"version": "9.0.19",
|
|
4
4
|
"description": "CRUD building blocks for Praxis UI: integrates dynamic forms and tables with unified configuration and services.",
|
|
5
5
|
"peerDependencies": {
|
|
6
6
|
"@angular/common": "^21.0.0",
|
|
7
7
|
"@angular/core": "^21.0.0",
|
|
8
|
-
"@praxisui/dynamic-form": "^9.0.
|
|
9
|
-
"@praxisui/table": "^9.0.
|
|
10
|
-
"@praxisui/core": "^9.0.
|
|
11
|
-
"@praxisui/dynamic-fields": "^9.0.
|
|
12
|
-
"@praxisui/settings-panel": "^9.0.
|
|
8
|
+
"@praxisui/dynamic-form": "^9.0.19",
|
|
9
|
+
"@praxisui/table": "^9.0.19",
|
|
10
|
+
"@praxisui/core": "^9.0.19",
|
|
11
|
+
"@praxisui/dynamic-fields": "^9.0.19",
|
|
12
|
+
"@praxisui/settings-panel": "^9.0.19",
|
|
13
13
|
"@angular/cdk": "^21.0.0",
|
|
14
14
|
"@angular/forms": "^21.0.0",
|
|
15
15
|
"@angular/material": "^21.0.0",
|
|
16
16
|
"@angular/router": "^21.0.0",
|
|
17
|
-
"@praxisui/ai": "^9.0.
|
|
17
|
+
"@praxisui/ai": "^9.0.19",
|
|
18
18
|
"rxjs": "~7.8.0"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
package/types/praxisui-crud.d.ts
CHANGED
|
@@ -48,6 +48,7 @@ declare class DialogService {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
type FormOpenMode = 'route' | 'modal' | 'drawer';
|
|
51
|
+
type CrudInteractionMode = 'interactive' | 'inspect-only';
|
|
51
52
|
type CrudReactiveDeterminationStabilityStatus = 'pending' | 'settled-satisfied' | 'settled-unsatisfied';
|
|
52
53
|
/** Value-free stability evidence for the Dynamic Form opened by one CRUD action. */
|
|
53
54
|
interface CrudFormReactiveDeterminationStabilityChange {
|
|
@@ -101,6 +102,12 @@ interface CrudResource {
|
|
|
101
102
|
}
|
|
102
103
|
interface CrudMetadata {
|
|
103
104
|
component: 'praxis-crud';
|
|
105
|
+
/**
|
|
106
|
+
* Governs whether the CRUD may materialize operational actions.
|
|
107
|
+
* `interactive` preserves the historical behavior; `inspect-only` is
|
|
108
|
+
* fail-closed and only materializes local, non-operational inspection.
|
|
109
|
+
*/
|
|
110
|
+
interactionMode?: CrudInteractionMode;
|
|
104
111
|
resource?: CrudResource;
|
|
105
112
|
data?: any[] | null;
|
|
106
113
|
table: TableConfig;
|
|
@@ -270,6 +277,7 @@ declare class PraxisCrudComponent implements OnChanges {
|
|
|
270
277
|
private collectionCapabilitiesRequestSeq;
|
|
271
278
|
private currentAuthoringDocument?;
|
|
272
279
|
selectedRow: Record<string, unknown> | null;
|
|
280
|
+
get resolvedTableConfigPersistenceStrategy(): TableConfigPersistenceStrategy;
|
|
273
281
|
onTableRowAction(event: CrudActionRuntimeEvent): void;
|
|
274
282
|
private getResourceDiscovery;
|
|
275
283
|
private getActionOpenAdapter;
|
|
@@ -359,6 +367,9 @@ declare class PraxisCrudComponent implements OnChanges {
|
|
|
359
367
|
private buildWidgetPersistencePayload;
|
|
360
368
|
private resolveCreateToolbarAction;
|
|
361
369
|
private resolveContextCrudActions;
|
|
370
|
+
private isInspectOnly;
|
|
371
|
+
private buildInspectOnlyTableConfig;
|
|
372
|
+
private emitInspectOnlyDiagnostics;
|
|
362
373
|
private resolveCollectionWorkflowCrudActions;
|
|
363
374
|
private resolveCollectionWorkflowToolbarActions;
|
|
364
375
|
private supportsCreateCapability;
|
|
@@ -851,4 +862,4 @@ type OpenCrudMetadataEditorOptions = {
|
|
|
851
862
|
declare function openCrudMetadataEditor(settings: SettingsPanelService, opts?: OpenCrudMetadataEditorOptions): _praxisui_settings_panel.SettingsPanelRef;
|
|
852
863
|
|
|
853
864
|
export { CRUD_AI_CAPABILITIES, CrudLauncherService, CrudMetadataEditorComponent, CrudPageHeaderComponent, DialogService, DynamicFormDialogHostComponent, PRAXIS_CRUD_AUTHORING_MANIFEST, PRAXIS_CRUD_COMPONENT_METADATA, PraxisCrudComponent, PraxisCrudWidgetConfigEditor, assertCrudMetadata, createCrudAuthoringDocument, findCrudAction, normalizeCrudAuthoringDocument, openCrudMetadataEditor, parseLegacyOrCrudDocument, providePraxisCrudMetadata, serializeCrudAuthoringDocument, validateCrudAuthoringDocument };
|
|
854
|
-
export type { Capability, CapabilityCatalog, CapabilityCategory, CrudAction, CrudActionFormContract, CrudActionResolutionMode, CrudAuthoringDocument, CrudAuthoringWidgetPersistenceEvent, CrudDefaults, CrudEditorDiagnostic, CrudFormReactiveDeterminationStabilityChange, CrudHeaderConfig, CrudHeaderVariant, CrudMetadata, CrudMetadataAssertionOptions, CrudParamMapping, CrudReactiveDeterminationStabilityChange, CrudReactiveDeterminationStabilityStatus, CrudResource, CrudValidationContext, DialogConfig, DialogRef, FormOpenMode, OpenCrudMetadataEditorOptions, PraxisCrudWidgetEditorInputs, PraxisCrudWidgetEditorValue, ValueKind };
|
|
865
|
+
export type { Capability, CapabilityCatalog, CapabilityCategory, CrudAction, CrudActionFormContract, CrudActionResolutionMode, CrudAuthoringDocument, CrudAuthoringWidgetPersistenceEvent, CrudDefaults, CrudEditorDiagnostic, CrudFormReactiveDeterminationStabilityChange, CrudHeaderConfig, CrudHeaderVariant, CrudInteractionMode, CrudMetadata, CrudMetadataAssertionOptions, CrudParamMapping, CrudReactiveDeterminationStabilityChange, CrudReactiveDeterminationStabilityStatus, CrudResource, CrudValidationContext, DialogConfig, DialogRef, FormOpenMode, OpenCrudMetadataEditorOptions, PraxisCrudWidgetEditorInputs, PraxisCrudWidgetEditorValue, ValueKind };
|