@persei/perseed-api 5.0.23 → 5.0.25
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/dist/client.cjs +57 -0
- package/dist/client.cjs.map +1 -1
- package/dist/client.mjs +57 -0
- package/dist/client.mjs.map +1 -1
- package/dist/dates.helper-CDM5aEJG.cjs.map +1 -1
- package/dist/dates.helper-XRCJ_UAQ.js.map +1 -1
- package/dist/dates.schema-BqkBcmM6.js +18 -0
- package/dist/dates.schema-BqkBcmM6.js.map +1 -0
- package/dist/dates.schema-npKpToAJ.cjs +17 -0
- package/dist/dates.schema-npKpToAJ.cjs.map +1 -0
- package/dist/ecosystem-container-widget.cjs +1 -1
- package/dist/ecosystem-container-widget.mjs +1 -1
- package/dist/ecosystem-process-log.cjs +209 -0
- package/dist/ecosystem-process-log.cjs.map +1 -0
- package/dist/ecosystem-process-log.d.ts +1 -0
- package/dist/ecosystem-process-log.mjs +209 -0
- package/dist/ecosystem-process-log.mjs.map +1 -0
- package/dist/global-dates.cjs +5 -6
- package/dist/global-dates.cjs.map +1 -1
- package/dist/global-dates.mjs +5 -6
- package/dist/global-dates.mjs.map +1 -1
- package/dist/lib/src/generated/client.d.ts +247 -0
- package/dist/lib/src/generated/client.d.ts.map +1 -1
- package/dist/src/Services/ProcessLogService.d.ts.map +1 -1
- package/dist/src/Services/QueryService.d.ts.map +1 -1
- package/dist/src/app.d.ts +2 -2
- package/dist/src/app.d.ts.map +1 -1
- package/dist/src/controllers/IntrospectionController.d.ts.map +1 -1
- package/dist/src/models/project/Displayer.d.ts.map +1 -1
- package/dist/src/models/project/DisplayerMeta.d.ts +2 -1
- package/dist/src/models/project/DisplayerMeta.d.ts.map +1 -1
- package/dist/src/models/project/QuestionariesInfo.d.ts +2 -1
- package/dist/src/models/project/QuestionariesInfo.d.ts.map +1 -1
- package/dist/src/schemas/process_log/create_process_log_payload.schema.json +12 -1
- package/dist/src/schemas/process_log/types.d.ts +8 -5
- package/dist/src/schemas/process_log/types.d.ts.map +1 -1
- package/dist/src/test/test-helpers.d.ts +12 -0
- package/dist/src/test/test-helpers.d.ts.map +1 -1
- package/dist/src/v2/modules/ecosystem/action-system/action-system.service/automatic-trigger.service.d.ts +4 -4
- package/dist/src/v2/modules/ecosystem/action-system/action-system.service/manual-trigger-engine.service.d.ts.map +1 -1
- package/dist/src/v2/modules/ecosystem/action-system/action-system.service/manual-trigger.service.d.ts +8 -8
- package/dist/src/v2/modules/ecosystem/action-system/action-system.service/trigger-engine.service.d.ts +18 -1
- package/dist/src/v2/modules/ecosystem/action-system/action-system.service/trigger-engine.service.d.ts.map +1 -1
- package/dist/src/v2/modules/ecosystem/action-system/index.d.ts +1 -1
- package/dist/src/v2/modules/ecosystem/action-system/index.d.ts.map +1 -1
- package/dist/src/v2/modules/ecosystem/alert/alert.controller.d.ts +3 -3
- package/dist/src/v2/modules/ecosystem/alert/alert.controller.d.ts.map +1 -1
- package/dist/src/v2/modules/ecosystem/alert/alert.model.d.ts +15 -2
- package/dist/src/v2/modules/ecosystem/alert/alert.model.d.ts.map +1 -1
- package/dist/src/v2/modules/ecosystem/alert/alert.schema.d.ts +14 -5
- package/dist/src/v2/modules/ecosystem/alert/alert.schema.d.ts.map +1 -1
- package/dist/src/v2/modules/ecosystem/alert/alert.service.d.ts.map +1 -1
- package/dist/src/v2/modules/ecosystem/alert/index.d.ts +1 -1
- package/dist/src/v2/modules/ecosystem/alert/index.d.ts.map +1 -1
- package/dist/src/v2/modules/ecosystem/process-log/index.d.ts +4 -1
- package/dist/src/v2/modules/ecosystem/process-log/index.d.ts.map +1 -1
- package/dist/src/v2/modules/ecosystem/process-log/lib.d.ts +2 -0
- package/dist/src/v2/modules/ecosystem/process-log/lib.d.ts.map +1 -0
- package/dist/src/v2/modules/ecosystem/process-log/process-log.controller.d.ts +5 -0
- package/dist/src/v2/modules/ecosystem/process-log/process-log.controller.d.ts.map +1 -0
- package/dist/src/v2/modules/ecosystem/process-log/process-log.controller.e2e.d.ts +2 -0
- package/dist/src/v2/modules/ecosystem/process-log/process-log.controller.e2e.d.ts.map +1 -0
- package/dist/src/v2/modules/ecosystem/process-log/process-log.controller.test.d.ts +2 -0
- package/dist/src/v2/modules/ecosystem/process-log/process-log.controller.test.d.ts.map +1 -0
- package/dist/src/v2/modules/ecosystem/process-log/process-log.model.d.ts +9 -2
- package/dist/src/v2/modules/ecosystem/process-log/process-log.model.d.ts.map +1 -1
- package/dist/src/v2/modules/ecosystem/process-log/process-log.schema.d.ts +111 -0
- package/dist/src/v2/modules/ecosystem/process-log/process-log.schema.d.ts.map +1 -0
- package/dist/src/v2/modules/ecosystem/process-log/process-log.service.d.ts +16 -0
- package/dist/src/v2/modules/ecosystem/process-log/process-log.service.d.ts.map +1 -1
- package/dist/src/v2/modules/global/dates/{dates.helper.d.ts → dates.helper/dates.helper.d.ts} +1 -1
- package/dist/src/v2/modules/global/dates/dates.helper/dates.helper.d.ts.map +1 -0
- package/dist/src/v2/modules/global/dates/dates.helper/dates.helper.test.d.ts.map +1 -0
- package/dist/src/v2/modules/global/dates/dates.helper/decoding-validator.helper.d.ts +75 -0
- package/dist/src/v2/modules/global/dates/dates.helper/decoding-validator.helper.d.ts.map +1 -0
- package/dist/src/v2/modules/global/dates/dates.helper/decoding-validator.helper.test.d.ts +2 -0
- package/dist/src/v2/modules/global/dates/dates.helper/decoding-validator.helper.test.d.ts.map +1 -0
- package/dist/src/v2/modules/global/dates/dates.helper/index.d.ts +3 -0
- package/dist/src/v2/modules/global/dates/dates.helper/index.d.ts.map +1 -0
- package/dist/src/v2/modules/global/dates/dates.schema.d.ts +23 -0
- package/dist/src/v2/modules/global/dates/dates.schema.d.ts.map +1 -1
- package/dist/src/v2/routes/v2/ecosystem/_ecosystemName/alert/index.d.ts +1 -1
- package/dist/src/v2/routes/v2/ecosystem/_ecosystemName/project/_projectName/alert/index.d.ts +1 -1
- package/dist/src/v2/routes/v2/ecosystem/_ecosystemName/project/_projectName/process-log/index.d.ts +3 -0
- package/dist/src/v2/routes/v2/ecosystem/_ecosystemName/project/_projectName/process-log/index.d.ts.map +1 -0
- package/dist/v1/perseed-api.cjs +0 -7
- package/dist/v1/perseed-api.cjs.map +1 -1
- package/dist/v1/perseed-api.mjs +0 -7
- package/dist/v1/perseed-api.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/src/v2/modules/global/dates/dates.helper.d.ts.map +0 -1
- package/dist/src/v2/modules/global/dates/dates.helper.test.d.ts.map +0 -1
- /package/dist/src/v2/modules/global/dates/{dates.helper.test.d.ts → dates.helper/dates.helper.test.d.ts} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dates.helper-CDM5aEJG.cjs","sources":["../../src/v2/modules/global/dates/dates.helper.ts"],"sourcesContent":["import dayjs from 'dayjs'\nimport utcPlugin from 'dayjs/plugin/utc'\nimport type { PeriodUnit } from '
|
|
1
|
+
{"version":3,"file":"dates.helper-CDM5aEJG.cjs","sources":["../../src/v2/modules/global/dates/dates.helper/dates.helper.ts"],"sourcesContent":["import dayjs from 'dayjs'\nimport utcPlugin from 'dayjs/plugin/utc'\nimport type { PeriodUnit } from '../dates.schema'\n\n/**\n * Generic calendar primitives — period alignment and whole-period arithmetic. Built on `dayjs`\n * (already used by every consumer), so calendar arithmetic and month-end clamping come for free.\n *\n * These functions are locale-agnostic: the week start is always an injected number (1 = Monday …\n * 7 = Sunday), never derived here. Callers that need a locale-aware week start resolve it with\n * `global/locale`'s `getWeekStart(locale)` and pass the result in. That keeps this module free of\n * any dependency on other v2 modules.\n *\n * The `utc` flag selects the calendar the alignment runs in: `false` (default) uses the ambient\n * local calendar (a viewer's timezone); `true` uses UTC (the backend). Everything else is shared.\n */\n\ndayjs.extend(utcPlugin)\n\n// ISO Monday — the week start assumed when the caller doesn't inject a locale-derived one. Matches\n// DEFAULT_LOCALE (es-ES), whose week also starts on Monday.\nexport const DEFAULT_WEEK_START = 1\n\n// Builds the dayjs instance in the requested calendar (UTC or ambient local).\nexport function toCalendar(ms: number, utc: boolean): dayjs.Dayjs {\n return utc ? dayjs.utc(ms) : dayjs(ms)\n}\n\n// dayjs `.day()` is 0 = Sunday … 6 = Saturday; convert to ISO 1 = Monday … 7 = Sunday.\nfunction isoWeekday(d: dayjs.Dayjs): number {\n const day = d.day()\n return day === 0 ? 7 : day\n}\n\n/**\n * Aligns an instant to the start of the calendar period it falls in:\n * weeks → the injected first weekday at midnight, months → the 1st at midnight,\n * days → midnight, hours → the start of the hour. `utc` runs the alignment in UTC.\n */\nexport function getPeriodStart(\n ms: number,\n unit: PeriodUnit,\n weekStart: number = DEFAULT_WEEK_START,\n utc = false,\n): number {\n const d = toCalendar(ms, utc)\n if (unit === 'week') {\n // Not `startOf('week')`: that follows the dayjs locale, but the week start here is caller-driven.\n const diff = (isoWeekday(d) - weekStart + 7) % 7\n return d.subtract(diff, 'day').startOf('day').valueOf()\n }\n return d.startOf(unit).valueOf()\n}\n\n/**\n * Subtracts `value` whole calendar periods from an instant, without aligning. Month subtraction\n * clamps to the last day of the target month (e.g. 31 Mar − 1 month → 28 Feb), which dayjs does\n * natively. `utc` runs the arithmetic in UTC.\n */\nexport function subtractPeriods(ms: number, value: number, unit: PeriodUnit, utc = false): number {\n return toCalendar(ms, utc).subtract(value, unit).valueOf()\n}\n"],"names":[],"mappings":";;;AAiBA,MAAM,OAAO,SAAS;AAIf,MAAM,qBAAqB;AAG3B,SAAS,WAAW,IAAY,KAA2B;AAChE,SAAO,MAAM,MAAM,IAAI,EAAE,IAAI,MAAM,EAAE;AACvC;AAGA,SAAS,WAAW,GAAwB;AAC1C,QAAM,MAAM,EAAE,IAAA;AACd,SAAO,QAAQ,IAAI,IAAI;AACzB;AAOO,SAAS,eACd,IACA,MACA,YAAoB,oBACpB,MAAM,OACE;AACR,QAAM,IAAI,WAAW,IAAI,GAAG;AAC5B,MAAI,SAAS,QAAQ;AAEnB,UAAM,QAAQ,WAAW,CAAC,IAAI,YAAY,KAAK;AAC/C,WAAO,EAAE,SAAS,MAAM,KAAK,EAAE,QAAQ,KAAK,EAAE,QAAA;AAAA,EAChD;AACA,SAAO,EAAE,QAAQ,IAAI,EAAE,QAAA;AACzB;AAOO,SAAS,gBAAgB,IAAY,OAAe,MAAkB,MAAM,OAAe;AAChG,SAAO,WAAW,IAAI,GAAG,EAAE,SAAS,OAAO,IAAI,EAAE,QAAA;AACnD;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dates.helper-XRCJ_UAQ.js","sources":["../../src/v2/modules/global/dates/dates.helper.ts"],"sourcesContent":["import dayjs from 'dayjs'\nimport utcPlugin from 'dayjs/plugin/utc'\nimport type { PeriodUnit } from '
|
|
1
|
+
{"version":3,"file":"dates.helper-XRCJ_UAQ.js","sources":["../../src/v2/modules/global/dates/dates.helper/dates.helper.ts"],"sourcesContent":["import dayjs from 'dayjs'\nimport utcPlugin from 'dayjs/plugin/utc'\nimport type { PeriodUnit } from '../dates.schema'\n\n/**\n * Generic calendar primitives — period alignment and whole-period arithmetic. Built on `dayjs`\n * (already used by every consumer), so calendar arithmetic and month-end clamping come for free.\n *\n * These functions are locale-agnostic: the week start is always an injected number (1 = Monday …\n * 7 = Sunday), never derived here. Callers that need a locale-aware week start resolve it with\n * `global/locale`'s `getWeekStart(locale)` and pass the result in. That keeps this module free of\n * any dependency on other v2 modules.\n *\n * The `utc` flag selects the calendar the alignment runs in: `false` (default) uses the ambient\n * local calendar (a viewer's timezone); `true` uses UTC (the backend). Everything else is shared.\n */\n\ndayjs.extend(utcPlugin)\n\n// ISO Monday — the week start assumed when the caller doesn't inject a locale-derived one. Matches\n// DEFAULT_LOCALE (es-ES), whose week also starts on Monday.\nexport const DEFAULT_WEEK_START = 1\n\n// Builds the dayjs instance in the requested calendar (UTC or ambient local).\nexport function toCalendar(ms: number, utc: boolean): dayjs.Dayjs {\n return utc ? dayjs.utc(ms) : dayjs(ms)\n}\n\n// dayjs `.day()` is 0 = Sunday … 6 = Saturday; convert to ISO 1 = Monday … 7 = Sunday.\nfunction isoWeekday(d: dayjs.Dayjs): number {\n const day = d.day()\n return day === 0 ? 7 : day\n}\n\n/**\n * Aligns an instant to the start of the calendar period it falls in:\n * weeks → the injected first weekday at midnight, months → the 1st at midnight,\n * days → midnight, hours → the start of the hour. `utc` runs the alignment in UTC.\n */\nexport function getPeriodStart(\n ms: number,\n unit: PeriodUnit,\n weekStart: number = DEFAULT_WEEK_START,\n utc = false,\n): number {\n const d = toCalendar(ms, utc)\n if (unit === 'week') {\n // Not `startOf('week')`: that follows the dayjs locale, but the week start here is caller-driven.\n const diff = (isoWeekday(d) - weekStart + 7) % 7\n return d.subtract(diff, 'day').startOf('day').valueOf()\n }\n return d.startOf(unit).valueOf()\n}\n\n/**\n * Subtracts `value` whole calendar periods from an instant, without aligning. Month subtraction\n * clamps to the last day of the target month (e.g. 31 Mar − 1 month → 28 Feb), which dayjs does\n * natively. `utc` runs the arithmetic in UTC.\n */\nexport function subtractPeriods(ms: number, value: number, unit: PeriodUnit, utc = false): number {\n return toCalendar(ms, utc).subtract(value, unit).valueOf()\n}\n"],"names":[],"mappings":";;AAiBA,MAAM,OAAO,SAAS;AAIf,MAAM,qBAAqB;AAG3B,SAAS,WAAW,IAAY,KAA2B;AAChE,SAAO,MAAM,MAAM,IAAI,EAAE,IAAI,MAAM,EAAE;AACvC;AAGA,SAAS,WAAW,GAAwB;AAC1C,QAAM,MAAM,EAAE,IAAA;AACd,SAAO,QAAQ,IAAI,IAAI;AACzB;AAOO,SAAS,eACd,IACA,MACA,YAAoB,oBACpB,MAAM,OACE;AACR,QAAM,IAAI,WAAW,IAAI,GAAG;AAC5B,MAAI,SAAS,QAAQ;AAEnB,UAAM,QAAQ,WAAW,CAAC,IAAI,YAAY,KAAK;AAC/C,WAAO,EAAE,SAAS,MAAM,KAAK,EAAE,QAAQ,KAAK,EAAE,QAAA;AAAA,EAChD;AACA,SAAO,EAAE,QAAQ,IAAI,EAAE,QAAA;AACzB;AAOO,SAAS,gBAAgB,IAAY,OAAe,MAAkB,MAAM,OAAe;AAChG,SAAO,WAAW,IAAI,GAAG,EAAE,SAAS,OAAO,IAAI,EAAE,QAAA;AACnD;"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Type } from "typebox";
|
|
2
|
+
const API_DATETIME_ACCEPTED_NOTE = "Only this spelling is accepted: `T` as the separator (a space is a 400) and an offset with minutes, either `Z` or `±HH:MM` (`+01` and `+0100` are a 400). A lowercase `t`/`z` and a fractional second are fine";
|
|
3
|
+
const API_DATETIME_EXAMPLE = "2026-01-15T10:30:00Z";
|
|
4
|
+
const EMITTED_DATETIME_NOTE = "Emitted as ISO-8601 in UTC";
|
|
5
|
+
const apiDateTime = Type.Codec(Type.String({ format: "date-time" })).Decode((value) => {
|
|
6
|
+
const date = new Date(value);
|
|
7
|
+
if (Number.isNaN(date.getTime())) {
|
|
8
|
+
throw new Error(`Invalid date-time: ${value}`);
|
|
9
|
+
}
|
|
10
|
+
return date;
|
|
11
|
+
}).Encode((date) => date.toISOString());
|
|
12
|
+
export {
|
|
13
|
+
API_DATETIME_ACCEPTED_NOTE as A,
|
|
14
|
+
EMITTED_DATETIME_NOTE as E,
|
|
15
|
+
API_DATETIME_EXAMPLE as a,
|
|
16
|
+
apiDateTime as b
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=dates.schema-BqkBcmM6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dates.schema-BqkBcmM6.js","sources":["../../src/v2/modules/global/dates/dates.schema.ts"],"sourcesContent":["import { Type } from 'typebox'\n\n/**\n * Generic calendar unit shared by the date primitives. Pure type — the calendar arithmetic that\n * consumes it lives in `dates.helper.ts`. Domain modules that need a narrower alias (e.g. the trend\n * widget's `TrendWindowUnit`) build it on top of this one, so the set of units is defined once here.\n */\nexport type PeriodUnit = 'hour' | 'day' | 'week' | 'month'\n\n/**\n * Datetimes a request carries are declared with `format: 'date-time'` (RFC 3339): a date and a time\n * separated by `T`, an optional fraction, and a mandatory offset (`Z` or `±HH:MM`). The offset names\n * the instant; the service converts it to UTC for the column.\n *\n * The format is TypeBox's, not `ajv-formats`': routes compile through `TypeBoxValidatorCompiler`\n * (`app.ts`), and `ajv-formats` only validates the v1/Objection layer. Which one runs matters,\n * because TypeBox's is the stricter of the two and the difference is visible from outside:\n *\n * - It splits the value on `/T/i` alone, so `T`/`t` is the only separator — a space is a 400.\n * - Its offset is `(?:Z|([+-])(\\d\\d):(\\d\\d))?`, so the minutes are not optional: `+01` is a 400,\n * and so is `+0100` without the colon. That is what keeps `dayjs.utc()` from ever seeing an\n * hour-only offset, which it cannot read — it would fall back to parsing the value as a bare wall\n * clock and drop the offset, storing an instant an hour off with no error.\n * - It bounds the offset to `±23:59` (`tzH > 23 || tzM > 59`), so `+99:99` is a 400, and it checks\n * the calendar (`IsDate`, leap years included), so `2026-02-31T00:00:00Z` is a 400 before any\n * handler runs. The bound is RFC 3339's and not the tz database's, so it also takes offsets no\n * zone uses (`-14:00`, `+23:59`) — each still names one unambiguous instant, so what gets stored\n * is right.\n *\n * A `pattern` alongside the format would be dead weight: everything one could reasonably spell in it\n * is already a subset of what the format checks, and a stricter one drifts silently the day either\n * side changes. This was tried and removed (persei/tasks#294).\n *\n * This is that contract in one sentence, for the description of a request field: what the format\n * takes and, just as important, the two near-miss spellings a client is likely to try.\n */\nexport const API_DATETIME_ACCEPTED_NOTE =\n 'Only this spelling is accepted: `T` as the separator (a space is a 400) and an offset with minutes, either `Z` or `±HH:MM` (`+01` and `+0100` are a 400). A lowercase `t`/`z` and a fractional second are fine'\n\n/** An RFC 3339 datetime, for schema examples and API documentation. */\nexport const API_DATETIME_EXAMPLE = '2026-01-15T10:30:00Z'\n\n/**\n * What a datetime *coming out* of the API looks like, for the description of a response field.\n *\n * The outbound shape is narrower than the inbound one and no pattern states it: datetimes leave the\n * column as `Date` and are serialised by `fast-json-stringify` with `.toISOString()`, so the schema\n * never validates what is emitted. Saying it in the description is what puts it in the published\n * spec, which is where a client reads the contract from.\n */\nexport const EMITTED_DATETIME_NOTE = 'Emitted as ISO-8601 in UTC'\n\n/**\n * An RFC 3339 datetime a request carries, decoded to a `Date` at the HTTP boundary.\n *\n * Declaring a request field with this instead of `Type.String({ format: 'date-time' })` is what\n * moves the string→instant conversion out of the services: the handler receives a `Date`, hands it\n * to the model, and `BaseModel.$parseJson` (`datesToString` → `getMySQLDateTime`) writes the UTC\n * string the column takes. No service has to know a date format.\n *\n * The decode runs in the validator compiler (`decodingValidatorCompiler`), after validation — see\n * `decoding-validator.helper.ts` for why that is the only place it can run. What this type contributes is the\n * declaration: a schema that carries it is a schema whose datetimes arrive decoded.\n *\n * `Type.Codec` and not `Type.Transform`: this is `typebox`, where the codec combinator carries that\n * name. The wrapped type is the same `format: 'date-time'` as before, so what the route accepts and\n * rejects does not move — see `API_DATETIME_ACCEPTED_NOTE` for the contract that stays put.\n *\n * `Encode` exists for completeness and does not run on the way out: responses are serialised by\n * `fast-json-stringify`, which knows nothing about codecs. Datetimes leave as ISO-8601 because they\n * come out of the pool as `Date` and get `.toISOString()`d there, not because of this. In this\n * architecture the codec is effectively one-way.\n */\nexport const apiDateTime = Type.Codec(Type.String({ format: 'date-time' }))\n .Decode((value) => {\n const date = new Date(value)\n // `format: 'date-time'` accepts a leap second (`:60`), which RFC 3339 allows and `Date` does\n // not: `new Date('2026-01-15T23:59:60Z')` is an `Invalid Date`. Rejecting it here answers 400\n // like any other malformed datetime, instead of letting the invalid instant reach the model and\n // fail there as a 500.\n if (Number.isNaN(date.getTime())) {\n throw new Error(`Invalid date-time: ${value}`)\n }\n return date\n })\n .Encode((date) => date.toISOString())\n"],"names":[],"mappings":";AAoCO,MAAM,6BACX;AAGK,MAAM,uBAAuB;AAU7B,MAAM,wBAAwB;AAuB9B,MAAM,cAAc,KAAK,MAAM,KAAK,OAAO,EAAE,QAAQ,aAAa,CAAC,EACvE,OAAO,CAAC,UAAU;AACjB,QAAM,OAAO,IAAI,KAAK,KAAK;AAK3B,MAAI,OAAO,MAAM,KAAK,QAAA,CAAS,GAAG;AAChC,UAAM,IAAI,MAAM,sBAAsB,KAAK,EAAE;AAAA,EAC/C;AACA,SAAO;AACT,CAAC,EACA,OAAO,CAAC,SAAS,KAAK,aAAa;"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const typebox = require("typebox");
|
|
3
|
+
const API_DATETIME_ACCEPTED_NOTE = "Only this spelling is accepted: `T` as the separator (a space is a 400) and an offset with minutes, either `Z` or `±HH:MM` (`+01` and `+0100` are a 400). A lowercase `t`/`z` and a fractional second are fine";
|
|
4
|
+
const API_DATETIME_EXAMPLE = "2026-01-15T10:30:00Z";
|
|
5
|
+
const EMITTED_DATETIME_NOTE = "Emitted as ISO-8601 in UTC";
|
|
6
|
+
const apiDateTime = typebox.Type.Codec(typebox.Type.String({ format: "date-time" })).Decode((value) => {
|
|
7
|
+
const date = new Date(value);
|
|
8
|
+
if (Number.isNaN(date.getTime())) {
|
|
9
|
+
throw new Error(`Invalid date-time: ${value}`);
|
|
10
|
+
}
|
|
11
|
+
return date;
|
|
12
|
+
}).Encode((date) => date.toISOString());
|
|
13
|
+
exports.API_DATETIME_ACCEPTED_NOTE = API_DATETIME_ACCEPTED_NOTE;
|
|
14
|
+
exports.API_DATETIME_EXAMPLE = API_DATETIME_EXAMPLE;
|
|
15
|
+
exports.EMITTED_DATETIME_NOTE = EMITTED_DATETIME_NOTE;
|
|
16
|
+
exports.apiDateTime = apiDateTime;
|
|
17
|
+
//# sourceMappingURL=dates.schema-npKpToAJ.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dates.schema-npKpToAJ.cjs","sources":["../../src/v2/modules/global/dates/dates.schema.ts"],"sourcesContent":["import { Type } from 'typebox'\n\n/**\n * Generic calendar unit shared by the date primitives. Pure type — the calendar arithmetic that\n * consumes it lives in `dates.helper.ts`. Domain modules that need a narrower alias (e.g. the trend\n * widget's `TrendWindowUnit`) build it on top of this one, so the set of units is defined once here.\n */\nexport type PeriodUnit = 'hour' | 'day' | 'week' | 'month'\n\n/**\n * Datetimes a request carries are declared with `format: 'date-time'` (RFC 3339): a date and a time\n * separated by `T`, an optional fraction, and a mandatory offset (`Z` or `±HH:MM`). The offset names\n * the instant; the service converts it to UTC for the column.\n *\n * The format is TypeBox's, not `ajv-formats`': routes compile through `TypeBoxValidatorCompiler`\n * (`app.ts`), and `ajv-formats` only validates the v1/Objection layer. Which one runs matters,\n * because TypeBox's is the stricter of the two and the difference is visible from outside:\n *\n * - It splits the value on `/T/i` alone, so `T`/`t` is the only separator — a space is a 400.\n * - Its offset is `(?:Z|([+-])(\\d\\d):(\\d\\d))?`, so the minutes are not optional: `+01` is a 400,\n * and so is `+0100` without the colon. That is what keeps `dayjs.utc()` from ever seeing an\n * hour-only offset, which it cannot read — it would fall back to parsing the value as a bare wall\n * clock and drop the offset, storing an instant an hour off with no error.\n * - It bounds the offset to `±23:59` (`tzH > 23 || tzM > 59`), so `+99:99` is a 400, and it checks\n * the calendar (`IsDate`, leap years included), so `2026-02-31T00:00:00Z` is a 400 before any\n * handler runs. The bound is RFC 3339's and not the tz database's, so it also takes offsets no\n * zone uses (`-14:00`, `+23:59`) — each still names one unambiguous instant, so what gets stored\n * is right.\n *\n * A `pattern` alongside the format would be dead weight: everything one could reasonably spell in it\n * is already a subset of what the format checks, and a stricter one drifts silently the day either\n * side changes. This was tried and removed (persei/tasks#294).\n *\n * This is that contract in one sentence, for the description of a request field: what the format\n * takes and, just as important, the two near-miss spellings a client is likely to try.\n */\nexport const API_DATETIME_ACCEPTED_NOTE =\n 'Only this spelling is accepted: `T` as the separator (a space is a 400) and an offset with minutes, either `Z` or `±HH:MM` (`+01` and `+0100` are a 400). A lowercase `t`/`z` and a fractional second are fine'\n\n/** An RFC 3339 datetime, for schema examples and API documentation. */\nexport const API_DATETIME_EXAMPLE = '2026-01-15T10:30:00Z'\n\n/**\n * What a datetime *coming out* of the API looks like, for the description of a response field.\n *\n * The outbound shape is narrower than the inbound one and no pattern states it: datetimes leave the\n * column as `Date` and are serialised by `fast-json-stringify` with `.toISOString()`, so the schema\n * never validates what is emitted. Saying it in the description is what puts it in the published\n * spec, which is where a client reads the contract from.\n */\nexport const EMITTED_DATETIME_NOTE = 'Emitted as ISO-8601 in UTC'\n\n/**\n * An RFC 3339 datetime a request carries, decoded to a `Date` at the HTTP boundary.\n *\n * Declaring a request field with this instead of `Type.String({ format: 'date-time' })` is what\n * moves the string→instant conversion out of the services: the handler receives a `Date`, hands it\n * to the model, and `BaseModel.$parseJson` (`datesToString` → `getMySQLDateTime`) writes the UTC\n * string the column takes. No service has to know a date format.\n *\n * The decode runs in the validator compiler (`decodingValidatorCompiler`), after validation — see\n * `decoding-validator.helper.ts` for why that is the only place it can run. What this type contributes is the\n * declaration: a schema that carries it is a schema whose datetimes arrive decoded.\n *\n * `Type.Codec` and not `Type.Transform`: this is `typebox`, where the codec combinator carries that\n * name. The wrapped type is the same `format: 'date-time'` as before, so what the route accepts and\n * rejects does not move — see `API_DATETIME_ACCEPTED_NOTE` for the contract that stays put.\n *\n * `Encode` exists for completeness and does not run on the way out: responses are serialised by\n * `fast-json-stringify`, which knows nothing about codecs. Datetimes leave as ISO-8601 because they\n * come out of the pool as `Date` and get `.toISOString()`d there, not because of this. In this\n * architecture the codec is effectively one-way.\n */\nexport const apiDateTime = Type.Codec(Type.String({ format: 'date-time' }))\n .Decode((value) => {\n const date = new Date(value)\n // `format: 'date-time'` accepts a leap second (`:60`), which RFC 3339 allows and `Date` does\n // not: `new Date('2026-01-15T23:59:60Z')` is an `Invalid Date`. Rejecting it here answers 400\n // like any other malformed datetime, instead of letting the invalid instant reach the model and\n // fail there as a 500.\n if (Number.isNaN(date.getTime())) {\n throw new Error(`Invalid date-time: ${value}`)\n }\n return date\n })\n .Encode((date) => date.toISOString())\n"],"names":["Type"],"mappings":";;AAoCO,MAAM,6BACX;AAGK,MAAM,uBAAuB;AAU7B,MAAM,wBAAwB;AAuB9B,MAAM,cAAcA,QAAAA,KAAK,MAAMA,QAAAA,KAAK,OAAO,EAAE,QAAQ,aAAa,CAAC,EACvE,OAAO,CAAC,UAAU;AACjB,QAAM,OAAO,IAAI,KAAK,KAAK;AAK3B,MAAI,OAAO,MAAM,KAAK,QAAA,CAAS,GAAG;AAChC,UAAM,IAAI,MAAM,sBAAsB,KAAK,EAAE;AAAA,EAC/C;AACA,SAAO;AACT,CAAC,EACA,OAAO,CAAC,SAAS,KAAK,aAAa;;;;;"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const dates_helper = require("./dates.helper-CDM5aEJG.cjs");
|
|
4
3
|
const globalLocale = require("./global-locale.cjs");
|
|
4
|
+
const dates_helper = require("./dates.helper-CDM5aEJG.cjs");
|
|
5
5
|
function resolveTrendWindow(nowMs, config, weekStart = globalLocale.getWeekStart(), utc = false) {
|
|
6
6
|
const { fromValue, unit } = config;
|
|
7
7
|
const toValue = config.toValue ?? 0;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as toCalendar, g as getPeriodStart, s as subtractPeriods } from "./dates.helper-XRCJ_UAQ.js";
|
|
2
1
|
import { getWeekStart } from "./global-locale.mjs";
|
|
2
|
+
import { t as toCalendar, g as getPeriodStart, s as subtractPeriods } from "./dates.helper-XRCJ_UAQ.js";
|
|
3
3
|
function resolveTrendWindow(nowMs, config, weekStart = getWeekStart(), utc = false) {
|
|
4
4
|
const { fromValue, unit } = config;
|
|
5
5
|
const toValue = config.toValue ?? 0;
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const typebox = require("typebox");
|
|
4
|
+
const dates_schema = require("./dates.schema-npKpToAJ.cjs");
|
|
5
|
+
const ProcessLogType = {
|
|
6
|
+
LOG: 0,
|
|
7
|
+
RESULT: 1,
|
|
8
|
+
WARNING: -1,
|
|
9
|
+
ERROR: -2
|
|
10
|
+
};
|
|
11
|
+
const processLogTypeSchema = typebox.Type.Enum(Object.values(ProcessLogType), {
|
|
12
|
+
title: "ProcessLogType",
|
|
13
|
+
description: "Severity of the log row (not a layout/kind marker): LOG, RESULT, WARNING or ERROR"
|
|
14
|
+
});
|
|
15
|
+
const ProcessLogCode = {
|
|
16
|
+
BULK_UPLOAD_BATCH: "bulk_upload_batch",
|
|
17
|
+
BULK_UPLOAD_SUCCESS: "bulk_upload_success",
|
|
18
|
+
BULK_UPLOAD_ERROR: "bulk_upload_error",
|
|
19
|
+
// Trigger engine (#348). Written by `TriggerEngineService` (`action-system` module): one
|
|
20
|
+
// `TRIGGER_EVALUATION` row per trigger evaluated, one `TRIGGER_ACTION` row per action it ran, and a
|
|
21
|
+
// `TRIGGER_ERROR` row when a trigger's evaluation throws.
|
|
22
|
+
TRIGGER_EVALUATION: "trigger_evaluation",
|
|
23
|
+
TRIGGER_ERROR: "trigger_error",
|
|
24
|
+
TRIGGER_ACTION: "trigger_action"
|
|
25
|
+
};
|
|
26
|
+
const processLogCodeSchema = typebox.Type.Enum(Object.values(ProcessLogCode), {
|
|
27
|
+
title: "ProcessLogCode",
|
|
28
|
+
description: "What kind of event a process_log row records, and what shape its extra_data takes"
|
|
29
|
+
});
|
|
30
|
+
const triggerEvaluationExtraDataSchema = typebox.Type.Object(
|
|
31
|
+
{
|
|
32
|
+
source: typebox.Type.String({ description: "What fired the event: a model row or a displayer/form save" }),
|
|
33
|
+
target: typebox.Type.Optional(
|
|
34
|
+
typebox.Type.Union([typebox.Type.String(), typebox.Type.Null()], { description: "Model/displayer name the trigger is bound to" })
|
|
35
|
+
),
|
|
36
|
+
operation: typebox.Type.Optional(
|
|
37
|
+
typebox.Type.Union([typebox.Type.String(), typebox.Type.Null()], { description: "create/update/delete that fired the event" })
|
|
38
|
+
),
|
|
39
|
+
matched: typebox.Type.Boolean({ description: "Whether the trigger conditions matched" }),
|
|
40
|
+
conditions: typebox.Type.Optional(
|
|
41
|
+
typebox.Type.Union([typebox.Type.Unknown(), typebox.Type.Null()], {
|
|
42
|
+
description: "jsonLogic conditions the trigger was configured with"
|
|
43
|
+
})
|
|
44
|
+
),
|
|
45
|
+
relations: typebox.Type.Optional(
|
|
46
|
+
typebox.Type.Union([typebox.Type.Unknown(), typebox.Type.Null()], {
|
|
47
|
+
description: "Relations the trigger declared to load onto `current`"
|
|
48
|
+
})
|
|
49
|
+
),
|
|
50
|
+
relationsSkipped: typebox.Type.Optional(
|
|
51
|
+
typebox.Type.Union([typebox.Type.String(), typebox.Type.Null()], {
|
|
52
|
+
description: "Reason a declared relation could not be loaded, when one was skipped"
|
|
53
|
+
})
|
|
54
|
+
)
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
title: "TriggerEvaluationExtraData",
|
|
58
|
+
description: "extra_data of a `trigger_evaluation` row — how a trigger resolved, never the entity data it resolved against",
|
|
59
|
+
additionalProperties: false
|
|
60
|
+
}
|
|
61
|
+
);
|
|
62
|
+
const triggerErrorExtraDataSchema = typebox.Type.Object(
|
|
63
|
+
{ error: typebox.Type.String({ description: "String representation of the exception the trigger evaluation threw" }) },
|
|
64
|
+
{ title: "TriggerErrorExtraData", description: "extra_data of a `trigger_error` row", additionalProperties: false }
|
|
65
|
+
);
|
|
66
|
+
const triggerActionExtraDataSchema = typebox.Type.Object(
|
|
67
|
+
{
|
|
68
|
+
actionId: typebox.Type.Number({ description: "id of the action row that ran" }),
|
|
69
|
+
triggerId: typebox.Type.Number({ description: "id of the trigger that ran this action" }),
|
|
70
|
+
// Needed because the engine is shared: `triggerId` alone is ambiguous, since automatic and
|
|
71
|
+
// manual triggers are different tables (`automatic_trigger`, `manual_trigger`) with overlapping
|
|
72
|
+
// id ranges. Paired with `triggerId` this is what a consumer needs to resolve the trigger row.
|
|
73
|
+
triggerModel: typebox.Type.String({ description: "Table the trigger belongs to (automatic_trigger or manual_trigger)" }),
|
|
74
|
+
executionOrder: typebox.Type.Number({ description: "Order of this action within the trigger" }),
|
|
75
|
+
type: typebox.Type.String({ description: "Type of the action (e.g. ApiAction)" }),
|
|
76
|
+
validation: typebox.Type.Unknown({ description: "Result of validating the action context before running it" }),
|
|
77
|
+
// `ok`/`output` describe an action that ran; `aborted`/`reason` an action that never did,
|
|
78
|
+
// because validating its context failed (`resolveActionOutcome`). The two pairs are mutually
|
|
79
|
+
// exclusive in practice but declared as four optionals rather than a union: `additionalProperties:
|
|
80
|
+
// false` is what makes this schema worth having, and a row whose outcome keys are undeclared is
|
|
81
|
+
// one the debugging popup cannot show a reason for — which is exactly the aborted case.
|
|
82
|
+
ok: typebox.Type.Optional(typebox.Type.Union([typebox.Type.Boolean(), typebox.Type.Null()], { description: "Whether the action call succeeded" })),
|
|
83
|
+
output: typebox.Type.Optional(
|
|
84
|
+
typebox.Type.Union([typebox.Type.String(), typebox.Type.Null()], { description: "Failure output, when the action ran and failed" })
|
|
85
|
+
),
|
|
86
|
+
aborted: typebox.Type.Optional(typebox.Type.Boolean({ description: "True when the action never ran" })),
|
|
87
|
+
reason: typebox.Type.Optional(typebox.Type.String({ description: "Why the action was aborted, e.g. context_validation" }))
|
|
88
|
+
},
|
|
89
|
+
{ title: "TriggerActionExtraData", description: "extra_data of a `trigger_action` row", additionalProperties: false }
|
|
90
|
+
);
|
|
91
|
+
const processLogTriggerEngineExtraDataSchema = typebox.Type.Union(
|
|
92
|
+
[
|
|
93
|
+
typebox.Type.Object({
|
|
94
|
+
code: typebox.Type.Literal(ProcessLogCode.TRIGGER_EVALUATION),
|
|
95
|
+
extra_data: triggerEvaluationExtraDataSchema
|
|
96
|
+
}),
|
|
97
|
+
typebox.Type.Object({ code: typebox.Type.Literal(ProcessLogCode.TRIGGER_ERROR), extra_data: triggerErrorExtraDataSchema }),
|
|
98
|
+
typebox.Type.Object({ code: typebox.Type.Literal(ProcessLogCode.TRIGGER_ACTION), extra_data: triggerActionExtraDataSchema })
|
|
99
|
+
],
|
|
100
|
+
{
|
|
101
|
+
title: "ProcessLogTriggerEngineExtraData",
|
|
102
|
+
description: "Ties each trigger-engine `code` to the shape its `extra_data` takes"
|
|
103
|
+
}
|
|
104
|
+
);
|
|
105
|
+
const processLogSchema = typebox.Type.Object(
|
|
106
|
+
{
|
|
107
|
+
id: typebox.Type.Number({ description: "Unique identifier of the row" }),
|
|
108
|
+
project_id: typebox.Type.Optional(
|
|
109
|
+
typebox.Type.Union([typebox.Type.Number(), typebox.Type.Null()], { description: "Project this row belongs to, when scoped to one" })
|
|
110
|
+
),
|
|
111
|
+
created_user: typebox.Type.Optional(
|
|
112
|
+
typebox.Type.Union([typebox.Type.Number(), typebox.Type.Null()], {
|
|
113
|
+
description: "User who caused the row to be written, when a user did"
|
|
114
|
+
})
|
|
115
|
+
),
|
|
116
|
+
related_model: typebox.Type.Optional(
|
|
117
|
+
typebox.Type.Union([typebox.Type.String({ maxLength: 255 }), typebox.Type.Null()], { description: "Table/entity kind the row is about" })
|
|
118
|
+
),
|
|
119
|
+
related_id: typebox.Type.Optional(
|
|
120
|
+
typebox.Type.Union([typebox.Type.String({ maxLength: 255 }), typebox.Type.Null()], {
|
|
121
|
+
description: "Id of the related entity, as a string"
|
|
122
|
+
})
|
|
123
|
+
),
|
|
124
|
+
code: typebox.Type.Optional(typebox.Type.Union([processLogCodeSchema, typebox.Type.Null()])),
|
|
125
|
+
log: typebox.Type.String({ description: "Short human-readable message" }),
|
|
126
|
+
long_log: typebox.Type.Optional(typebox.Type.Union([typebox.Type.String(), typebox.Type.Null()], { description: "Extended message, when needed" })),
|
|
127
|
+
extra_data: typebox.Type.Optional(
|
|
128
|
+
typebox.Type.Union([typebox.Type.Record(typebox.Type.String(), typebox.Type.Unknown()), typebox.Type.Null()], {
|
|
129
|
+
description: "Structured data specific to `code` — see the per-code schemas for the trigger-engine codes"
|
|
130
|
+
})
|
|
131
|
+
),
|
|
132
|
+
type: processLogTypeSchema,
|
|
133
|
+
requires_attention: typebox.Type.Optional(typebox.Type.Boolean({ description: "Whether the row needs a human to review it" })),
|
|
134
|
+
reviewed: typebox.Type.Optional(typebox.Type.Boolean({ description: "Whether the row has been reviewed" })),
|
|
135
|
+
reviewed_date: typebox.Type.Optional(
|
|
136
|
+
typebox.Type.Union([typebox.Type.String(), typebox.Type.Null()], {
|
|
137
|
+
description: `When the row was reviewed. Null while unreviewed. ${dates_schema.EMITTED_DATETIME_NOTE}`
|
|
138
|
+
})
|
|
139
|
+
),
|
|
140
|
+
// Correlation to a parent row (#348): a `trigger_action` row's parent is the `trigger_evaluation`
|
|
141
|
+
// (or `trigger_error`) row of the trigger that ran it, so an action's trace can always be walked
|
|
142
|
+
// back to the evaluation that triggered it. Optional/nullable because most rows (bulk upload,
|
|
143
|
+
// the trigger-evaluation row itself) have no parent, and because the column is applied out of
|
|
144
|
+
// band per ecosystem — see README.md — so it may be entirely absent from a given row's database.
|
|
145
|
+
parent_id: typebox.Type.Optional(
|
|
146
|
+
typebox.Type.Union([typebox.Type.Number(), typebox.Type.Null()], {
|
|
147
|
+
description: "Id of this row's parent process_log row, when it has one"
|
|
148
|
+
})
|
|
149
|
+
),
|
|
150
|
+
expires_at: typebox.Type.Optional(
|
|
151
|
+
typebox.Type.Union([typebox.Type.String(), typebox.Type.Null()], {
|
|
152
|
+
description: `Retention deadline; the row is purged after it, and never expires when null. ${dates_schema.EMITTED_DATETIME_NOTE}`,
|
|
153
|
+
examples: [dates_schema.API_DATETIME_EXAMPLE]
|
|
154
|
+
})
|
|
155
|
+
),
|
|
156
|
+
created_at: typebox.Type.Optional(
|
|
157
|
+
typebox.Type.String({
|
|
158
|
+
description: `When the row was created. ${dates_schema.EMITTED_DATETIME_NOTE}`,
|
|
159
|
+
examples: [dates_schema.API_DATETIME_EXAMPLE]
|
|
160
|
+
})
|
|
161
|
+
),
|
|
162
|
+
mod_time: typebox.Type.Optional(
|
|
163
|
+
typebox.Type.String({
|
|
164
|
+
description: `When the row was last modified. ${dates_schema.EMITTED_DATETIME_NOTE}`,
|
|
165
|
+
examples: [dates_schema.API_DATETIME_EXAMPLE]
|
|
166
|
+
})
|
|
167
|
+
)
|
|
168
|
+
},
|
|
169
|
+
{ title: "ProcessLog", description: "A process_log row" }
|
|
170
|
+
);
|
|
171
|
+
const listProcessLogQuerySchema = typebox.Type.Object(
|
|
172
|
+
{
|
|
173
|
+
code: typebox.Type.Optional(processLogCodeSchema),
|
|
174
|
+
type: typebox.Type.Optional(processLogTypeSchema),
|
|
175
|
+
related_model: typebox.Type.Optional(typebox.Type.String({ description: "Filter by the related entity kind" })),
|
|
176
|
+
related_id: typebox.Type.Optional(typebox.Type.String({ description: "Filter by the id of the related entity" })),
|
|
177
|
+
parent_id: typebox.Type.Optional(typebox.Type.Number({ description: "Filter by the id of the parent process_log row" })),
|
|
178
|
+
requires_attention: typebox.Type.Optional(typebox.Type.Boolean({ description: "Filter by whether the row needs review" })),
|
|
179
|
+
reviewed: typebox.Type.Optional(typebox.Type.Boolean({ description: "Filter by whether the row has been reviewed" })),
|
|
180
|
+
// `apiDateTime`, not a bare string: it carries `format: 'date-time'`, so a malformed value is
|
|
181
|
+
// rejected by the validator as a 400. A plain `Type.String` accepts anything and hands it to
|
|
182
|
+
// `getMySQLDateTime(value, true)`, which throws a `PublicApiError` with no `statusCode` — a 500
|
|
183
|
+
// for what is a bad request. Same type `alert.schema.ts` uses for its datetime fields.
|
|
184
|
+
created_from: typebox.Type.Optional(
|
|
185
|
+
typebox.Type.Union([dates_schema.apiDateTime], {
|
|
186
|
+
description: `Only rows created at or after this instant. ${dates_schema.API_DATETIME_ACCEPTED_NOTE}. ${dates_schema.EMITTED_DATETIME_NOTE}`,
|
|
187
|
+
examples: [dates_schema.API_DATETIME_EXAMPLE]
|
|
188
|
+
})
|
|
189
|
+
),
|
|
190
|
+
created_to: typebox.Type.Optional(
|
|
191
|
+
typebox.Type.Union([dates_schema.apiDateTime], {
|
|
192
|
+
description: `Only rows created at or before this instant. ${dates_schema.API_DATETIME_ACCEPTED_NOTE}. ${dates_schema.EMITTED_DATETIME_NOTE}`,
|
|
193
|
+
examples: [dates_schema.API_DATETIME_EXAMPLE]
|
|
194
|
+
})
|
|
195
|
+
)
|
|
196
|
+
},
|
|
197
|
+
{ title: "ListProcessLogQuery", description: "Filters available on the process_log list" }
|
|
198
|
+
);
|
|
199
|
+
exports.ProcessLogCode = ProcessLogCode;
|
|
200
|
+
exports.ProcessLogType = ProcessLogType;
|
|
201
|
+
exports.listProcessLogQuerySchema = listProcessLogQuerySchema;
|
|
202
|
+
exports.processLogCodeSchema = processLogCodeSchema;
|
|
203
|
+
exports.processLogSchema = processLogSchema;
|
|
204
|
+
exports.processLogTriggerEngineExtraDataSchema = processLogTriggerEngineExtraDataSchema;
|
|
205
|
+
exports.processLogTypeSchema = processLogTypeSchema;
|
|
206
|
+
exports.triggerActionExtraDataSchema = triggerActionExtraDataSchema;
|
|
207
|
+
exports.triggerErrorExtraDataSchema = triggerErrorExtraDataSchema;
|
|
208
|
+
exports.triggerEvaluationExtraDataSchema = triggerEvaluationExtraDataSchema;
|
|
209
|
+
//# sourceMappingURL=ecosystem-process-log.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ecosystem-process-log.cjs","sources":["../../src/v2/modules/ecosystem/process-log/process-log.schema.ts"],"sourcesContent":["import { Type, Static, StaticDecode } from 'typebox'\n// From the schema file, not the module barrel (`@/modules/global/dates`) that every other consumer\n// imports — the one place where `no-restricted-imports` has to give way, hence the disable.\n//\n// This module has a `lib.ts`, so this file is an entry point of the published `@persei/perseed-api`\n// bundle, which is browser code. The barrel re-exports `dates.middleware`, a `fastify-plugin` that\n// pulls in `@v1/log/debug` and, transitively, the server dependencies behind it; bundling that\n// fails, and it fails naming a transitive JSON file (`ent/reversed.json: Could not parse JSON\n// file`) rather than the import that dragged it in, so the message points nowhere near the cause.\n//\n// `global/dates`'s own `lib.ts` sidesteps the same barrel for the same reason. The alternative —\n// inlining the two description constants — would duplicate the wording the whole API documents its\n// datetimes with, and let this module's copy drift from it silently.\n// eslint-disable-next-line no-restricted-imports\nimport {\n EMITTED_DATETIME_NOTE,\n API_DATETIME_EXAMPLE,\n API_DATETIME_ACCEPTED_NOTE,\n apiDateTime,\n} from '@/modules/global/dates/dates.schema'\n\n// `process_log` is the ecosystem-wide execution log (see README.md): rows written by the trigger\n// engine, the actions it runs and the v1 bulk upload. This module owns the schema for the whole\n// table, not only the trigger-engine rows — `code` is what tells them apart.\n\n// ── ProcessLogType (severity, NOT layout) ───────────────────────────────\n// Mirrors the v1 enum (`src/schemas/process_log/types.ts`) verbatim: it already ships on the wire\n// (`type` column) and changing its numeric values would be a breaking change for every existing row\n// and consumer. Restated here as a TypeBox schema — not imported from v1 — because `lib.ts` may\n// only export pure TypeBox (see below); v1 has no schema module of its own to import from.\nexport const ProcessLogType = {\n LOG: 0,\n RESULT: 1,\n WARNING: -1,\n ERROR: -2,\n} as const\nexport const processLogTypeSchema = Type.Enum(Object.values(ProcessLogType), {\n title: 'ProcessLogType',\n description: 'Severity of the log row (not a layout/kind marker): LOG, RESULT, WARNING or ERROR',\n})\nexport type ProcessLogType = Static<typeof processLogTypeSchema>\n\n// ── ProcessLogCode ───────────────────────────────────────────────────────\n//\n// Canonical enum now lives HERE (v2), not in `src/schemas/process_log/types.ts` (v1).\n//\n// Why: this module (`process-log`) is the one being extended with the trigger-engine codes as part\n// of #348, it already owns the model/service half of `process_log`, and every v2 consumer that needs\n// a *typed* extra_data contract (this schema file) has to sit next to the code enum it is keyed by.\n// The two v1 importers (`BulkUploadController.ts` and `IntrospectionController.ts`) import it from\n// here rather than from `@v1/schemas`, which keeps one enum instead of two that could drift. v1's\n// `types.ts` deliberately does NOT re-export the value: doing so closes the cycle `@v1/schemas` →\n// this module's barrel → `process-log.model.ts` → `@v1/schemas`, under which the enum resolves to\n// `undefined` at runtime. It keeps an `import type` only, which is erased at compile time.\nexport const ProcessLogCode = {\n BULK_UPLOAD_BATCH: 'bulk_upload_batch',\n BULK_UPLOAD_SUCCESS: 'bulk_upload_success',\n BULK_UPLOAD_ERROR: 'bulk_upload_error',\n // Trigger engine (#348). Written by `TriggerEngineService` (`action-system` module): one\n // `TRIGGER_EVALUATION` row per trigger evaluated, one `TRIGGER_ACTION` row per action it ran, and a\n // `TRIGGER_ERROR` row when a trigger's evaluation throws.\n TRIGGER_EVALUATION: 'trigger_evaluation',\n TRIGGER_ERROR: 'trigger_error',\n TRIGGER_ACTION: 'trigger_action',\n} as const\nexport const processLogCodeSchema = Type.Enum(Object.values(ProcessLogCode), {\n title: 'ProcessLogCode',\n description: 'What kind of event a process_log row records, and what shape its extra_data takes',\n})\nexport type ProcessLogCode = Static<typeof processLogCodeSchema>\n\n// ── extra_data shapes, one per trigger-engine code ───────────────────────\n// Bulk upload codes carry no typed extra_data today (nothing writes them yet outside the\n// filter-by-code reads in `BulkUploadController.ts`), so they are left out of the discriminated\n// union below rather than given a placeholder shape that no writer populates.\n\nexport const triggerEvaluationExtraDataSchema = Type.Object(\n {\n source: Type.String({ description: 'What fired the event: a model row or a displayer/form save' }),\n target: Type.Optional(\n Type.Union([Type.String(), Type.Null()], { description: 'Model/displayer name the trigger is bound to' }),\n ),\n operation: Type.Optional(\n Type.Union([Type.String(), Type.Null()], { description: 'create/update/delete that fired the event' }),\n ),\n matched: Type.Boolean({ description: 'Whether the trigger conditions matched' }),\n conditions: Type.Optional(\n Type.Union([Type.Unknown(), Type.Null()], {\n description: 'jsonLogic conditions the trigger was configured with',\n }),\n ),\n relations: Type.Optional(\n Type.Union([Type.Unknown(), Type.Null()], {\n description: 'Relations the trigger declared to load onto `current`',\n }),\n ),\n relationsSkipped: Type.Optional(\n Type.Union([Type.String(), Type.Null()], {\n description: 'Reason a declared relation could not be loaded, when one was skipped',\n }),\n ),\n },\n {\n title: 'TriggerEvaluationExtraData',\n description:\n 'extra_data of a `trigger_evaluation` row — how a trigger resolved, never the entity data it resolved against',\n additionalProperties: false,\n },\n)\nexport type TriggerEvaluationExtraData = Static<typeof triggerEvaluationExtraDataSchema>\n\nexport const triggerErrorExtraDataSchema = Type.Object(\n { error: Type.String({ description: 'String representation of the exception the trigger evaluation threw' }) },\n { title: 'TriggerErrorExtraData', description: 'extra_data of a `trigger_error` row', additionalProperties: false },\n)\nexport type TriggerErrorExtraData = Static<typeof triggerErrorExtraDataSchema>\n\nexport const triggerActionExtraDataSchema = Type.Object(\n {\n actionId: Type.Number({ description: 'id of the action row that ran' }),\n triggerId: Type.Number({ description: 'id of the trigger that ran this action' }),\n // Needed because the engine is shared: `triggerId` alone is ambiguous, since automatic and\n // manual triggers are different tables (`automatic_trigger`, `manual_trigger`) with overlapping\n // id ranges. Paired with `triggerId` this is what a consumer needs to resolve the trigger row.\n triggerModel: Type.String({ description: 'Table the trigger belongs to (automatic_trigger or manual_trigger)' }),\n executionOrder: Type.Number({ description: 'Order of this action within the trigger' }),\n type: Type.String({ description: 'Type of the action (e.g. ApiAction)' }),\n validation: Type.Unknown({ description: 'Result of validating the action context before running it' }),\n // `ok`/`output` describe an action that ran; `aborted`/`reason` an action that never did,\n // because validating its context failed (`resolveActionOutcome`). The two pairs are mutually\n // exclusive in practice but declared as four optionals rather than a union: `additionalProperties:\n // false` is what makes this schema worth having, and a row whose outcome keys are undeclared is\n // one the debugging popup cannot show a reason for — which is exactly the aborted case.\n ok: Type.Optional(Type.Union([Type.Boolean(), Type.Null()], { description: 'Whether the action call succeeded' })),\n output: Type.Optional(\n Type.Union([Type.String(), Type.Null()], { description: 'Failure output, when the action ran and failed' }),\n ),\n aborted: Type.Optional(Type.Boolean({ description: 'True when the action never ran' })),\n reason: Type.Optional(Type.String({ description: 'Why the action was aborted, e.g. context_validation' })),\n },\n { title: 'TriggerActionExtraData', description: 'extra_data of a `trigger_action` row', additionalProperties: false },\n)\nexport type TriggerActionExtraData = Static<typeof triggerActionExtraDataSchema>\n\n// Discriminated (by `code`) union tying each trigger-engine code to its extra_data shape. Usable\n// both to validate a row being created and to type one being read. Bulk upload codes are\n// deliberately absent (see comment above the individual schemas).\nexport const processLogTriggerEngineExtraDataSchema = Type.Union(\n [\n Type.Object({\n code: Type.Literal(ProcessLogCode.TRIGGER_EVALUATION),\n extra_data: triggerEvaluationExtraDataSchema,\n }),\n Type.Object({ code: Type.Literal(ProcessLogCode.TRIGGER_ERROR), extra_data: triggerErrorExtraDataSchema }),\n Type.Object({ code: Type.Literal(ProcessLogCode.TRIGGER_ACTION), extra_data: triggerActionExtraDataSchema }),\n ],\n {\n title: 'ProcessLogTriggerEngineExtraData',\n description: 'Ties each trigger-engine `code` to the shape its `extra_data` takes',\n },\n)\nexport type ProcessLogTriggerEngineExtraData = Static<typeof processLogTriggerEngineExtraDataSchema>\n\n// ── process_log entity ────────────────────────────────────────────────────\n// Full row shape, for the read side of the (still to be implemented) list endpoint. `extra_data` is\n// left as a free record here — a response schema describes what every row of the table can hold,\n// including the untyped bulk_upload rows, unlike `processLogTriggerEngineExtraDataSchema` above\n// which narrows by `code` for a writer/reader that already knows it is on the trigger-engine path.\nexport const processLogSchema = Type.Object(\n {\n id: Type.Number({ description: 'Unique identifier of the row' }),\n project_id: Type.Optional(\n Type.Union([Type.Number(), Type.Null()], { description: 'Project this row belongs to, when scoped to one' }),\n ),\n created_user: Type.Optional(\n Type.Union([Type.Number(), Type.Null()], {\n description: 'User who caused the row to be written, when a user did',\n }),\n ),\n related_model: Type.Optional(\n Type.Union([Type.String({ maxLength: 255 }), Type.Null()], { description: 'Table/entity kind the row is about' }),\n ),\n related_id: Type.Optional(\n Type.Union([Type.String({ maxLength: 255 }), Type.Null()], {\n description: 'Id of the related entity, as a string',\n }),\n ),\n code: Type.Optional(Type.Union([processLogCodeSchema, Type.Null()])),\n log: Type.String({ description: 'Short human-readable message' }),\n long_log: Type.Optional(Type.Union([Type.String(), Type.Null()], { description: 'Extended message, when needed' })),\n extra_data: Type.Optional(\n Type.Union([Type.Record(Type.String(), Type.Unknown()), Type.Null()], {\n description: 'Structured data specific to `code` — see the per-code schemas for the trigger-engine codes',\n }),\n ),\n type: processLogTypeSchema,\n requires_attention: Type.Optional(Type.Boolean({ description: 'Whether the row needs a human to review it' })),\n reviewed: Type.Optional(Type.Boolean({ description: 'Whether the row has been reviewed' })),\n reviewed_date: Type.Optional(\n Type.Union([Type.String(), Type.Null()], {\n description: `When the row was reviewed. Null while unreviewed. ${EMITTED_DATETIME_NOTE}`,\n }),\n ),\n // Correlation to a parent row (#348): a `trigger_action` row's parent is the `trigger_evaluation`\n // (or `trigger_error`) row of the trigger that ran it, so an action's trace can always be walked\n // back to the evaluation that triggered it. Optional/nullable because most rows (bulk upload,\n // the trigger-evaluation row itself) have no parent, and because the column is applied out of\n // band per ecosystem — see README.md — so it may be entirely absent from a given row's database.\n parent_id: Type.Optional(\n Type.Union([Type.Number(), Type.Null()], {\n description: \"Id of this row's parent process_log row, when it has one\",\n }),\n ),\n expires_at: Type.Optional(\n Type.Union([Type.String(), Type.Null()], {\n description: `Retention deadline; the row is purged after it, and never expires when null. ${EMITTED_DATETIME_NOTE}`,\n examples: [API_DATETIME_EXAMPLE],\n }),\n ),\n created_at: Type.Optional(\n Type.String({\n description: `When the row was created. ${EMITTED_DATETIME_NOTE}`,\n examples: [API_DATETIME_EXAMPLE],\n }),\n ),\n mod_time: Type.Optional(\n Type.String({\n description: `When the row was last modified. ${EMITTED_DATETIME_NOTE}`,\n examples: [API_DATETIME_EXAMPLE],\n }),\n ),\n },\n { title: 'ProcessLog', description: 'A process_log row' },\n)\nexport type ProcessLogData = Static<typeof processLogSchema>\n\n// ── list query filters ────────────────────────────────────────────────────\n// Filters of the (upcoming) list endpoint, on top of the pagination query — see `alert.schema.ts`\n// `listAlertQuerySchema` for the sibling precedent. Everything is optional: with none of them the\n// endpoint lists everything in scope. Exported for the endpoint (implemented separately) to consume.\nexport const listProcessLogQuerySchema = Type.Object(\n {\n code: Type.Optional(processLogCodeSchema),\n type: Type.Optional(processLogTypeSchema),\n related_model: Type.Optional(Type.String({ description: 'Filter by the related entity kind' })),\n related_id: Type.Optional(Type.String({ description: 'Filter by the id of the related entity' })),\n parent_id: Type.Optional(Type.Number({ description: 'Filter by the id of the parent process_log row' })),\n requires_attention: Type.Optional(Type.Boolean({ description: 'Filter by whether the row needs review' })),\n reviewed: Type.Optional(Type.Boolean({ description: 'Filter by whether the row has been reviewed' })),\n // `apiDateTime`, not a bare string: it carries `format: 'date-time'`, so a malformed value is\n // rejected by the validator as a 400. A plain `Type.String` accepts anything and hands it to\n // `getMySQLDateTime(value, true)`, which throws a `PublicApiError` with no `statusCode` — a 500\n // for what is a bad request. Same type `alert.schema.ts` uses for its datetime fields.\n created_from: Type.Optional(\n Type.Union([apiDateTime], {\n description: `Only rows created at or after this instant. ${API_DATETIME_ACCEPTED_NOTE}. ${EMITTED_DATETIME_NOTE}`,\n examples: [API_DATETIME_EXAMPLE],\n }),\n ),\n created_to: Type.Optional(\n Type.Union([apiDateTime], {\n description: `Only rows created at or before this instant. ${API_DATETIME_ACCEPTED_NOTE}. ${EMITTED_DATETIME_NOTE}`,\n examples: [API_DATETIME_EXAMPLE],\n }),\n ),\n },\n { title: 'ListProcessLogQuery', description: 'Filters available on the process_log list' },\n)\n// `StaticDecode`, not `Static`: this type describes what the *handler receives*, and the two date\n// bounds carry `apiDateTime`, so they arrive decoded to a `Date`. `Static` would type them as the\n// strings the client sent and the service would format something it never gets.\nexport type ListProcessLogQuery = StaticDecode<typeof listProcessLogQuerySchema>\n"],"names":["Type","EMITTED_DATETIME_NOTE","API_DATETIME_EXAMPLE","apiDateTime","API_DATETIME_ACCEPTED_NOTE"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './src/v2/modules/ecosystem/process-log/lib'
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { Type } from "typebox";
|
|
2
|
+
import { b as apiDateTime, a as API_DATETIME_EXAMPLE, A as API_DATETIME_ACCEPTED_NOTE, E as EMITTED_DATETIME_NOTE } from "./dates.schema-BqkBcmM6.js";
|
|
3
|
+
const ProcessLogType = {
|
|
4
|
+
LOG: 0,
|
|
5
|
+
RESULT: 1,
|
|
6
|
+
WARNING: -1,
|
|
7
|
+
ERROR: -2
|
|
8
|
+
};
|
|
9
|
+
const processLogTypeSchema = Type.Enum(Object.values(ProcessLogType), {
|
|
10
|
+
title: "ProcessLogType",
|
|
11
|
+
description: "Severity of the log row (not a layout/kind marker): LOG, RESULT, WARNING or ERROR"
|
|
12
|
+
});
|
|
13
|
+
const ProcessLogCode = {
|
|
14
|
+
BULK_UPLOAD_BATCH: "bulk_upload_batch",
|
|
15
|
+
BULK_UPLOAD_SUCCESS: "bulk_upload_success",
|
|
16
|
+
BULK_UPLOAD_ERROR: "bulk_upload_error",
|
|
17
|
+
// Trigger engine (#348). Written by `TriggerEngineService` (`action-system` module): one
|
|
18
|
+
// `TRIGGER_EVALUATION` row per trigger evaluated, one `TRIGGER_ACTION` row per action it ran, and a
|
|
19
|
+
// `TRIGGER_ERROR` row when a trigger's evaluation throws.
|
|
20
|
+
TRIGGER_EVALUATION: "trigger_evaluation",
|
|
21
|
+
TRIGGER_ERROR: "trigger_error",
|
|
22
|
+
TRIGGER_ACTION: "trigger_action"
|
|
23
|
+
};
|
|
24
|
+
const processLogCodeSchema = Type.Enum(Object.values(ProcessLogCode), {
|
|
25
|
+
title: "ProcessLogCode",
|
|
26
|
+
description: "What kind of event a process_log row records, and what shape its extra_data takes"
|
|
27
|
+
});
|
|
28
|
+
const triggerEvaluationExtraDataSchema = Type.Object(
|
|
29
|
+
{
|
|
30
|
+
source: Type.String({ description: "What fired the event: a model row or a displayer/form save" }),
|
|
31
|
+
target: Type.Optional(
|
|
32
|
+
Type.Union([Type.String(), Type.Null()], { description: "Model/displayer name the trigger is bound to" })
|
|
33
|
+
),
|
|
34
|
+
operation: Type.Optional(
|
|
35
|
+
Type.Union([Type.String(), Type.Null()], { description: "create/update/delete that fired the event" })
|
|
36
|
+
),
|
|
37
|
+
matched: Type.Boolean({ description: "Whether the trigger conditions matched" }),
|
|
38
|
+
conditions: Type.Optional(
|
|
39
|
+
Type.Union([Type.Unknown(), Type.Null()], {
|
|
40
|
+
description: "jsonLogic conditions the trigger was configured with"
|
|
41
|
+
})
|
|
42
|
+
),
|
|
43
|
+
relations: Type.Optional(
|
|
44
|
+
Type.Union([Type.Unknown(), Type.Null()], {
|
|
45
|
+
description: "Relations the trigger declared to load onto `current`"
|
|
46
|
+
})
|
|
47
|
+
),
|
|
48
|
+
relationsSkipped: Type.Optional(
|
|
49
|
+
Type.Union([Type.String(), Type.Null()], {
|
|
50
|
+
description: "Reason a declared relation could not be loaded, when one was skipped"
|
|
51
|
+
})
|
|
52
|
+
)
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
title: "TriggerEvaluationExtraData",
|
|
56
|
+
description: "extra_data of a `trigger_evaluation` row — how a trigger resolved, never the entity data it resolved against",
|
|
57
|
+
additionalProperties: false
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
const triggerErrorExtraDataSchema = Type.Object(
|
|
61
|
+
{ error: Type.String({ description: "String representation of the exception the trigger evaluation threw" }) },
|
|
62
|
+
{ title: "TriggerErrorExtraData", description: "extra_data of a `trigger_error` row", additionalProperties: false }
|
|
63
|
+
);
|
|
64
|
+
const triggerActionExtraDataSchema = Type.Object(
|
|
65
|
+
{
|
|
66
|
+
actionId: Type.Number({ description: "id of the action row that ran" }),
|
|
67
|
+
triggerId: Type.Number({ description: "id of the trigger that ran this action" }),
|
|
68
|
+
// Needed because the engine is shared: `triggerId` alone is ambiguous, since automatic and
|
|
69
|
+
// manual triggers are different tables (`automatic_trigger`, `manual_trigger`) with overlapping
|
|
70
|
+
// id ranges. Paired with `triggerId` this is what a consumer needs to resolve the trigger row.
|
|
71
|
+
triggerModel: Type.String({ description: "Table the trigger belongs to (automatic_trigger or manual_trigger)" }),
|
|
72
|
+
executionOrder: Type.Number({ description: "Order of this action within the trigger" }),
|
|
73
|
+
type: Type.String({ description: "Type of the action (e.g. ApiAction)" }),
|
|
74
|
+
validation: Type.Unknown({ description: "Result of validating the action context before running it" }),
|
|
75
|
+
// `ok`/`output` describe an action that ran; `aborted`/`reason` an action that never did,
|
|
76
|
+
// because validating its context failed (`resolveActionOutcome`). The two pairs are mutually
|
|
77
|
+
// exclusive in practice but declared as four optionals rather than a union: `additionalProperties:
|
|
78
|
+
// false` is what makes this schema worth having, and a row whose outcome keys are undeclared is
|
|
79
|
+
// one the debugging popup cannot show a reason for — which is exactly the aborted case.
|
|
80
|
+
ok: Type.Optional(Type.Union([Type.Boolean(), Type.Null()], { description: "Whether the action call succeeded" })),
|
|
81
|
+
output: Type.Optional(
|
|
82
|
+
Type.Union([Type.String(), Type.Null()], { description: "Failure output, when the action ran and failed" })
|
|
83
|
+
),
|
|
84
|
+
aborted: Type.Optional(Type.Boolean({ description: "True when the action never ran" })),
|
|
85
|
+
reason: Type.Optional(Type.String({ description: "Why the action was aborted, e.g. context_validation" }))
|
|
86
|
+
},
|
|
87
|
+
{ title: "TriggerActionExtraData", description: "extra_data of a `trigger_action` row", additionalProperties: false }
|
|
88
|
+
);
|
|
89
|
+
const processLogTriggerEngineExtraDataSchema = Type.Union(
|
|
90
|
+
[
|
|
91
|
+
Type.Object({
|
|
92
|
+
code: Type.Literal(ProcessLogCode.TRIGGER_EVALUATION),
|
|
93
|
+
extra_data: triggerEvaluationExtraDataSchema
|
|
94
|
+
}),
|
|
95
|
+
Type.Object({ code: Type.Literal(ProcessLogCode.TRIGGER_ERROR), extra_data: triggerErrorExtraDataSchema }),
|
|
96
|
+
Type.Object({ code: Type.Literal(ProcessLogCode.TRIGGER_ACTION), extra_data: triggerActionExtraDataSchema })
|
|
97
|
+
],
|
|
98
|
+
{
|
|
99
|
+
title: "ProcessLogTriggerEngineExtraData",
|
|
100
|
+
description: "Ties each trigger-engine `code` to the shape its `extra_data` takes"
|
|
101
|
+
}
|
|
102
|
+
);
|
|
103
|
+
const processLogSchema = Type.Object(
|
|
104
|
+
{
|
|
105
|
+
id: Type.Number({ description: "Unique identifier of the row" }),
|
|
106
|
+
project_id: Type.Optional(
|
|
107
|
+
Type.Union([Type.Number(), Type.Null()], { description: "Project this row belongs to, when scoped to one" })
|
|
108
|
+
),
|
|
109
|
+
created_user: Type.Optional(
|
|
110
|
+
Type.Union([Type.Number(), Type.Null()], {
|
|
111
|
+
description: "User who caused the row to be written, when a user did"
|
|
112
|
+
})
|
|
113
|
+
),
|
|
114
|
+
related_model: Type.Optional(
|
|
115
|
+
Type.Union([Type.String({ maxLength: 255 }), Type.Null()], { description: "Table/entity kind the row is about" })
|
|
116
|
+
),
|
|
117
|
+
related_id: Type.Optional(
|
|
118
|
+
Type.Union([Type.String({ maxLength: 255 }), Type.Null()], {
|
|
119
|
+
description: "Id of the related entity, as a string"
|
|
120
|
+
})
|
|
121
|
+
),
|
|
122
|
+
code: Type.Optional(Type.Union([processLogCodeSchema, Type.Null()])),
|
|
123
|
+
log: Type.String({ description: "Short human-readable message" }),
|
|
124
|
+
long_log: Type.Optional(Type.Union([Type.String(), Type.Null()], { description: "Extended message, when needed" })),
|
|
125
|
+
extra_data: Type.Optional(
|
|
126
|
+
Type.Union([Type.Record(Type.String(), Type.Unknown()), Type.Null()], {
|
|
127
|
+
description: "Structured data specific to `code` — see the per-code schemas for the trigger-engine codes"
|
|
128
|
+
})
|
|
129
|
+
),
|
|
130
|
+
type: processLogTypeSchema,
|
|
131
|
+
requires_attention: Type.Optional(Type.Boolean({ description: "Whether the row needs a human to review it" })),
|
|
132
|
+
reviewed: Type.Optional(Type.Boolean({ description: "Whether the row has been reviewed" })),
|
|
133
|
+
reviewed_date: Type.Optional(
|
|
134
|
+
Type.Union([Type.String(), Type.Null()], {
|
|
135
|
+
description: `When the row was reviewed. Null while unreviewed. ${EMITTED_DATETIME_NOTE}`
|
|
136
|
+
})
|
|
137
|
+
),
|
|
138
|
+
// Correlation to a parent row (#348): a `trigger_action` row's parent is the `trigger_evaluation`
|
|
139
|
+
// (or `trigger_error`) row of the trigger that ran it, so an action's trace can always be walked
|
|
140
|
+
// back to the evaluation that triggered it. Optional/nullable because most rows (bulk upload,
|
|
141
|
+
// the trigger-evaluation row itself) have no parent, and because the column is applied out of
|
|
142
|
+
// band per ecosystem — see README.md — so it may be entirely absent from a given row's database.
|
|
143
|
+
parent_id: Type.Optional(
|
|
144
|
+
Type.Union([Type.Number(), Type.Null()], {
|
|
145
|
+
description: "Id of this row's parent process_log row, when it has one"
|
|
146
|
+
})
|
|
147
|
+
),
|
|
148
|
+
expires_at: Type.Optional(
|
|
149
|
+
Type.Union([Type.String(), Type.Null()], {
|
|
150
|
+
description: `Retention deadline; the row is purged after it, and never expires when null. ${EMITTED_DATETIME_NOTE}`,
|
|
151
|
+
examples: [API_DATETIME_EXAMPLE]
|
|
152
|
+
})
|
|
153
|
+
),
|
|
154
|
+
created_at: Type.Optional(
|
|
155
|
+
Type.String({
|
|
156
|
+
description: `When the row was created. ${EMITTED_DATETIME_NOTE}`,
|
|
157
|
+
examples: [API_DATETIME_EXAMPLE]
|
|
158
|
+
})
|
|
159
|
+
),
|
|
160
|
+
mod_time: Type.Optional(
|
|
161
|
+
Type.String({
|
|
162
|
+
description: `When the row was last modified. ${EMITTED_DATETIME_NOTE}`,
|
|
163
|
+
examples: [API_DATETIME_EXAMPLE]
|
|
164
|
+
})
|
|
165
|
+
)
|
|
166
|
+
},
|
|
167
|
+
{ title: "ProcessLog", description: "A process_log row" }
|
|
168
|
+
);
|
|
169
|
+
const listProcessLogQuerySchema = Type.Object(
|
|
170
|
+
{
|
|
171
|
+
code: Type.Optional(processLogCodeSchema),
|
|
172
|
+
type: Type.Optional(processLogTypeSchema),
|
|
173
|
+
related_model: Type.Optional(Type.String({ description: "Filter by the related entity kind" })),
|
|
174
|
+
related_id: Type.Optional(Type.String({ description: "Filter by the id of the related entity" })),
|
|
175
|
+
parent_id: Type.Optional(Type.Number({ description: "Filter by the id of the parent process_log row" })),
|
|
176
|
+
requires_attention: Type.Optional(Type.Boolean({ description: "Filter by whether the row needs review" })),
|
|
177
|
+
reviewed: Type.Optional(Type.Boolean({ description: "Filter by whether the row has been reviewed" })),
|
|
178
|
+
// `apiDateTime`, not a bare string: it carries `format: 'date-time'`, so a malformed value is
|
|
179
|
+
// rejected by the validator as a 400. A plain `Type.String` accepts anything and hands it to
|
|
180
|
+
// `getMySQLDateTime(value, true)`, which throws a `PublicApiError` with no `statusCode` — a 500
|
|
181
|
+
// for what is a bad request. Same type `alert.schema.ts` uses for its datetime fields.
|
|
182
|
+
created_from: Type.Optional(
|
|
183
|
+
Type.Union([apiDateTime], {
|
|
184
|
+
description: `Only rows created at or after this instant. ${API_DATETIME_ACCEPTED_NOTE}. ${EMITTED_DATETIME_NOTE}`,
|
|
185
|
+
examples: [API_DATETIME_EXAMPLE]
|
|
186
|
+
})
|
|
187
|
+
),
|
|
188
|
+
created_to: Type.Optional(
|
|
189
|
+
Type.Union([apiDateTime], {
|
|
190
|
+
description: `Only rows created at or before this instant. ${API_DATETIME_ACCEPTED_NOTE}. ${EMITTED_DATETIME_NOTE}`,
|
|
191
|
+
examples: [API_DATETIME_EXAMPLE]
|
|
192
|
+
})
|
|
193
|
+
)
|
|
194
|
+
},
|
|
195
|
+
{ title: "ListProcessLogQuery", description: "Filters available on the process_log list" }
|
|
196
|
+
);
|
|
197
|
+
export {
|
|
198
|
+
ProcessLogCode,
|
|
199
|
+
ProcessLogType,
|
|
200
|
+
listProcessLogQuerySchema,
|
|
201
|
+
processLogCodeSchema,
|
|
202
|
+
processLogSchema,
|
|
203
|
+
processLogTriggerEngineExtraDataSchema,
|
|
204
|
+
processLogTypeSchema,
|
|
205
|
+
triggerActionExtraDataSchema,
|
|
206
|
+
triggerErrorExtraDataSchema,
|
|
207
|
+
triggerEvaluationExtraDataSchema
|
|
208
|
+
};
|
|
209
|
+
//# sourceMappingURL=ecosystem-process-log.mjs.map
|