@adonis-agora/flags 0.0.0-stage → 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.
- package/CHANGELOG.md +12 -0
- package/LICENSE +21 -0
- package/README.md +15 -2
- package/dist/assets/spa/assets/index-DdmFo7xr.js +12 -0
- package/dist/assets/spa/assets/index-DdmFo7xr.js.map +1 -0
- package/dist/assets/spa/assets/index-DhkcP3Cw.css +2 -0
- package/dist/assets/spa/index.html +26 -0
- package/dist/commands/flags_list.d.ts +9 -0
- package/dist/commands/flags_list.d.ts.map +1 -0
- package/dist/commands/flags_list.js +51 -0
- package/dist/commands/flags_list.js.map +1 -0
- package/dist/commands/flags_ops.d.ts +60 -0
- package/dist/commands/flags_ops.d.ts.map +1 -0
- package/dist/commands/flags_ops.js +253 -0
- package/dist/commands/flags_ops.js.map +1 -0
- package/dist/commands/flags_refs.d.ts +15 -0
- package/dist/commands/flags_refs.d.ts.map +1 -0
- package/dist/commands/flags_refs.js +90 -0
- package/dist/commands/flags_refs.js.map +1 -0
- package/dist/commands/flags_set.d.ts +19 -0
- package/dist/commands/flags_set.d.ts.map +1 -0
- package/dist/commands/flags_set.js +97 -0
- package/dist/commands/flags_set.js.map +1 -0
- package/dist/commands/flags_types.d.ts +18 -0
- package/dist/commands/flags_types.d.ts.map +1 -0
- package/dist/commands/flags_types.js +94 -0
- package/dist/commands/flags_types.js.map +1 -0
- package/dist/commands/flags_work.d.ts +16 -0
- package/dist/commands/flags_work.d.ts.map +1 -0
- package/dist/commands/flags_work.js +71 -0
- package/dist/commands/flags_work.js.map +1 -0
- package/dist/commands/main.d.ts +15 -0
- package/dist/commands/main.d.ts.map +1 -0
- package/dist/commands/main.js +30 -0
- package/dist/commands/main.js.map +1 -0
- package/dist/commands/shared.d.ts +21 -0
- package/dist/commands/shared.d.ts.map +1 -0
- package/dist/commands/shared.js +70 -0
- package/dist/commands/shared.js.map +1 -0
- package/dist/configure.d.ts +11 -0
- package/dist/configure.d.ts.map +1 -0
- package/dist/configure.js +32 -0
- package/dist/configure.js.map +1 -0
- package/dist/providers/dashboard_provider.d.ts +65 -0
- package/dist/providers/dashboard_provider.d.ts.map +1 -0
- package/dist/providers/dashboard_provider.js +340 -0
- package/dist/providers/dashboard_provider.js.map +1 -0
- package/dist/providers/flags_provider.d.ts +30 -0
- package/dist/providers/flags_provider.d.ts.map +1 -0
- package/dist/providers/flags_provider.js +184 -0
- package/dist/providers/flags_provider.js.map +1 -0
- package/dist/services/main.d.ts +17 -0
- package/dist/services/main.d.ts.map +1 -0
- package/dist/services/main.js +20 -0
- package/dist/services/main.js.map +1 -0
- package/dist/src/admin.d.ts +189 -0
- package/dist/src/admin.d.ts.map +1 -0
- package/dist/src/admin.js +539 -0
- package/dist/src/admin.js.map +1 -0
- package/dist/src/analytics/backend.d.ts +18 -0
- package/dist/src/analytics/backend.d.ts.map +1 -0
- package/dist/src/analytics/backend.js +25 -0
- package/dist/src/analytics/backend.js.map +1 -0
- package/dist/src/analytics/clickhouse_backend.d.ts +16 -0
- package/dist/src/analytics/clickhouse_backend.d.ts.map +1 -0
- package/dist/src/analytics/clickhouse_backend.js +48 -0
- package/dist/src/analytics/clickhouse_backend.js.map +1 -0
- package/dist/src/analytics/duckdb.d.ts +39 -0
- package/dist/src/analytics/duckdb.d.ts.map +1 -0
- package/dist/src/analytics/duckdb.js +117 -0
- package/dist/src/analytics/duckdb.js.map +1 -0
- package/dist/src/analytics/lucid_backend.d.ts +16 -0
- package/dist/src/analytics/lucid_backend.d.ts.map +1 -0
- package/dist/src/analytics/lucid_backend.js +45 -0
- package/dist/src/analytics/lucid_backend.js.map +1 -0
- package/dist/src/analytics/metrics.d.ts +50 -0
- package/dist/src/analytics/metrics.d.ts.map +1 -0
- package/dist/src/analytics/metrics.js +42 -0
- package/dist/src/analytics/metrics.js.map +1 -0
- package/dist/src/analytics/results.d.ts +80 -0
- package/dist/src/analytics/results.d.ts.map +1 -0
- package/dist/src/analytics/results.js +143 -0
- package/dist/src/analytics/results.js.map +1 -0
- package/dist/src/dashboard/access_denied_page.d.ts +100 -0
- package/dist/src/dashboard/access_denied_page.d.ts.map +1 -0
- package/dist/src/dashboard/access_denied_page.js +262 -0
- package/dist/src/dashboard/access_denied_page.js.map +1 -0
- package/dist/src/dashboard/actor.d.ts +12 -0
- package/dist/src/dashboard/actor.d.ts.map +1 -0
- package/dist/src/dashboard/actor.js +33 -0
- package/dist/src/dashboard/actor.js.map +1 -0
- package/dist/src/dashboard/authorize_decision.d.ts +48 -0
- package/dist/src/dashboard/authorize_decision.d.ts.map +1 -0
- package/dist/src/dashboard/authorize_decision.js +44 -0
- package/dist/src/dashboard/authorize_decision.js.map +1 -0
- package/dist/src/dashboard/console_authorize.d.ts +77 -0
- package/dist/src/dashboard/console_authorize.d.ts.map +1 -0
- package/dist/src/dashboard/console_authorize.js +104 -0
- package/dist/src/dashboard/console_authorize.js.map +1 -0
- package/dist/src/dashboard/define_config.d.ts +71 -0
- package/dist/src/dashboard/define_config.d.ts.map +1 -0
- package/dist/src/dashboard/define_config.js +18 -0
- package/dist/src/dashboard/define_config.js.map +1 -0
- package/dist/src/dashboard/handlers.d.ts +172 -0
- package/dist/src/dashboard/handlers.d.ts.map +1 -0
- package/dist/src/dashboard/handlers.js +949 -0
- package/dist/src/dashboard/handlers.js.map +1 -0
- package/dist/src/dashboard/index.d.ts +15 -0
- package/dist/src/dashboard/index.d.ts.map +1 -0
- package/dist/src/dashboard/index.js +10 -0
- package/dist/src/dashboard/index.js.map +1 -0
- package/dist/src/dashboard/shape.d.ts +12 -0
- package/dist/src/dashboard/shape.d.ts.map +1 -0
- package/dist/src/dashboard/shape.js +232 -0
- package/dist/src/dashboard/shape.js.map +1 -0
- package/dist/src/dashboard/spa.d.ts +34 -0
- package/dist/src/dashboard/spa.d.ts.map +1 -0
- package/dist/src/dashboard/spa.js +50 -0
- package/dist/src/dashboard/spa.js.map +1 -0
- package/dist/src/declare.d.ts +85 -0
- package/dist/src/declare.d.ts.map +1 -0
- package/dist/src/declare.js +62 -0
- package/dist/src/declare.js.map +1 -0
- package/dist/src/define_config.d.ts +256 -0
- package/dist/src/define_config.d.ts.map +1 -0
- package/dist/src/define_config.js +90 -0
- package/dist/src/define_config.js.map +1 -0
- package/dist/src/durable.d.ts +29 -0
- package/dist/src/durable.d.ts.map +1 -0
- package/dist/src/durable.js +55 -0
- package/dist/src/durable.js.map +1 -0
- package/dist/src/enrichers.d.ts +51 -0
- package/dist/src/enrichers.d.ts.map +1 -0
- package/dist/src/enrichers.js +105 -0
- package/dist/src/enrichers.js.map +1 -0
- package/dist/src/events/buffer.d.ts +38 -0
- package/dist/src/events/buffer.d.ts.map +1 -0
- package/dist/src/events/buffer.js +86 -0
- package/dist/src/events/buffer.js.map +1 -0
- package/dist/src/events/event.d.ts +42 -0
- package/dist/src/events/event.d.ts.map +1 -0
- package/dist/src/events/event.js +82 -0
- package/dist/src/events/event.js.map +1 -0
- package/dist/src/http/browser.d.ts +33 -0
- package/dist/src/http/browser.d.ts.map +1 -0
- package/dist/src/http/browser.js +81 -0
- package/dist/src/http/browser.js.map +1 -0
- package/dist/src/http/browser_api.d.ts +48 -0
- package/dist/src/http/browser_api.d.ts.map +1 -0
- package/dist/src/http/browser_api.js +273 -0
- package/dist/src/http/browser_api.js.map +1 -0
- package/dist/src/http/browser_tokens.d.ts +27 -0
- package/dist/src/http/browser_tokens.d.ts.map +1 -0
- package/dist/src/http/browser_tokens.js +48 -0
- package/dist/src/http/browser_tokens.js.map +1 -0
- package/dist/src/http/control_plane.d.ts +58 -0
- package/dist/src/http/control_plane.d.ts.map +1 -0
- package/dist/src/http/control_plane.js +318 -0
- package/dist/src/http/control_plane.js.map +1 -0
- package/dist/src/http/csrf.d.ts +22 -0
- package/dist/src/http/csrf.d.ts.map +1 -0
- package/dist/src/http/csrf.js +24 -0
- package/dist/src/http/csrf.js.map +1 -0
- package/dist/src/http/edge_tag.d.ts +55 -0
- package/dist/src/http/edge_tag.d.ts.map +1 -0
- package/dist/src/http/edge_tag.js +45 -0
- package/dist/src/http/edge_tag.js.map +1 -0
- package/dist/src/http/flag_middleware.d.ts +27 -0
- package/dist/src/http/flag_middleware.d.ts.map +1 -0
- package/dist/src/http/flag_middleware.js +30 -0
- package/dist/src/http/flag_middleware.js.map +1 -0
- package/dist/src/http/flags_middleware.d.ts +20 -0
- package/dist/src/http/flags_middleware.d.ts.map +1 -0
- package/dist/src/http/flags_middleware.js +20 -0
- package/dist/src/http/flags_middleware.js.map +1 -0
- package/dist/src/http/subject_resolver.d.ts +45 -0
- package/dist/src/http/subject_resolver.d.ts.map +1 -0
- package/dist/src/http/subject_resolver.js +93 -0
- package/dist/src/http/subject_resolver.js.map +1 -0
- package/dist/src/identity.d.ts +82 -0
- package/dist/src/identity.d.ts.map +1 -0
- package/dist/src/identity.js +100 -0
- package/dist/src/identity.js.map +1 -0
- package/dist/src/index.d.ts +41 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +34 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/manager.d.ts +154 -0
- package/dist/src/manager.d.ts.map +1 -0
- package/dist/src/manager.js +333 -0
- package/dist/src/manager.js.map +1 -0
- package/dist/src/openfeature/provider.d.ts +36 -0
- package/dist/src/openfeature/provider.d.ts.map +1 -0
- package/dist/src/openfeature/provider.js +82 -0
- package/dist/src/openfeature/provider.js.map +1 -0
- package/dist/src/relay/relay.d.ts +36 -0
- package/dist/src/relay/relay.d.ts.map +1 -0
- package/dist/src/relay/relay.js +73 -0
- package/dist/src/relay/relay.js.map +1 -0
- package/dist/src/relay/results_cache.d.ts +20 -0
- package/dist/src/relay/results_cache.d.ts.map +1 -0
- package/dist/src/relay/results_cache.js +31 -0
- package/dist/src/relay/results_cache.js.map +1 -0
- package/dist/src/relay/worker.d.ts +66 -0
- package/dist/src/relay/worker.d.ts.map +1 -0
- package/dist/src/relay/worker.js +177 -0
- package/dist/src/relay/worker.js.map +1 -0
- package/dist/src/ruleset_source.d.ts +73 -0
- package/dist/src/ruleset_source.d.ts.map +1 -0
- package/dist/src/ruleset_source.js +128 -0
- package/dist/src/ruleset_source.js.map +1 -0
- package/dist/src/runtime.d.ts +70 -0
- package/dist/src/runtime.d.ts.map +1 -0
- package/dist/src/runtime.js +301 -0
- package/dist/src/runtime.js.map +1 -0
- package/dist/src/schema.d.ts +39 -0
- package/dist/src/schema.d.ts.map +1 -0
- package/dist/src/schema.js +311 -0
- package/dist/src/schema.js.map +1 -0
- package/dist/src/services/accessor.d.ts +5 -0
- package/dist/src/services/accessor.d.ts.map +1 -0
- package/dist/src/services/accessor.js +20 -0
- package/dist/src/services/accessor.js.map +1 -0
- package/dist/src/sinks/clickhouse.d.ts +41 -0
- package/dist/src/sinks/clickhouse.d.ts.map +1 -0
- package/dist/src/sinks/clickhouse.js +117 -0
- package/dist/src/sinks/clickhouse.js.map +1 -0
- package/dist/src/sinks/lucid_sink.d.ts +25 -0
- package/dist/src/sinks/lucid_sink.d.ts.map +1 -0
- package/dist/src/sinks/lucid_sink.js +87 -0
- package/dist/src/sinks/lucid_sink.js.map +1 -0
- package/dist/src/sinks/parquet_sink.d.ts +41 -0
- package/dist/src/sinks/parquet_sink.d.ts.map +1 -0
- package/dist/src/sinks/parquet_sink.js +140 -0
- package/dist/src/sinks/parquet_sink.js.map +1 -0
- package/dist/src/sinks/posthog_sink.d.ts +29 -0
- package/dist/src/sinks/posthog_sink.d.ts.map +1 -0
- package/dist/src/sinks/posthog_sink.js +65 -0
- package/dist/src/sinks/posthog_sink.js.map +1 -0
- package/dist/src/sinks/sink.d.ts +36 -0
- package/dist/src/sinks/sink.d.ts.map +1 -0
- package/dist/src/sinks/sink.js +36 -0
- package/dist/src/sinks/sink.js.map +1 -0
- package/dist/src/sql.d.ts +33 -0
- package/dist/src/sql.d.ts.map +1 -0
- package/dist/src/sql.js +66 -0
- package/dist/src/sql.js.map +1 -0
- package/dist/src/stores/lucid_store.d.ts +55 -0
- package/dist/src/stores/lucid_store.d.ts.map +1 -0
- package/dist/src/stores/lucid_store.js +412 -0
- package/dist/src/stores/lucid_store.js.map +1 -0
- package/dist/src/stores/memory_store.d.ts +38 -0
- package/dist/src/stores/memory_store.d.ts.map +1 -0
- package/dist/src/stores/memory_store.js +166 -0
- package/dist/src/stores/memory_store.js.map +1 -0
- package/dist/src/stores/store.d.ts +166 -0
- package/dist/src/stores/store.d.ts.map +1 -0
- package/dist/src/stores/store.js +67 -0
- package/dist/src/stores/store.js.map +1 -0
- package/dist/src/subject.d.ts +25 -0
- package/dist/src/subject.d.ts.map +1 -0
- package/dist/src/subject.js +30 -0
- package/dist/src/subject.js.map +1 -0
- package/dist/src/testing/index.d.ts +31 -0
- package/dist/src/testing/index.d.ts.map +1 -0
- package/dist/src/testing/index.js +60 -0
- package/dist/src/testing/index.js.map +1 -0
- package/dist/src/topology/browser_token.d.ts +48 -0
- package/dist/src/topology/browser_token.d.ts.map +1 -0
- package/dist/src/topology/browser_token.js +128 -0
- package/dist/src/topology/browser_token.js.map +1 -0
- package/dist/src/topology/remote_source.d.ts +39 -0
- package/dist/src/topology/remote_source.d.ts.map +1 -0
- package/dist/src/topology/remote_source.js +184 -0
- package/dist/src/topology/remote_source.js.map +1 -0
- package/dist/src/topology/token.d.ts +36 -0
- package/dist/src/topology/token.d.ts.map +1 -0
- package/dist/src/topology/token.js +68 -0
- package/dist/src/topology/token.js.map +1 -0
- package/dist/src/topology/verify.d.ts +88 -0
- package/dist/src/topology/verify.d.ts.map +1 -0
- package/dist/src/topology/verify.js +128 -0
- package/dist/src/topology/verify.js.map +1 -0
- package/dist/src/transports/db_transport.d.ts +55 -0
- package/dist/src/transports/db_transport.d.ts.map +1 -0
- package/dist/src/transports/db_transport.js +202 -0
- package/dist/src/transports/db_transport.js.map +1 -0
- package/dist/src/transports/http_transport.d.ts +30 -0
- package/dist/src/transports/http_transport.d.ts.map +1 -0
- package/dist/src/transports/http_transport.js +51 -0
- package/dist/src/transports/http_transport.js.map +1 -0
- package/dist/src/transports/memory_transport.d.ts +29 -0
- package/dist/src/transports/memory_transport.d.ts.map +1 -0
- package/dist/src/transports/memory_transport.js +91 -0
- package/dist/src/transports/memory_transport.js.map +1 -0
- package/dist/src/transports/redis_transport.d.ts +50 -0
- package/dist/src/transports/redis_transport.d.ts.map +1 -0
- package/dist/src/transports/redis_transport.js +107 -0
- package/dist/src/transports/redis_transport.js.map +1 -0
- package/dist/src/transports/transport.d.ts +62 -0
- package/dist/src/transports/transport.d.ts.map +1 -0
- package/dist/src/transports/transport.js +2 -0
- package/dist/src/transports/transport.js.map +1 -0
- package/dist/src/types.d.ts +30 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/usage.d.ts +18 -0
- package/dist/src/usage.d.ts.map +1 -0
- package/dist/src/usage.js +52 -0
- package/dist/src/usage.js.map +1 -0
- package/dist/stubs/config/flags.stub +50 -0
- package/dist/stubs/config/flags_dashboard.stub +35 -0
- package/dist/stubs/database/migrations/create_flags_tables.stub +27 -0
- package/dist/stubs/main.d.ts +3 -0
- package/dist/stubs/main.d.ts.map +1 -0
- package/dist/stubs/main.js +9 -0
- package/dist/stubs/main.js.map +1 -0
- package/package.json +178 -3
- package/skills/flags-basics/SKILL.md +142 -0
- package/skills/flags-deployment/SKILL.md +125 -0
- package/skills/flags-experiments/SKILL.md +99 -0
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { basename, resolve as resolvePath } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { resolveAccessDeniedPage, } from '../src/dashboard/access_denied_page.js';
|
|
5
|
+
import { defaultActor, FALLBACK_ACTOR, toActor } from '../src/dashboard/actor.js';
|
|
6
|
+
import { resolveConsoleAuthorize, } from '../src/dashboard/console_authorize.js';
|
|
7
|
+
import { resolveConfig, } from '../src/dashboard/define_config.js';
|
|
8
|
+
import { approveChangeRequest, audit, cancelChangeRequest, cancelSchedule, createFlag, createSchedule, deleteFlag, deleteLayer, deleteSegment, evaluateContext, experimentDetail, exportRuleset, flagDetail, importRuleset, listChangeRequests, listExperiments, listFlags, listLayers, listSchedules, listSegments, meta, ops, preview, promote, recomputeExperiment, rejectChangeRequest, saveFlag, saveHoldout, saveLayer, saveSegment, setEnabled, setOverride, setRollout, setVariant, stale, updateDeclaration, } from '../src/dashboard/handlers.js';
|
|
9
|
+
import { contentTypeFor, renderIndexHtml } from '../src/dashboard/spa.js';
|
|
10
|
+
import { authkitIdentity } from '../src/http/subject_resolver.js';
|
|
11
|
+
import { getRuntime, hasRuntime } from '../src/services/accessor.js';
|
|
12
|
+
/**
|
|
13
|
+
* Directory of the built SPA (`dist/assets/spa`, copied in by `copy:spa`), relative to this
|
|
14
|
+
* compiled provider (`dist/providers`). Resolved lazily: `fileURLToPath` throws on a non-`file:`
|
|
15
|
+
* `import.meta.url`, which would make the provider unimportable under some test runners.
|
|
16
|
+
*
|
|
17
|
+
* This reads BUILT ASSETS FROM DISK. The provider never imports `@adonis-agora/flags-dashboard` —
|
|
18
|
+
* that package is a devDependency purely so the workspace build orders them.
|
|
19
|
+
*/
|
|
20
|
+
let spaDir;
|
|
21
|
+
function spaDirectory() {
|
|
22
|
+
spaDir ??= fileURLToPath(new URL('../assets/spa/', import.meta.url));
|
|
23
|
+
return spaDir;
|
|
24
|
+
}
|
|
25
|
+
/** Logged once at boot when `authorize` is omitted. Same wording in every Agora console. */
|
|
26
|
+
export const NO_AUTHORIZE_WARNING = '[@adonis-agora/flags] console has no `authorize` configured: it is open outside production and denies every request in production. Set `authorize` in config/flags_dashboard.ts.';
|
|
27
|
+
/** Logged at boot on a tenant, which has nothing to edit locally. */
|
|
28
|
+
export const TENANT_WARNING = '[@adonis-agora/flags] this app is a flags tenant: its flags are edited on the control-plane, so the console is not mounted here. Remove the dashboard provider or open the control-plane console.';
|
|
29
|
+
/**
|
|
30
|
+
* Mounts the flags console into an AdonisJS app: the `@adonis-agora/flags-dashboard` React SPA plus
|
|
31
|
+
* a JSON API over the booted flags runtime (`getRuntime()`), under a configurable path (default
|
|
32
|
+
* `/flags`).
|
|
33
|
+
*
|
|
34
|
+
* Every write goes through `FlagsAdmin`, so the console gets the validation, `authorize` hook,
|
|
35
|
+
* two-person approvals and audit trail the commands get. Writes are `POST`/`PUT`/`DELETE` only —
|
|
36
|
+
* never a `GET` a prefetcher could follow — and sit behind the same {@link enforce} guard as every
|
|
37
|
+
* read. CSRF is the host app's: `@adonisjs/shield` guards these routes like any other
|
|
38
|
+
* state-changing route of the app, and the SPA echoes its `XSRF-TOKEN` cookie in `x-xsrf-token`.
|
|
39
|
+
*
|
|
40
|
+
* Routes (relative to the configured `path`):
|
|
41
|
+
* - `GET /`, `/assets/:file` → the SPA
|
|
42
|
+
* - `GET /api/meta` → environments, approvals, the acting user
|
|
43
|
+
* - `GET /api/flags`, `/api/flags/:key` → list / one flag (definition, audit, schedules)
|
|
44
|
+
* - `PUT /api/flags/:key` `DELETE /api/flags/:key` → save / remove a definition
|
|
45
|
+
* - `POST /api/flags/:key/{enabled,rollout,variant,overrides,schedules}`
|
|
46
|
+
* - `POST /api/preview`, `/api/evaluate` → validate a draft / test a context
|
|
47
|
+
* - `GET /api/segments` `PUT|DELETE /api/segments/:key`
|
|
48
|
+
* - `GET /api/layers` `PUT|DELETE /api/layers/:key` `PUT /api/holdout`
|
|
49
|
+
* - `GET /api/experiments`, `/api/experiments/:key` `POST /api/experiments/:key/recompute`
|
|
50
|
+
* - `GET /api/change-requests` `POST /api/change-requests/:id/{approve,reject,cancel}`
|
|
51
|
+
* - `GET /api/audit`, `/api/schedules` `DELETE /api/schedules/:id`
|
|
52
|
+
* - `GET /api/export` `POST /api/import`, `/api/promote`
|
|
53
|
+
* - `GET /api/stale`, `/api/ops`
|
|
54
|
+
*
|
|
55
|
+
* On a `tenant` (no store, no admin) nothing is registered and a warning is logged.
|
|
56
|
+
*/
|
|
57
|
+
export default class FlagsDashboardProvider {
|
|
58
|
+
app;
|
|
59
|
+
constructor(app) {
|
|
60
|
+
this.app = app;
|
|
61
|
+
}
|
|
62
|
+
warnedOnAuthorizeThrow = false;
|
|
63
|
+
authorizeGuard = async () => ({
|
|
64
|
+
allowed: false,
|
|
65
|
+
status: 403,
|
|
66
|
+
reason: 'forbidden',
|
|
67
|
+
});
|
|
68
|
+
identity;
|
|
69
|
+
async boot() {
|
|
70
|
+
const config = resolveConfig(this.app.config.get('flags_dashboard', {}));
|
|
71
|
+
if (!config.enabled)
|
|
72
|
+
return;
|
|
73
|
+
const flagsConfig = this.app.config.get('flags', undefined);
|
|
74
|
+
if (flagsConfig?.topology === 'tenant') {
|
|
75
|
+
await this.warn(TENANT_WARNING);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
this.identity = flagsConfig?.identity;
|
|
79
|
+
this.authorizeGuard = await this.resolveGuard(config);
|
|
80
|
+
// The router is committed only after every provider's `boot()`: register in `booted`.
|
|
81
|
+
await this.app.booted(async () => {
|
|
82
|
+
const router = await this.app.container.make('router');
|
|
83
|
+
this.registerRoutes(router, config);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
registerRoutes(router, config) {
|
|
87
|
+
const api = `${config.path}/api`;
|
|
88
|
+
this.registerSpaRoutes(router, config, api);
|
|
89
|
+
const json = (handler) => async (ctx) => {
|
|
90
|
+
const guard = await this.enforce(config, ctx, 'api');
|
|
91
|
+
if (!guard.allowed)
|
|
92
|
+
return;
|
|
93
|
+
if (!hasRuntime()) {
|
|
94
|
+
return ctx.response.status(503).json({
|
|
95
|
+
error: '@adonis-agora/flags is not booted: register "@adonis-agora/flags/flags_provider" in adonisrc.ts',
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
try {
|
|
99
|
+
const actor = await this.actorOf(config, ctx);
|
|
100
|
+
const result = await handler({ runtime: getRuntime(), actor }, toApiRequest(ctx));
|
|
101
|
+
return ctx.response.status(result.status).json(result.body);
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
return ctx.response
|
|
105
|
+
.status(500)
|
|
106
|
+
.json({ error: error instanceof Error ? error.message : 'internal error' });
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
const name = (suffix) => `flags_dashboard.${suffix}`;
|
|
110
|
+
router.get(`${api}/meta`, json(meta)).as(name('meta'));
|
|
111
|
+
router.get(`${api}/flags`, json(listFlags)).as(name('flags'));
|
|
112
|
+
router.get(`${api}/flags/:key`, json(flagDetail)).as(name('flags.show'));
|
|
113
|
+
router.post(`${api}/flags`, json(createFlag)).as(name('flags.create'));
|
|
114
|
+
router.put(`${api}/flags/:key`, json(saveFlag)).as(name('flags.save'));
|
|
115
|
+
router
|
|
116
|
+
.put(`${api}/flags/:key/declaration`, json(updateDeclaration))
|
|
117
|
+
.as(name('flags.declaration'));
|
|
118
|
+
router.delete(`${api}/flags/:key`, json(deleteFlag)).as(name('flags.delete'));
|
|
119
|
+
router.post(`${api}/flags/:key/enabled`, json(setEnabled)).as(name('flags.enabled'));
|
|
120
|
+
router.post(`${api}/flags/:key/rollout`, json(setRollout)).as(name('flags.rollout'));
|
|
121
|
+
router.post(`${api}/flags/:key/variant`, json(setVariant)).as(name('flags.variant'));
|
|
122
|
+
router.post(`${api}/flags/:key/overrides`, json(setOverride)).as(name('flags.overrides'));
|
|
123
|
+
router.post(`${api}/flags/:key/schedules`, json(createSchedule)).as(name('flags.schedule'));
|
|
124
|
+
// Not writes, but they take a body (a draft definition, an evaluation context) — `POST`.
|
|
125
|
+
router.post(`${api}/preview`, json(preview)).as(name('preview'));
|
|
126
|
+
router.post(`${api}/evaluate`, json(evaluateContext)).as(name('evaluate'));
|
|
127
|
+
router.get(`${api}/segments`, json(listSegments)).as(name('segments'));
|
|
128
|
+
router.put(`${api}/segments/:key`, json(saveSegment)).as(name('segments.save'));
|
|
129
|
+
router.delete(`${api}/segments/:key`, json(deleteSegment)).as(name('segments.delete'));
|
|
130
|
+
router.get(`${api}/layers`, json(listLayers)).as(name('layers'));
|
|
131
|
+
router.put(`${api}/layers/:key`, json(saveLayer)).as(name('layers.save'));
|
|
132
|
+
router.delete(`${api}/layers/:key`, json(deleteLayer)).as(name('layers.delete'));
|
|
133
|
+
router.put(`${api}/holdout`, json(saveHoldout)).as(name('holdout.save'));
|
|
134
|
+
router.get(`${api}/experiments`, json(listExperiments)).as(name('experiments'));
|
|
135
|
+
router.get(`${api}/experiments/:key`, json(experimentDetail)).as(name('experiments.show'));
|
|
136
|
+
router
|
|
137
|
+
.post(`${api}/experiments/:key/recompute`, json(recomputeExperiment))
|
|
138
|
+
.as(name('experiments.recompute'));
|
|
139
|
+
router.get(`${api}/change-requests`, json(listChangeRequests)).as(name('requests'));
|
|
140
|
+
router
|
|
141
|
+
.post(`${api}/change-requests/:id/approve`, json(approveChangeRequest))
|
|
142
|
+
.as(name('requests.approve'));
|
|
143
|
+
router
|
|
144
|
+
.post(`${api}/change-requests/:id/reject`, json(rejectChangeRequest))
|
|
145
|
+
.as(name('requests.reject'));
|
|
146
|
+
router
|
|
147
|
+
.post(`${api}/change-requests/:id/cancel`, json(cancelChangeRequest))
|
|
148
|
+
.as(name('requests.cancel'));
|
|
149
|
+
router.get(`${api}/audit`, json(audit)).as(name('audit'));
|
|
150
|
+
router.get(`${api}/schedules`, json(listSchedules)).as(name('schedules'));
|
|
151
|
+
router.delete(`${api}/schedules/:id`, json(cancelSchedule)).as(name('schedules.cancel'));
|
|
152
|
+
router.get(`${api}/export`, json(exportRuleset)).as(name('export'));
|
|
153
|
+
router.post(`${api}/import`, json(importRuleset)).as(name('import'));
|
|
154
|
+
router.post(`${api}/promote`, json(promote)).as(name('promote'));
|
|
155
|
+
router.get(`${api}/stale`, json(stale)).as(name('stale'));
|
|
156
|
+
router.get(`${api}/ops`, json(ops)).as(name('ops'));
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Who is acting: the configured `actor`, else the authkit identity (its `sub` and name), else
|
|
160
|
+
* `ctx.auth.user`, else the anonymous `'dashboard'` (refused where approvals are on).
|
|
161
|
+
*/
|
|
162
|
+
async actorOf(config, ctx) {
|
|
163
|
+
if (!config.actor && this.identity?.actor) {
|
|
164
|
+
try {
|
|
165
|
+
return (await this.identity.actor(ctx)) ?? FALLBACK_ACTOR;
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
return FALLBACK_ACTOR;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (!config.actor) {
|
|
172
|
+
const identity = await authkitIdentity(ctx);
|
|
173
|
+
if (identity) {
|
|
174
|
+
const name = identity.profile?.name ?? identity.email;
|
|
175
|
+
return name ? { id: identity.userId, name } : { id: identity.userId };
|
|
176
|
+
}
|
|
177
|
+
return defaultActor(ctx);
|
|
178
|
+
}
|
|
179
|
+
try {
|
|
180
|
+
return toActor(await config.actor(ctx));
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
return FALLBACK_ACTOR;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/** Mount the React SPA at `config.path` plus its hashed asset bundle. */
|
|
187
|
+
registerSpaRoutes(router, config, api) {
|
|
188
|
+
const indexPath = config.path === '' ? '/' : config.path;
|
|
189
|
+
router
|
|
190
|
+
.get(indexPath, async (ctx) => {
|
|
191
|
+
if (!(await this.enforce(config, ctx, 'page')).allowed)
|
|
192
|
+
return;
|
|
193
|
+
let html;
|
|
194
|
+
try {
|
|
195
|
+
html = await readFile(resolvePath(spaDirectory(), 'index.html'), 'utf8');
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
return ctx.response
|
|
199
|
+
.status(404)
|
|
200
|
+
.send('The flags console SPA is not built. Run `pnpm --filter @adonis-agora/flags-dashboard build` (or the package build) to emit dist/spa.');
|
|
201
|
+
}
|
|
202
|
+
const environment = hasRuntime() ? getRuntime().manager.environment : 'production';
|
|
203
|
+
return ctx.response
|
|
204
|
+
.header('content-type', 'text/html; charset=utf-8')
|
|
205
|
+
.header('cache-control', 'no-store, must-revalidate')
|
|
206
|
+
.send(renderIndexHtml(html, config.path, api, environment));
|
|
207
|
+
})
|
|
208
|
+
.as('flags_dashboard.index');
|
|
209
|
+
router
|
|
210
|
+
.get(`${config.path}/assets/:file`, async (ctx) => {
|
|
211
|
+
if (!(await this.enforce(config, ctx, 'page')).allowed)
|
|
212
|
+
return;
|
|
213
|
+
const file = basename(String(ctx.params.file));
|
|
214
|
+
const root = resolvePath(spaDirectory(), 'assets');
|
|
215
|
+
const assetPath = resolvePath(root, file);
|
|
216
|
+
if (!assetPath.startsWith(root))
|
|
217
|
+
return ctx.response.status(404).send('');
|
|
218
|
+
let bytes;
|
|
219
|
+
try {
|
|
220
|
+
bytes = await readFile(assetPath);
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
return ctx.response.status(404).send('');
|
|
224
|
+
}
|
|
225
|
+
return ctx.response
|
|
226
|
+
.header('content-type', contentTypeFor(file))
|
|
227
|
+
.header('cache-control', 'public, max-age=31536000, immutable')
|
|
228
|
+
.send(bytes);
|
|
229
|
+
})
|
|
230
|
+
.as('flags_dashboard.assets');
|
|
231
|
+
}
|
|
232
|
+
async warn(message) {
|
|
233
|
+
try {
|
|
234
|
+
const logger = await this.app.container.make('logger');
|
|
235
|
+
logger.warn(message);
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
// Logging is best-effort: a missing logger must not stop the app from booting.
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* The `authorize` option turned into one guard. Omitted: open outside production, every request
|
|
243
|
+
* refused (`403`) in production; either way it says so once at boot.
|
|
244
|
+
*/
|
|
245
|
+
async resolveGuard(config) {
|
|
246
|
+
if (config.authorize)
|
|
247
|
+
return resolveConsoleAuthorize(config.authorize);
|
|
248
|
+
const identity = this.identity;
|
|
249
|
+
if (identity?.authorizeConsole) {
|
|
250
|
+
return resolveConsoleAuthorize((ctx) => identity.authorizeConsole(ctx));
|
|
251
|
+
}
|
|
252
|
+
await this.warn(NO_AUTHORIZE_WARNING);
|
|
253
|
+
if (this.app.inProduction !== true)
|
|
254
|
+
return async () => ({ allowed: true });
|
|
255
|
+
return async () => ({ allowed: false, status: 403, reason: 'forbidden' });
|
|
256
|
+
}
|
|
257
|
+
async warnAuthorizeThrow(hookError) {
|
|
258
|
+
if (this.warnedOnAuthorizeThrow)
|
|
259
|
+
return;
|
|
260
|
+
this.warnedOnAuthorizeThrow = true;
|
|
261
|
+
const message = hookError instanceof Error ? hookError.message : String(hookError);
|
|
262
|
+
await this.warn(`flags dashboard authorize hook threw; treating as denial (403). ${message}`);
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Run the `authorize` gate. A denial answers `401`/`403` — the access-denied PAGE for a page
|
|
266
|
+
* navigation, `{ error }` JSON for an API call; `{ redirectTo }` is a `302` for a page and
|
|
267
|
+
* `401 { error, redirectTo }` for the API. A hook that already answered keeps its answer.
|
|
268
|
+
*/
|
|
269
|
+
async enforce(config, ctx, mode) {
|
|
270
|
+
// Never `if (!(await authorize(ctx)))`: a `{ allowed: false }` decision is truthy.
|
|
271
|
+
const decision = await this.authorizeGuard(ctx);
|
|
272
|
+
if (decision.allowed)
|
|
273
|
+
return { allowed: true };
|
|
274
|
+
if (decision.status === 403 && decision.error !== undefined) {
|
|
275
|
+
await this.warnAuthorizeThrow(decision.error);
|
|
276
|
+
}
|
|
277
|
+
if (decision.status === 302) {
|
|
278
|
+
if (responseAnswered(ctx))
|
|
279
|
+
return { allowed: false };
|
|
280
|
+
if (mode === 'page')
|
|
281
|
+
ctx.response.redirect(decision.redirectTo);
|
|
282
|
+
else {
|
|
283
|
+
ctx.response
|
|
284
|
+
.status(401)
|
|
285
|
+
.json({ error: 'unauthenticated', redirectTo: decision.redirectTo });
|
|
286
|
+
}
|
|
287
|
+
return { allowed: false };
|
|
288
|
+
}
|
|
289
|
+
if (mode === 'page') {
|
|
290
|
+
await this.denyPage(ctx, config, { status: decision.status, reason: decision.reason });
|
|
291
|
+
}
|
|
292
|
+
else if (!responseAnswered(ctx)) {
|
|
293
|
+
ctx.response
|
|
294
|
+
.status(decision.status)
|
|
295
|
+
.json({ error: decision.status === 401 ? 'unauthenticated' : 'forbidden' });
|
|
296
|
+
}
|
|
297
|
+
return { allowed: false };
|
|
298
|
+
}
|
|
299
|
+
/** Answer a refused PAGE navigation with HTML: the built-in page or the host's own. */
|
|
300
|
+
async denyPage(ctx, config, denial) {
|
|
301
|
+
const answered = () => responseAnswered(ctx);
|
|
302
|
+
if (answered())
|
|
303
|
+
return;
|
|
304
|
+
const nonce = cspNonce(ctx);
|
|
305
|
+
const info = {
|
|
306
|
+
...denial,
|
|
307
|
+
basePath: config.path,
|
|
308
|
+
...(nonce !== undefined ? { nonce } : {}),
|
|
309
|
+
};
|
|
310
|
+
const html = await resolveAccessDeniedPage(info, config.accessDenied, ctx, answered);
|
|
311
|
+
if (html === null)
|
|
312
|
+
return;
|
|
313
|
+
ctx.response
|
|
314
|
+
.status(info.status)
|
|
315
|
+
.header('content-type', 'text/html; charset=utf-8')
|
|
316
|
+
.header('cache-control', 'no-store, must-revalidate')
|
|
317
|
+
.send(html);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
/** Whether something already answered this request (a redirect or a queued body). */
|
|
321
|
+
function responseAnswered(ctx) {
|
|
322
|
+
if (ctx.response.getHeader('location'))
|
|
323
|
+
return true;
|
|
324
|
+
const response = ctx.response;
|
|
325
|
+
return response.hasLazyBody === true || response.headersSent === true;
|
|
326
|
+
}
|
|
327
|
+
/** The request's CSP nonce when the host runs `@adonisjs/shield` with `@nonce`. */
|
|
328
|
+
function cspNonce(ctx) {
|
|
329
|
+
const nonce = ctx.response.nonce;
|
|
330
|
+
return typeof nonce === 'string' && nonce !== '' ? nonce : undefined;
|
|
331
|
+
}
|
|
332
|
+
/** Adapt an AdonisJS `HttpContext` to the framework-light {@link ApiRequest}. */
|
|
333
|
+
function toApiRequest(ctx) {
|
|
334
|
+
return {
|
|
335
|
+
params: ctx.params,
|
|
336
|
+
query: ctx.request.qs(),
|
|
337
|
+
body: ctx.request.body(),
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
//# sourceMappingURL=dashboard_provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard_provider.js","sourceRoot":"","sources":["../../providers/dashboard_provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { ApplicationService } from '@adonisjs/core/types';
|
|
2
|
+
import type { FlagsManager } from '../src/manager.js';
|
|
3
|
+
import { type FlagsRuntime } from '../src/runtime.js';
|
|
4
|
+
declare module '@adonisjs/core/types' {
|
|
5
|
+
interface ContainerBindings {
|
|
6
|
+
'flags.manager': FlagsManager;
|
|
7
|
+
'flags.runtime': FlagsRuntime;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Builds the flags runtime from `config/flags.ts` once the app has booted, publishes it to the
|
|
12
|
+
* container (`flags.manager`, `flags.runtime`) and to `services/main`, mounts the control-plane
|
|
13
|
+
* routes, and decides where background work runs:
|
|
14
|
+
*
|
|
15
|
+
* - `role: 'api'` — never runs background work.
|
|
16
|
+
* - `dispatcher: 'durable'` (or `auto` with the durable provider registered) — registers durable
|
|
17
|
+
* workflows and schedules; the durable worker runs them.
|
|
18
|
+
* - `dispatcher: 'in-process'` (or `auto` without durable) — a timer in each web/worker process;
|
|
19
|
+
* leases make concurrent replicas safe.
|
|
20
|
+
* - Ace commands never start the loop, except `node ace flags:work`.
|
|
21
|
+
*/
|
|
22
|
+
export default class FlagsProvider {
|
|
23
|
+
#private;
|
|
24
|
+
protected app: ApplicationService;
|
|
25
|
+
constructor(app: ApplicationService);
|
|
26
|
+
register(): void;
|
|
27
|
+
boot(): Promise<void>;
|
|
28
|
+
shutdown(): Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=flags_provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flags_provider.d.ts","sourceRoot":"","sources":["../../providers/flags_provider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAM/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAKrE,OAAO,QAAQ,sBAAsB,CAAC;IACpC,UAAU,iBAAiB;QACzB,eAAe,EAAE,YAAY,CAAC;QAC9B,eAAe,EAAE,YAAY,CAAC;KAC/B;CACF;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,OAAO,OAAO,aAAa;;IAIpB,SAAS,CAAC,GAAG,EAAE,kBAAkB;IAA7C,YAAsB,GAAG,EAAE,kBAAkB,EAAI;IAEjD,QAAQ,SAGP;IA2HK,IAAI,kBAuBT;IAgCK,QAAQ,kBAKb;CACF"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { registerDurableWorkflows } from '../src/durable.js';
|
|
3
|
+
import { browserSecret, registerBrowser } from '../src/http/browser.js';
|
|
4
|
+
import { ControlPlane } from '../src/http/control_plane.js';
|
|
5
|
+
import { registerEdgeTag } from '../src/http/edge_tag.js';
|
|
6
|
+
import { createRuntime } from '../src/runtime.js';
|
|
7
|
+
import { setRuntime } from '../src/services/accessor.js';
|
|
8
|
+
/**
|
|
9
|
+
* Builds the flags runtime from `config/flags.ts` once the app has booted, publishes it to the
|
|
10
|
+
* container (`flags.manager`, `flags.runtime`) and to `services/main`, mounts the control-plane
|
|
11
|
+
* routes, and decides where background work runs:
|
|
12
|
+
*
|
|
13
|
+
* - `role: 'api'` — never runs background work.
|
|
14
|
+
* - `dispatcher: 'durable'` (or `auto` with the durable provider registered) — registers durable
|
|
15
|
+
* workflows and schedules; the durable worker runs them.
|
|
16
|
+
* - `dispatcher: 'in-process'` (or `auto` without durable) — a timer in each web/worker process;
|
|
17
|
+
* leases make concurrent replicas safe.
|
|
18
|
+
* - Ace commands never start the loop, except `node ace flags:work`.
|
|
19
|
+
*/
|
|
20
|
+
export default class FlagsProvider {
|
|
21
|
+
app;
|
|
22
|
+
#runtime;
|
|
23
|
+
#building;
|
|
24
|
+
constructor(app) {
|
|
25
|
+
this.app = app;
|
|
26
|
+
}
|
|
27
|
+
register() {
|
|
28
|
+
this.app.container.singleton('flags.runtime', () => this.#build());
|
|
29
|
+
this.app.container.singleton('flags.manager', async () => (await this.#build()).manager);
|
|
30
|
+
}
|
|
31
|
+
#config() {
|
|
32
|
+
const config = this.app.config.get('flags');
|
|
33
|
+
if (!config)
|
|
34
|
+
throw new Error('config/flags.ts is missing (node ace configure @adonis-agora/flags)');
|
|
35
|
+
return config;
|
|
36
|
+
}
|
|
37
|
+
#build() {
|
|
38
|
+
this.#building ??= (async () => {
|
|
39
|
+
const config = this.#config();
|
|
40
|
+
const container = this.app.container;
|
|
41
|
+
const logger = await container.make('logger');
|
|
42
|
+
const environment = this.app.getEnvironment();
|
|
43
|
+
const ownsState = config.topology !== 'tenant';
|
|
44
|
+
const lucid = ownsState && container.hasBinding('lucid.db');
|
|
45
|
+
const runtime = await createRuntime(config, {
|
|
46
|
+
app: this.app,
|
|
47
|
+
...(this.#packageName() ? { appName: this.#packageName() } : {}),
|
|
48
|
+
async db(connection) {
|
|
49
|
+
if (!lucid)
|
|
50
|
+
throw new Error('@adonisjs/lucid is not configured');
|
|
51
|
+
const db = (await container.make('lucid.db'));
|
|
52
|
+
return db.connection(connection);
|
|
53
|
+
},
|
|
54
|
+
async redis(connection) {
|
|
55
|
+
if (!container.hasBinding('redis'))
|
|
56
|
+
throw new Error('@adonisjs/redis is not configured');
|
|
57
|
+
const redis = (await container.make('redis'));
|
|
58
|
+
return redis.connection(connection).ioConnection;
|
|
59
|
+
},
|
|
60
|
+
autoCreateSchema: config.autoCreateSchema ?? true,
|
|
61
|
+
partitionEvents: config.partitionEvents ?? false,
|
|
62
|
+
}, {
|
|
63
|
+
logger,
|
|
64
|
+
// Timers run in servers and tests; one-shot ace commands only read and write.
|
|
65
|
+
start: true,
|
|
66
|
+
runWorker: false,
|
|
67
|
+
// A held LISTEN connection keeps `db.manager.closeAll()` waiting: ace commands
|
|
68
|
+
// (migration:run, db:seed…) would never exit.
|
|
69
|
+
listen: environment !== 'console' && environment !== 'repl',
|
|
70
|
+
onApplied: () => { },
|
|
71
|
+
});
|
|
72
|
+
this.#runtime = runtime;
|
|
73
|
+
setRuntime(runtime);
|
|
74
|
+
if (ownsState &&
|
|
75
|
+
runtime.role !== 'api' &&
|
|
76
|
+
environment !== 'console' &&
|
|
77
|
+
environment !== 'repl') {
|
|
78
|
+
await this.#startBackground(runtime, logger);
|
|
79
|
+
}
|
|
80
|
+
const realtime = config.realtime;
|
|
81
|
+
if (realtime)
|
|
82
|
+
await this.#realtime(runtime, realtime, logger);
|
|
83
|
+
return runtime;
|
|
84
|
+
})();
|
|
85
|
+
return this.#building;
|
|
86
|
+
}
|
|
87
|
+
async #durableEngine() {
|
|
88
|
+
try {
|
|
89
|
+
const durable = (await import('@adonis-agora/durable'));
|
|
90
|
+
if (!this.app.container.hasBinding(durable.WorkflowEngine))
|
|
91
|
+
return undefined;
|
|
92
|
+
return (await this.app.container.make(durable.WorkflowEngine));
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async #startBackground(runtime, logger) {
|
|
99
|
+
const dispatcher = runtime.config.dispatcher ?? 'auto';
|
|
100
|
+
if (dispatcher !== 'in-process') {
|
|
101
|
+
const engine = await this.#durableEngine();
|
|
102
|
+
if (engine && registerDurableWorkflows(engine, runtime)) {
|
|
103
|
+
logger.info('[flags] background work runs as durable workflows');
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (dispatcher === 'durable') {
|
|
107
|
+
throw new Error('[flags] dispatcher "durable" needs @adonis-agora/durable with its provider registered (and a version with registerSchedules)');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
runtime.worker?.start();
|
|
111
|
+
}
|
|
112
|
+
async #realtime(runtime, realtime, logger) {
|
|
113
|
+
const channel = (typeof realtime === 'object' && realtime.channel) || 'flags/ruleset';
|
|
114
|
+
try {
|
|
115
|
+
const transmit = (await import('@adonisjs/transmit/services/main')).default;
|
|
116
|
+
runtime.source.onChange((ruleset) => transmit.broadcast(channel, { version: ruleset.version }));
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
logger.warn('[flags] realtime is on but @adonisjs/transmit is not installed/configured');
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
async boot() {
|
|
123
|
+
await this.app.booted(async () => {
|
|
124
|
+
const runtime = await this.#build();
|
|
125
|
+
const config = this.#config();
|
|
126
|
+
// `@flag` in Edge views, when the app renders Edge at all.
|
|
127
|
+
await registerEdgeTag();
|
|
128
|
+
if (runtime.role === 'worker')
|
|
129
|
+
return;
|
|
130
|
+
const router = await this.app.container.make('router');
|
|
131
|
+
const secret = browserSecret(runtime, this.#appKey());
|
|
132
|
+
let controlPlane;
|
|
133
|
+
if (config.topology === 'control-plane') {
|
|
134
|
+
controlPlane = new ControlPlane(runtime, config.controlPlane, secret);
|
|
135
|
+
controlPlane.register(router);
|
|
136
|
+
}
|
|
137
|
+
if (config.browser) {
|
|
138
|
+
const logger = await this.app.container.make('logger');
|
|
139
|
+
runtime.browser = registerBrowser(router, runtime, {
|
|
140
|
+
secret,
|
|
141
|
+
controlPlane,
|
|
142
|
+
logger,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* The app's name from its package.json (`@acme/shop` → `shop`). AdonisJS 7's `appName` is always
|
|
149
|
+
* `adonisjs_app`, which would tag every app on a control-plane alike.
|
|
150
|
+
*/
|
|
151
|
+
#packageName() {
|
|
152
|
+
try {
|
|
153
|
+
const raw = readFileSync(this.app.makePath('package.json'), 'utf8');
|
|
154
|
+
const name = JSON.parse(raw).name;
|
|
155
|
+
if (typeof name !== 'string' || !name)
|
|
156
|
+
return undefined;
|
|
157
|
+
return name.replace(/^@[^/]+\//, '');
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* The app key: `app.appKey` (AdonisJS 6), else the first key of the default encryptor
|
|
165
|
+
* (`config/encryption.ts`, AdonisJS 7), else `APP_KEY`.
|
|
166
|
+
*/
|
|
167
|
+
#appKey() {
|
|
168
|
+
const legacy = this.app.config.get('app.appKey', undefined);
|
|
169
|
+
if (legacy)
|
|
170
|
+
return legacy;
|
|
171
|
+
const encryption = this.app.config.get('encryption', undefined);
|
|
172
|
+
const encryptor = encryption?.list?.[encryption.default ?? ''];
|
|
173
|
+
if (encryptor?.keys?.[0])
|
|
174
|
+
return encryptor.keys[0];
|
|
175
|
+
return process.env.APP_KEY;
|
|
176
|
+
}
|
|
177
|
+
async shutdown() {
|
|
178
|
+
await this.#runtime?.close();
|
|
179
|
+
setRuntime(undefined);
|
|
180
|
+
this.#runtime = undefined;
|
|
181
|
+
this.#building = undefined;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=flags_provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flags_provider.js","sourceRoot":"","sources":["../../providers/flags_provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { FlagsManager } from '../src/manager.js';
|
|
2
|
+
/**
|
|
3
|
+
* The flags manager, ready to use:
|
|
4
|
+
*
|
|
5
|
+
* ```ts
|
|
6
|
+
* import flags from '@adonis-agora/flags/services/main'
|
|
7
|
+
*
|
|
8
|
+
* if (await flags.for(user).enabled('new_player')) { … }
|
|
9
|
+
* await flags.track(user, 'purchase', { value: order.total, client: trx })
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* Resolved from the container (`flags.manager`), so rebinding it in a test changes what app code
|
|
13
|
+
* gets. In HTTP handlers, `ctx.flags` (from the middleware) is the per-request scope.
|
|
14
|
+
*/
|
|
15
|
+
declare let flags: FlagsManager;
|
|
16
|
+
export { flags as default };
|
|
17
|
+
//# sourceMappingURL=main.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../services/main.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD;;;;;;;;;;;;GAYG;AACH,QAAA,IAAI,KAAK,EAAE,YAAY,CAAC;AAMxB,OAAO,EAAE,KAAK,IAAI,OAAO,EAAE,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import app from '@adonisjs/core/services/app';
|
|
2
|
+
/**
|
|
3
|
+
* The flags manager, ready to use:
|
|
4
|
+
*
|
|
5
|
+
* ```ts
|
|
6
|
+
* import flags from '@adonis-agora/flags/services/main'
|
|
7
|
+
*
|
|
8
|
+
* if (await flags.for(user).enabled('new_player')) { … }
|
|
9
|
+
* await flags.track(user, 'purchase', { value: order.total, client: trx })
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* Resolved from the container (`flags.manager`), so rebinding it in a test changes what app code
|
|
13
|
+
* gets. In HTTP handlers, `ctx.flags` (from the middleware) is the per-request scope.
|
|
14
|
+
*/
|
|
15
|
+
let flags;
|
|
16
|
+
await app.booted(async () => {
|
|
17
|
+
flags = await app.container.make('flags.manager');
|
|
18
|
+
});
|
|
19
|
+
export { flags as default };
|
|
20
|
+
//# sourceMappingURL=main.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../services/main.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,6BAA6B,CAAC;AAG9C;;;;;;;;;;;;GAYG;AACH,IAAI,KAAmB,CAAC;AAExB,MAAM,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE;IAC1B,KAAK,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;AACpD,CAAC,CAAC,CAAC;AAEH,OAAO,EAAE,KAAK,IAAI,OAAO,EAAE,CAAC"}
|