@shamar/adonis 0.1.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 (134) hide show
  1. package/assets/admin.css +2 -0
  2. package/assets/alpine.min.js +5 -0
  3. package/assets/input.css +2286 -0
  4. package/assets/shamar-ui.js +3658 -0
  5. package/dist/assets-controller.d.ts +12 -0
  6. package/dist/assets-controller.d.ts.map +1 -0
  7. package/dist/assets-controller.js +32 -0
  8. package/dist/assets-controller.js.map +1 -0
  9. package/dist/config.d.ts +79 -0
  10. package/dist/config.d.ts.map +1 -0
  11. package/dist/config.js +38 -0
  12. package/dist/config.js.map +1 -0
  13. package/dist/configure.d.ts +21 -0
  14. package/dist/configure.d.ts.map +1 -0
  15. package/dist/configure.js +20 -0
  16. package/dist/configure.js.map +1 -0
  17. package/dist/context.d.ts +22 -0
  18. package/dist/context.d.ts.map +1 -0
  19. package/dist/context.js +2 -0
  20. package/dist/context.js.map +1 -0
  21. package/dist/controller.d.ts +31 -0
  22. package/dist/controller.d.ts.map +1 -0
  23. package/dist/controller.js +45 -0
  24. package/dist/controller.js.map +1 -0
  25. package/dist/controllers/admin_controller.d.ts +72 -0
  26. package/dist/controllers/admin_controller.d.ts.map +1 -0
  27. package/dist/controllers/admin_controller.js +1075 -0
  28. package/dist/controllers/admin_controller.js.map +1 -0
  29. package/dist/discover.d.ts +7 -0
  30. package/dist/discover.d.ts.map +1 -0
  31. package/dist/discover.js +50 -0
  32. package/dist/discover.js.map +1 -0
  33. package/dist/form-state.d.ts +41 -0
  34. package/dist/form-state.d.ts.map +1 -0
  35. package/dist/form-state.js +74 -0
  36. package/dist/form-state.js.map +1 -0
  37. package/dist/index.d.ts +10 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +10 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/middleware/require_api_key_middleware.d.ts +30 -0
  42. package/dist/middleware/require_api_key_middleware.d.ts.map +1 -0
  43. package/dist/middleware/require_api_key_middleware.js +59 -0
  44. package/dist/middleware/require_api_key_middleware.js.map +1 -0
  45. package/dist/provider.d.ts +9 -0
  46. package/dist/provider.d.ts.map +1 -0
  47. package/dist/provider.js +66 -0
  48. package/dist/provider.js.map +1 -0
  49. package/dist/resources/api_key_resource.d.ts +35 -0
  50. package/dist/resources/api_key_resource.d.ts.map +1 -0
  51. package/dist/resources/api_key_resource.js +225 -0
  52. package/dist/resources/api_key_resource.js.map +1 -0
  53. package/dist/routes.d.ts +5 -0
  54. package/dist/routes.d.ts.map +1 -0
  55. package/dist/routes.js +97 -0
  56. package/dist/routes.js.map +1 -0
  57. package/dist/runtime.d.ts +27 -0
  58. package/dist/runtime.d.ts.map +1 -0
  59. package/dist/runtime.js +74 -0
  60. package/dist/runtime.js.map +1 -0
  61. package/dist/shamar/auth.d.ts +30 -0
  62. package/dist/shamar/auth.d.ts.map +1 -0
  63. package/dist/shamar/auth.js +218 -0
  64. package/dist/shamar/auth.js.map +1 -0
  65. package/dist/shamar/branding.d.ts +24 -0
  66. package/dist/shamar/branding.d.ts.map +1 -0
  67. package/dist/shamar/branding.js +91 -0
  68. package/dist/shamar/branding.js.map +1 -0
  69. package/dist/shamar/display-relations.d.ts +7 -0
  70. package/dist/shamar/display-relations.d.ts.map +1 -0
  71. package/dist/shamar/display-relations.js +89 -0
  72. package/dist/shamar/display-relations.js.map +1 -0
  73. package/dist/shamar/list-headers.d.ts +38 -0
  74. package/dist/shamar/list-headers.d.ts.map +1 -0
  75. package/dist/shamar/list-headers.js +218 -0
  76. package/dist/shamar/list-headers.js.map +1 -0
  77. package/dist/shamar/list-query.d.ts +229 -0
  78. package/dist/shamar/list-query.d.ts.map +1 -0
  79. package/dist/shamar/list-query.js +564 -0
  80. package/dist/shamar/list-query.js.map +1 -0
  81. package/dist/shamar/menu.d.ts +48 -0
  82. package/dist/shamar/menu.d.ts.map +1 -0
  83. package/dist/shamar/menu.js +93 -0
  84. package/dist/shamar/menu.js.map +1 -0
  85. package/dist/shamar/paths.d.ts +5 -0
  86. package/dist/shamar/paths.d.ts.map +1 -0
  87. package/dist/shamar/paths.js +16 -0
  88. package/dist/shamar/paths.js.map +1 -0
  89. package/dist/shamar/relation-fields.d.ts +54 -0
  90. package/dist/shamar/relation-fields.d.ts.map +1 -0
  91. package/dist/shamar/relation-fields.js +94 -0
  92. package/dist/shamar/relation-fields.js.map +1 -0
  93. package/dist/shamar/resource-actions.d.ts +9 -0
  94. package/dist/shamar/resource-actions.d.ts.map +1 -0
  95. package/dist/shamar/resource-actions.js +42 -0
  96. package/dist/shamar/resource-actions.js.map +1 -0
  97. package/dist/shamar/view-context.d.ts +79 -0
  98. package/dist/shamar/view-context.d.ts.map +1 -0
  99. package/dist/shamar/view-context.js +74 -0
  100. package/dist/shamar/view-context.js.map +1 -0
  101. package/dist/types.d.ts +15 -0
  102. package/dist/types.d.ts.map +1 -0
  103. package/dist/types.js +2 -0
  104. package/dist/types.js.map +1 -0
  105. package/package.json +67 -0
  106. package/resources/views/shamar/dashboard.edge +24 -0
  107. package/resources/views/shamar/form.edge +87 -0
  108. package/resources/views/shamar/index.edge +149 -0
  109. package/resources/views/shamar/partials/boolean-value.edge +25 -0
  110. package/resources/views/shamar/partials/csrf.edge +1 -0
  111. package/resources/views/shamar/partials/detail-entry.edge +72 -0
  112. package/resources/views/shamar/partials/dialog-host.edge +125 -0
  113. package/resources/views/shamar/partials/field-affix-icon.edge +23 -0
  114. package/resources/views/shamar/partials/field-input.edge +585 -0
  115. package/resources/views/shamar/partials/field-relation-checkbox.edge +104 -0
  116. package/resources/views/shamar/partials/field-relation-m2m.edge +110 -0
  117. package/resources/views/shamar/partials/field-relation-m2o.edge +116 -0
  118. package/resources/views/shamar/partials/field-relation-table.edge +139 -0
  119. package/resources/views/shamar/partials/form-container.edge +82 -0
  120. package/resources/views/shamar/partials/icon.edge +14 -0
  121. package/resources/views/shamar/partials/list-row.edge +73 -0
  122. package/resources/views/shamar/partials/list-toolbar.edge +269 -0
  123. package/resources/views/shamar/partials/nav-mobile.edge +21 -0
  124. package/resources/views/shamar/partials/nav.edge +58 -0
  125. package/resources/views/shamar/partials/page-heading.edge +130 -0
  126. package/resources/views/shamar/partials/pagination.edge +73 -0
  127. package/resources/views/shamar/partials/record-pager.edge +37 -0
  128. package/resources/views/shamar/partials/schema-node.edge +289 -0
  129. package/resources/views/shamar/partials/shell-close.edge +20 -0
  130. package/resources/views/shamar/partials/shell-open.edge +51 -0
  131. package/resources/views/shamar/partials/toast.edge +5 -0
  132. package/resources/views/shamar/partials/topbar.edge +115 -0
  133. package/resources/views/shamar/show.edge +17 -0
  134. package/stubs/config/shamar.stub +29 -0
@@ -0,0 +1,225 @@
1
+ import { Resource, form, table, infolist, actions, Section, TextInput, Textarea, Select, DatePicker, AbilitiesAssignment, TextColumn, TextEntry, ValidationException, } from '@shamar/core';
2
+ import { generateApiKey } from '@shamar/cherubim';
3
+ /**
4
+ * ORM-agnostic API credentials resource (PATs + machine keys).
5
+ *
6
+ * Apps bind their model: `class AppApiKeyResource extends ApiKeyResource { static model = ApiKey }`
7
+ *
8
+ * Create generates a one-time secret (shown once). Editing credentials is disabled;
9
+ * admins can deactivate / reactivate (and delete) instead.
10
+ * Abilities are picked from the registered `permissions` catalog by name.
11
+ */
12
+ export default class ApiKeyResource extends Resource {
13
+ /** Keep as `ResourceModel` so apps can override with a Lucid/Mongoose model class. */
14
+ static model = 'ApiKey';
15
+ static slug = 'api-keys';
16
+ static label = 'API Keys';
17
+ static singularLabel = 'API Key';
18
+ static recordTitleField = 'name';
19
+ static navigationGroup = 'System';
20
+ static navigationSort = 8;
21
+ static icon = 'key';
22
+ static canAccess(_user) {
23
+ return true;
24
+ }
25
+ static canViewAny(_user) {
26
+ return true;
27
+ }
28
+ static canView(_user, _record) {
29
+ return true;
30
+ }
31
+ static canCreate(_user) {
32
+ return true;
33
+ }
34
+ /** Secrets are create-once — use Deactivate / Reactivate instead of edit. */
35
+ static canEdit(_user, _record) {
36
+ return false;
37
+ }
38
+ static canDelete(_user, _record) {
39
+ return true;
40
+ }
41
+ static resourceActions() {
42
+ return actions((a) => {
43
+ a.create();
44
+ a.view();
45
+ a.delete().confirm('Permanently delete this API key? This cannot be undone.');
46
+ a.bulkDelete('Delete selected').confirm('Permanently delete %d selected API key(s)?');
47
+ a
48
+ .row('revoke', 'Deactivate')
49
+ .color('danger')
50
+ .confirm('Deactivate this API key? It will stop working immediately.')
51
+ .ability('delete');
52
+ a
53
+ .row('reactivate', 'Reactivate')
54
+ .confirm('Reactivate this API key?')
55
+ .ability('delete');
56
+ a
57
+ .bulk('revoke', 'Deactivate selected')
58
+ .color('danger')
59
+ .confirm('Deactivate %d selected API key(s)?')
60
+ .ability('delete');
61
+ });
62
+ }
63
+ static form() {
64
+ return form((f) => {
65
+ f.schema([
66
+ Section.make('Credential')
67
+ .columns(2)
68
+ .schema([
69
+ TextInput.make('name').required().searchable().columnSpanFull(),
70
+ Textarea.make('description')
71
+ .rows(3)
72
+ .columnSpanFull()
73
+ .helperText('Optional note about what this credential is for.'),
74
+ Select.make('kind')
75
+ .label('Type')
76
+ .options([
77
+ { label: 'Machine API key', value: 'machine' },
78
+ { label: 'Personal access token', value: 'pat' },
79
+ ])
80
+ .default('machine')
81
+ .required()
82
+ .live()
83
+ .helperText('Machine keys are standalone principals. PATs act as the selected user.'),
84
+ Select.make('userId')
85
+ .label('User')
86
+ .relationship('users', 'email')
87
+ .visible(({ get }) => get('kind') === 'pat')
88
+ .required(({ get }) => get('kind') === 'pat')
89
+ .helperText('Required for personal access tokens.'),
90
+ AbilitiesAssignment.make('abilities').helperText('Machine: permissions for the key (default * when empty). PAT: optional narrow of the user’s permissions.'),
91
+ DatePicker.make('expiresAt').label('Expires at (optional)'),
92
+ ]),
93
+ ]);
94
+ });
95
+ }
96
+ static table() {
97
+ return table((t) => {
98
+ t.defaultSort('createdAt', 'desc')
99
+ .defaultFilters([{ field: 'kind', value: 'machine' }])
100
+ .schema([
101
+ TextColumn.make('name').searchable().sortable(),
102
+ TextColumn.make('description'),
103
+ TextColumn.make('kind').label('Type').sortable().filterable().groupable(),
104
+ TextColumn.make('tokenPrefix').label('Prefix'),
105
+ TextColumn.make('status').label('Status').badge(),
106
+ TextColumn.make('user.email').label('User'),
107
+ TextColumn.make('lastUsedAt').dateTime().label('Last used'),
108
+ TextColumn.make('expiresAt').dateTime().label('Expires'),
109
+ ]);
110
+ });
111
+ }
112
+ static infolist() {
113
+ return infolist((i) => {
114
+ i.schema([
115
+ Section.make('Credential')
116
+ .columns(2)
117
+ .schema([
118
+ TextEntry.make('name').columnSpanFull(),
119
+ TextEntry.make('description').columnSpanFull(),
120
+ TextEntry.make('kind').label('Type'),
121
+ TextEntry.make('status').label('Status').badge(),
122
+ TextEntry.make('tokenPrefix').label('Prefix').copyable(),
123
+ TextEntry.make('user.email').label('User'),
124
+ TextEntry.make('abilities').badge().label('Abilities').columnSpanFull(),
125
+ TextEntry.make('lastUsedAt').dateTime().label('Last used'),
126
+ TextEntry.make('expiresAt').dateTime().label('Expires'),
127
+ TextEntry.make('revokedAt').dateTime().label('Revoked'),
128
+ TextEntry.make('createdAt').dateTime().label('Created'),
129
+ ]),
130
+ ]);
131
+ });
132
+ }
133
+ static async prepareCreate(data, ctx) {
134
+ const name = String(data.name ?? '').trim();
135
+ const descriptionRaw = data.description;
136
+ const description = descriptionRaw != null && String(descriptionRaw).trim() !== ''
137
+ ? String(descriptionRaw).trim()
138
+ : null;
139
+ const kind = String(data.kind ?? 'machine').trim();
140
+ const userIdRaw = data.userId;
141
+ const userId = userIdRaw != null && String(userIdRaw).trim() !== ''
142
+ ? String(userIdRaw).trim()
143
+ : null;
144
+ const errors = {};
145
+ if (!name)
146
+ errors.name = 'Name is required.';
147
+ if (kind !== 'pat' && kind !== 'machine') {
148
+ errors.kind = 'Choose Machine API key or Personal access token.';
149
+ }
150
+ if (kind === 'pat' && !userId) {
151
+ errors.userId = 'Personal access tokens require a user.';
152
+ }
153
+ if (Object.keys(errors).length > 0) {
154
+ throw new ValidationException(errors);
155
+ }
156
+ let abilities = Array.isArray(data.abilities)
157
+ ? data.abilities.map(String).map((entry) => entry.trim()).filter(Boolean)
158
+ : [];
159
+ if (kind === 'machine' && abilities.length === 0) {
160
+ abilities = ['*'];
161
+ }
162
+ const generated = generateApiKey();
163
+ const expiresRaw = data.expiresAt;
164
+ const expiresAt = expiresRaw != null && String(expiresRaw).trim() !== ''
165
+ ? new Date(String(expiresRaw))
166
+ : null;
167
+ const payload = {
168
+ name,
169
+ description,
170
+ kind,
171
+ abilities,
172
+ userId: kind === 'pat' ? userId : null,
173
+ tokenHash: generated.tokenHash,
174
+ tokenPrefix: generated.prefix,
175
+ createdByUserId: ctx.userId ?? null,
176
+ expiresAt: expiresAt && !Number.isNaN(expiresAt.getTime()) ? expiresAt : null,
177
+ revokedAt: null,
178
+ lastUsedAt: null,
179
+ };
180
+ const label = kind === 'pat' ? 'Personal access token' : 'Machine API key';
181
+ return {
182
+ data: payload,
183
+ flashPlainText: generated.plainText,
184
+ flashMessage: `${label} "${name}" created. Copy it now — it will not be shown again:\n${generated.plainText}`,
185
+ };
186
+ }
187
+ static async handleAction(action, records, ctx) {
188
+ if (action !== 'revoke' && action !== 'reactivate') {
189
+ return null;
190
+ }
191
+ let changed = 0;
192
+ for (const record of records) {
193
+ const id = String(record.id ?? record._id ?? '');
194
+ if (!id)
195
+ continue;
196
+ const revokedAt = record.revokedAt;
197
+ const isRevoked = revokedAt != null && String(revokedAt).trim() !== '';
198
+ if (action === 'revoke') {
199
+ if (isRevoked)
200
+ continue;
201
+ await ctx.adapter.update(ctx.meta, id, { revokedAt: new Date() });
202
+ changed += 1;
203
+ }
204
+ else {
205
+ if (!isRevoked)
206
+ continue;
207
+ await ctx.adapter.update(ctx.meta, id, { revokedAt: null });
208
+ changed += 1;
209
+ }
210
+ }
211
+ if (action === 'revoke') {
212
+ return {
213
+ message: changed === 1
214
+ ? 'API key deactivated'
215
+ : `${changed} API key(s) deactivated`,
216
+ };
217
+ }
218
+ return {
219
+ message: changed === 1
220
+ ? 'API key reactivated'
221
+ : `${changed} API key(s) reactivated`,
222
+ };
223
+ }
224
+ }
225
+ //# sourceMappingURL=api_key_resource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api_key_resource.js","sourceRoot":"","sources":["../../src/resources/api_key_resource.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { Router } from '@adonisjs/core/http';
2
+ import type { ApplicationService } from '@adonisjs/core/types';
3
+ import type { ShamarRuntime } from './runtime.js';
4
+ export declare function registerShamarRoutes(app: ApplicationService, router: Router, runtime: ShamarRuntime): Promise<void>;
5
+ //# sourceMappingURL=routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAgB,MAAM,cAAc,CAAC;AAqBhE,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,kBAAkB,EACvB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,IAAI,CAAC,CAoCf"}
package/dist/routes.js ADDED
@@ -0,0 +1,97 @@
1
+ import { AdminController } from './controllers/admin_controller.js';
2
+ import { AssetsController } from './assets-controller.js';
3
+ export async function registerShamarRoutes(app, router, runtime) {
4
+ const apiPrefix = runtime.config.apiPrefix ?? '/api/shamar';
5
+ for (const panel of runtime.panels) {
6
+ registerPanelRoutes(app, router, runtime, panel);
7
+ }
8
+ // JSON API uses the first panel's registry/adapter (compat).
9
+ const primary = runtime.panels[0];
10
+ const apiHandler = (action) => {
11
+ return async (ctx) => {
12
+ const controller = new AdminController(primary, runtime.config, runtime.authorizer);
13
+ const method = controller[action];
14
+ return method.call(controller, ctx, { asJson: true });
15
+ };
16
+ };
17
+ const api = router.group(() => {
18
+ router.get('/:slug', apiHandler('index')).as('shamar.api.index');
19
+ router.get('/:slug/:id', apiHandler('show')).as('shamar.api.show');
20
+ router.post('/:slug', apiHandler('store')).as('shamar.api.store');
21
+ router.put('/:slug/:id', apiHandler('update')).as('shamar.api.update');
22
+ router.delete('/:slug/:id', apiHandler('destroy')).as('shamar.api.destroy');
23
+ });
24
+ api.prefix(apiPrefix);
25
+ if (runtime.config.auth?.apiKeys?.protectApi) {
26
+ const { createRequireApiKeyMiddleware } = await import('./middleware/require_api_key_middleware.js');
27
+ api.use(createRequireApiKeyMiddleware(runtime.config));
28
+ }
29
+ }
30
+ function registerPanelRoutes(app, router, runtime, panel) {
31
+ const prefix = panel.path.replace(/\/+$/, '') || '/admin';
32
+ const routePrefix = `shamar.${panel.id}`;
33
+ const handler = (action, asJson = false) => {
34
+ return async (ctx) => {
35
+ const controller = new AdminController(panel, runtime.config, runtime.authorizer);
36
+ const method = controller[action];
37
+ return method.call(controller, ctx, { asJson });
38
+ };
39
+ };
40
+ const assets = new AssetsController(runtime.config, panel.config.branding);
41
+ const assetHandler = (action) => {
42
+ return async (ctx) => {
43
+ const method = assets[action];
44
+ return method.call(assets, ctx);
45
+ };
46
+ };
47
+ const group = router.group(() => {
48
+ router.get('/assets/admin.css', assetHandler('adminCss')).as(`${routePrefix}.assets.adminCss`);
49
+ router
50
+ .get('/assets/branding.css', assetHandler('brandingCss'))
51
+ .as(`${routePrefix}.assets.brandingCss`);
52
+ router.get('/assets/shamar-ui.js', assetHandler('shamarUi')).as(`${routePrefix}.assets.shamarUi`);
53
+ router.get('/assets/loom-ui.js', assetHandler('shamarUi')).as(`${routePrefix}.assets.legacyUi`);
54
+ router
55
+ .get('/assets/alpine.min.js', assetHandler('alpineJs'))
56
+ .as(`${routePrefix}.assets.alpineJs`);
57
+ router.get('/', handler('dashboard')).as(`${routePrefix}.dashboard`);
58
+ router.get('/:slug/create', handler('create')).as(`${routePrefix}.resources.create`);
59
+ router.post('/:slug/form-state', handler('formState')).as(`${routePrefix}.resources.formState`);
60
+ router
61
+ .get('/:slug/relation-search', handler('relationSearch', true))
62
+ .as(`${routePrefix}.resources.relationSearch`);
63
+ router
64
+ .post('/:slug/relation-quick-create', handler('relationQuickCreate', true))
65
+ .as(`${routePrefix}.resources.relationQuickCreate`);
66
+ router
67
+ .post('/:slug/relation-attach', handler('relationAttach', true))
68
+ .as(`${routePrefix}.resources.relationAttach`);
69
+ router
70
+ .post('/:slug/relation-detach', handler('relationDetach', true))
71
+ .as(`${routePrefix}.resources.relationDetach`);
72
+ router.post('/:slug', handler('store')).as(`${routePrefix}.resources.store`);
73
+ router.post('/:slug/bulk', handler('bulk')).as(`${routePrefix}.resources.bulk`);
74
+ router.get('/:slug/:id/edit', handler('edit')).as(`${routePrefix}.resources.edit`);
75
+ router
76
+ .get('/:slug/:id/summary', handler('summary', true))
77
+ .as(`${routePrefix}.resources.summary`);
78
+ router
79
+ .post('/:slug/:id/action/:action', handler('recordAction'))
80
+ .as(`${routePrefix}.resources.recordAction`);
81
+ router.post('/:slug/:id/delete', handler('destroy')).as(`${routePrefix}.resources.destroy`);
82
+ router.post('/:slug/:id', handler('update')).as(`${routePrefix}.resources.update`);
83
+ router.put('/:slug/:id', handler('update')).as(`${routePrefix}.resources.update.put`);
84
+ router.delete('/:slug/:id', handler('destroy')).as(`${routePrefix}.resources.destroy.delete`);
85
+ router
86
+ .get('/:slug/:id', handler('show'))
87
+ .where('slug', /^(?!assets$)/)
88
+ .as(`${routePrefix}.resources.show`);
89
+ router
90
+ .get('/:slug', handler('index'))
91
+ .where('slug', /^(?!assets$)/)
92
+ .as(`${routePrefix}.resources.index`);
93
+ });
94
+ group.prefix(prefix);
95
+ void app;
96
+ }
97
+ //# sourceMappingURL=routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { ResourceRegistry, type DataAdapter, type PanelConfig } from '@shamar/core';
2
+ import { type ShamarConfig } from './config.js';
3
+ import { type Authorizer } from '@shamar/cherubim';
4
+ export interface PanelRuntime {
5
+ id: string;
6
+ path: string;
7
+ config: PanelConfig;
8
+ registry: ResourceRegistry;
9
+ adapter: DataAdapter;
10
+ }
11
+ export interface ShamarRuntime {
12
+ config: ShamarConfig & {
13
+ panels: PanelConfig[];
14
+ };
15
+ authorizer: Authorizer;
16
+ /** @deprecated First panel registry — prefer `panels`. */
17
+ registry: ResourceRegistry;
18
+ /** @deprecated First panel adapter — prefer `panels`. */
19
+ adapter: DataAdapter;
20
+ panels: PanelRuntime[];
21
+ panel(id: string): PanelRuntime;
22
+ panelByPath(pathname: string): PanelRuntime | undefined;
23
+ }
24
+ export declare function createShamarRuntime(config: ShamarConfig, options?: {
25
+ appRoot?: string;
26
+ }): Promise<ShamarRuntime>;
27
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,KAAK,WAAW,EAChB,KAAK,WAAW,EAEjB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAgB,KAAK,YAAY,EAAkB,MAAM,aAAa,CAAC;AAE9E,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnE,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,YAAY,GAAG;QAAE,MAAM,EAAE,WAAW,EAAE,CAAA;KAAE,CAAC;IACjD,UAAU,EAAE,UAAU,CAAC;IACvB,0DAA0D;IAC1D,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,yDAAyD;IACzD,OAAO,EAAE,WAAW,CAAC;IACrB,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,CAAC;IAChC,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAAC;CACzD;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,YAAY,EACpB,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GACjC,OAAO,CAAC,aAAa,CAAC,CAoDxB"}
@@ -0,0 +1,74 @@
1
+ import { ResourceRegistry, } from '@shamar/core';
2
+ import { createLucidAdapter } from '@shamar/lucid';
3
+ import { createMongooseAdapter } from '@shamar/mongoose';
4
+ import { defineConfig } from './config.js';
5
+ import { createAuthorizer } from './shamar/auth.js';
6
+ import { PolicyRegistry } from '@shamar/cherubim';
7
+ import { discoverResources } from './discover.js';
8
+ export async function createShamarRuntime(config, options = {}) {
9
+ const resolved = defineConfig(config);
10
+ const policyRegistry = new PolicyRegistry();
11
+ if (resolved.auth?.policies) {
12
+ policyRegistry.registerMany(resolved.auth.policies);
13
+ }
14
+ const authorizer = createAuthorizer(resolved, policyRegistry);
15
+ const panels = [];
16
+ for (const panelConfig of resolved.panels) {
17
+ let resources = [...panelConfig.resources];
18
+ if (panelConfig.discover && options.appRoot) {
19
+ const discovered = await discoverResources(options.appRoot, panelConfig.discover);
20
+ resources = mergeResources(resources, discovered);
21
+ }
22
+ const panelResolved = { ...panelConfig, resources };
23
+ policyRegistry.registerResources(resources);
24
+ panels.push({
25
+ id: panelResolved.id,
26
+ path: panelResolved.path,
27
+ config: panelResolved,
28
+ registry: new ResourceRegistry(resources),
29
+ adapter: resolveAdapter(resolved, panelResolved),
30
+ });
31
+ }
32
+ if (panels.length === 0) {
33
+ throw new Error('Shamar config must define at least one panel');
34
+ }
35
+ const first = panels[0];
36
+ return {
37
+ config: resolved,
38
+ authorizer,
39
+ registry: first.registry,
40
+ adapter: first.adapter,
41
+ panels,
42
+ panel(id) {
43
+ const found = panels.find((p) => p.id === id);
44
+ if (!found)
45
+ throw new Error(`Unknown Shamar panel "${id}"`);
46
+ return found;
47
+ },
48
+ panelByPath(pathname) {
49
+ const normalized = pathname.replace(/\/+$/, '') || '/';
50
+ return panels
51
+ .slice()
52
+ .sort((a, b) => b.path.length - a.path.length)
53
+ .find((p) => normalized === p.path || normalized.startsWith(`${p.path}/`));
54
+ },
55
+ };
56
+ }
57
+ function mergeResources(explicit, discovered) {
58
+ const bySlug = new Map();
59
+ for (const resource of [...discovered, ...explicit]) {
60
+ bySlug.set(resource.slug, resource);
61
+ }
62
+ return [...bySlug.values()];
63
+ }
64
+ function resolveAdapter(config, panel) {
65
+ if (config.adapter) {
66
+ return typeof config.adapter === 'function' ? config.adapter() : config.adapter;
67
+ }
68
+ const orm = panel.orm ?? config.orm ?? 'lucid';
69
+ if (orm === 'mongoose') {
70
+ return createMongooseAdapter();
71
+ }
72
+ return createLucidAdapter();
73
+ }
74
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { ShamarHttpContext } from '../context.js';
2
+ import { Authorizer, ForbiddenError, PolicyRegistry, UnauthorizedError, type AuthorizationContext, type CherubimUser, type ResourceAction } from '@shamar/cherubim';
3
+ import type { ResourceMeta, ResourceRegistry } from '@shamar/core';
4
+ import type { ShamarConfig } from '../config.js';
5
+ export { ForbiddenError, UnauthorizedError };
6
+ /** Whether panel routes should require an authenticated user. */
7
+ export declare function authRequired(config: ShamarConfig): boolean;
8
+ export declare function createAuthorizer(config: ShamarConfig, policies: PolicyRegistry): Authorizer;
9
+ /** Map header credentials / session to a Cherubim principal. */
10
+ export declare function resolveShamarUser(ctx: ShamarHttpContext, config: ShamarConfig): Promise<CherubimUser | null>;
11
+ export declare function buildAuthContext(ctx: ShamarHttpContext, config: ShamarConfig, panelId?: string): Promise<AuthorizationContext>;
12
+ /**
13
+ * API-prefix requests may require a valid machine gateway key when the
14
+ * `requireApiKey` middleware is applied to the route (or `auth.apiKeys.protectApi`).
15
+ *
16
+ * @deprecated Prefer {@link RequireApiKeyMiddleware} / `protectApi`. Kept for
17
+ * callers that still pass an explicit API-route flag.
18
+ */
19
+ export declare function missingRequiredMachineKey(authCtx: AuthorizationContext, config: ShamarConfig, isApiRoute: boolean): boolean;
20
+ export interface ResourcePolicyFlags {
21
+ create: boolean;
22
+ update: boolean;
23
+ delete: boolean;
24
+ }
25
+ export declare function resourcePolicyFlags(authorizer: Authorizer, authCtx: AuthorizationContext, registry: ResourceRegistry, meta: ResourceMeta, record?: Record<string, unknown> | null): ResourcePolicyFlags;
26
+ export declare function canViewResource(authorizer: Authorizer, authCtx: AuthorizationContext, registry: ResourceRegistry, slug: string): boolean;
27
+ export declare function respondUnauthorized(ctx: ShamarHttpContext, config: ShamarConfig, asJson: boolean, message?: string): unknown;
28
+ export declare function respondForbidden(ctx: ShamarHttpContext, message: string, asJson: boolean, fallbackPath: string): unknown;
29
+ export declare function assertResourceAccess(authorizer: Authorizer, authCtx: AuthorizationContext, registry: ResourceRegistry, meta: ResourceMeta, action: ResourceAction, record?: Record<string, unknown>): void;
30
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/shamar/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEvD,OAAO,EACL,UAAU,EACV,cAAc,EACd,cAAc,EACd,iBAAiB,EAQjB,KAAK,oBAAoB,EACzB,KAAK,YAAY,EACjB,KAAK,cAAc,EACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,CAAC;AAE7C,iEAAiE;AACjE,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAI1D;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,cAAc,GAAG,UAAU,CAS3F;AAwHD,gEAAgE;AAChE,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,iBAAiB,EACtB,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAK9B;AAED,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,iBAAiB,EACtB,MAAM,EAAE,YAAY,EACpB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,oBAAoB,CAAC,CA0D/B;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,oBAAoB,EAC7B,MAAM,EAAE,YAAY,EACpB,UAAU,EAAE,OAAO,GAClB,OAAO,CAIT;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,oBAAoB,EAC7B,QAAQ,EAAE,gBAAgB,EAC1B,IAAI,EAAE,YAAY,EAClB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GACtC,mBAAmB,CAWrB;AAED,wBAAgB,eAAe,CAC7B,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,oBAAoB,EAC7B,QAAQ,EAAE,gBAAgB,EAC1B,IAAI,EAAE,MAAM,GACX,OAAO,CAKT;AAED,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,iBAAiB,EACtB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,OAAO,EACf,OAAO,SAA6B,GACnC,OAAO,CAMT;AAED,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,iBAAiB,EACtB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,OAAO,EACf,YAAY,EAAE,MAAM,GACnB,OAAO,CAOT;AAED,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,oBAAoB,EAC7B,QAAQ,EAAE,gBAAgB,EAC1B,IAAI,EAAE,YAAY,EAClB,MAAM,EAAE,cAAc,EACtB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,IAAI,CAIN"}