@owlmeans/planning 0.1.18-rc.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/README.md +169 -0
- package/agent-meta/manifest.json +16 -0
- package/agent-meta/skills/planning/SKILL.md +248 -0
- package/build/consts.d.ts +126 -0
- package/build/consts.d.ts.map +1 -0
- package/build/consts.js +129 -0
- package/build/consts.js.map +1 -0
- package/build/entrypoints.d.ts +14 -0
- package/build/entrypoints.d.ts.map +1 -0
- package/build/entrypoints.js +69 -0
- package/build/entrypoints.js.map +1 -0
- package/build/errors.d.ts +94 -0
- package/build/errors.d.ts.map +1 -0
- package/build/errors.js +169 -0
- package/build/errors.js.map +1 -0
- package/build/helpers/apply.d.ts +27 -0
- package/build/helpers/apply.d.ts.map +1 -0
- package/build/helpers/apply.js +162 -0
- package/build/helpers/apply.js.map +1 -0
- package/build/helpers/card.d.ts +17 -0
- package/build/helpers/card.d.ts.map +1 -0
- package/build/helpers/card.js +31 -0
- package/build/helpers/card.js.map +1 -0
- package/build/helpers/changes.d.ts +51 -0
- package/build/helpers/changes.d.ts.map +1 -0
- package/build/helpers/changes.js +277 -0
- package/build/helpers/changes.js.map +1 -0
- package/build/helpers/code.d.ts +24 -0
- package/build/helpers/code.d.ts.map +1 -0
- package/build/helpers/code.js +47 -0
- package/build/helpers/code.js.map +1 -0
- package/build/helpers/index.d.ts +9 -0
- package/build/helpers/index.d.ts.map +1 -0
- package/build/helpers/index.js +9 -0
- package/build/helpers/index.js.map +1 -0
- package/build/helpers/query.d.ts +39 -0
- package/build/helpers/query.d.ts.map +1 -0
- package/build/helpers/query.js +293 -0
- package/build/helpers/query.js.map +1 -0
- package/build/helpers/specification.d.ts +21 -0
- package/build/helpers/specification.d.ts.map +1 -0
- package/build/helpers/specification.js +48 -0
- package/build/helpers/specification.js.map +1 -0
- package/build/helpers/status.d.ts +44 -0
- package/build/helpers/status.d.ts.map +1 -0
- package/build/helpers/status.js +78 -0
- package/build/helpers/status.js.map +1 -0
- package/build/helpers/validate.d.ts +30 -0
- package/build/helpers/validate.d.ts.map +1 -0
- package/build/helpers/validate.js +93 -0
- package/build/helpers/validate.js.map +1 -0
- package/build/i18n/be.json +51 -0
- package/build/i18n/de.json +51 -0
- package/build/i18n/en.json +51 -0
- package/build/i18n/es.json +51 -0
- package/build/i18n/pl.json +51 -0
- package/build/i18n/ru.json +51 -0
- package/build/i18n/uk.json +51 -0
- package/build/i18n.d.ts +2 -0
- package/build/i18n.d.ts.map +1 -0
- package/build/i18n.js +19 -0
- package/build/i18n.js.map +1 -0
- package/build/index.d.ts +10 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +9 -0
- package/build/index.js.map +1 -0
- package/build/models/index.d.ts +7 -0
- package/build/models/index.d.ts.map +1 -0
- package/build/models/index.js +19 -0
- package/build/models/index.js.map +1 -0
- package/build/models/project.d.ts +4 -0
- package/build/models/project.d.ts.map +1 -0
- package/build/models/project.js +17 -0
- package/build/models/project.js.map +1 -0
- package/build/models/specification.d.ts +4 -0
- package/build/models/specification.d.ts.map +1 -0
- package/build/models/specification.js +15 -0
- package/build/models/specification.js.map +1 -0
- package/build/models/workcard.d.ts +14 -0
- package/build/models/workcard.d.ts.map +1 -0
- package/build/models/workcard.js +103 -0
- package/build/models/workcard.js.map +1 -0
- package/build/queue/index.d.ts +25 -0
- package/build/queue/index.d.ts.map +1 -0
- package/build/queue/index.js +14 -0
- package/build/queue/index.js.map +1 -0
- package/build/registry.d.ts +10 -0
- package/build/registry.d.ts.map +1 -0
- package/build/registry.js +75 -0
- package/build/registry.js.map +1 -0
- package/build/schemas.d.ts +56 -0
- package/build/schemas.d.ts.map +1 -0
- package/build/schemas.js +578 -0
- package/build/schemas.js.map +1 -0
- package/build/types.d.ts +785 -0
- package/build/types.d.ts.map +1 -0
- package/build/types.js +2 -0
- package/build/types.js.map +1 -0
- package/package.json +58 -0
- package/src/consts.ts +136 -0
- package/src/entrypoints.ts +127 -0
- package/src/errors.ts +207 -0
- package/src/helpers/apply.ts +183 -0
- package/src/helpers/card.ts +42 -0
- package/src/helpers/changes.ts +333 -0
- package/src/helpers/code.ts +66 -0
- package/src/helpers/index.ts +8 -0
- package/src/helpers/query.ts +345 -0
- package/src/helpers/specification.ts +65 -0
- package/src/helpers/status.ts +117 -0
- package/src/helpers/validate.ts +107 -0
- package/src/i18n/be.json +51 -0
- package/src/i18n/de.json +51 -0
- package/src/i18n/en.json +51 -0
- package/src/i18n/es.json +51 -0
- package/src/i18n/pl.json +51 -0
- package/src/i18n/ru.json +51 -0
- package/src/i18n/uk.json +51 -0
- package/src/i18n.ts +21 -0
- package/src/index.ts +9 -0
- package/src/models/index.ts +21 -0
- package/src/models/project.ts +24 -0
- package/src/models/specification.ts +21 -0
- package/src/models/workcard.ts +138 -0
- package/src/queue/index.ts +31 -0
- package/src/registry.ts +90 -0
- package/src/schemas.ts +654 -0
- package/src/types.ts +837 -0
- package/tests/apply.spec.ts +176 -0
- package/tests/code.spec.ts +40 -0
- package/tests/entrypoints.spec.ts +57 -0
- package/tests/fixtures.ts +124 -0
- package/tests/i18n.spec.ts +30 -0
- package/tests/models.spec.ts +133 -0
- package/tests/query.spec.ts +90 -0
- package/tests/schemas.spec.ts +74 -0
- package/tests/status.spec.ts +75 -0
- package/tests/tsconfig.json +17 -0
- package/tsconfig.json +15 -0
package/src/i18n/de.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": {
|
|
3
|
+
"card": "Karte",
|
|
4
|
+
"project": "Projekt",
|
|
5
|
+
"specification": "Spezifikation"
|
|
6
|
+
},
|
|
7
|
+
"intrinsic": {
|
|
8
|
+
"planned": "Geplant",
|
|
9
|
+
"in-progress": "In Arbeit",
|
|
10
|
+
"closed": "Abgeschlossen"
|
|
11
|
+
},
|
|
12
|
+
"action": {
|
|
13
|
+
"create": "Erstellt",
|
|
14
|
+
"update": "Aktualisiert",
|
|
15
|
+
"transit": "Status geändert",
|
|
16
|
+
"link": "Verknüpft",
|
|
17
|
+
"unlink": "Verknüpfung entfernt",
|
|
18
|
+
"delete": "Gelöscht"
|
|
19
|
+
},
|
|
20
|
+
"commit": {
|
|
21
|
+
"pending": "Wird gespeichert…",
|
|
22
|
+
"committed": "Gespeichert",
|
|
23
|
+
"failed": "Nicht gespeichert"
|
|
24
|
+
},
|
|
25
|
+
"format": {
|
|
26
|
+
"markdown": "Markdown",
|
|
27
|
+
"json": "JSON",
|
|
28
|
+
"text": "Reiner Text"
|
|
29
|
+
},
|
|
30
|
+
"errors": {
|
|
31
|
+
"PlanningError": "Die Planungsanfrage konnte nicht ausgeführt werden",
|
|
32
|
+
"PlanningErrorWorkcardNotFound": "Dieses Element existiert nicht oder ist für dich nicht verfügbar",
|
|
33
|
+
"PlanningErrorUnknownWorkcardType": "Dieser Elementtyp ist unbekannt",
|
|
34
|
+
"PlanningErrorUnknownStatusFlow": "Dieser Statusablauf ist unbekannt",
|
|
35
|
+
"PlanningErrorParentNotFound": "Das übergeordnete Element existiert nicht",
|
|
36
|
+
"PlanningErrorCardTypeNotAllowed": "Ein Element dieses Typs kann hier nicht hinzugefügt werden",
|
|
37
|
+
"PlanningErrorRefused": "Die Änderung wurde abgelehnt",
|
|
38
|
+
"PlanningErrorIllegalTransition": "Dieser Statuswechsel ist vom aktuellen Status aus nicht erlaubt",
|
|
39
|
+
"PlanningErrorFieldsInvalid": "Einige Felder haben ungültige Werte",
|
|
40
|
+
"PlanningErrorLabelNotAllowed": "Dieses Label ist hier nicht erlaubt",
|
|
41
|
+
"PlanningErrorSpecificationSlotUnknown": "Diese Art von Dokument ist hier nicht erlaubt",
|
|
42
|
+
"PlanningErrorSpecificationRevisionConflict": "Dieses Dokument existiert bereits — bearbeite es stattdessen",
|
|
43
|
+
"PlanningErrorRelationshipRefused": "Diese Verknüpfung ist nicht erlaubt",
|
|
44
|
+
"PlanningErrorCodeTaken": "Dieser Code ist bereits vergeben",
|
|
45
|
+
"PlanningErrorWorkcardConflict": "Jemand hat dieses Element inzwischen geändert — neu laden und erneut versuchen",
|
|
46
|
+
"PlanningErrorCommitTimeout": "Die Änderung wird noch gespeichert — prüfe es gleich noch einmal",
|
|
47
|
+
"PlanningErrorCommitFailed": "Die Änderung konnte nicht gespeichert werden",
|
|
48
|
+
"PlanningErrorScopeMismatch": "Dieses Element existiert nicht oder ist für dich nicht verfügbar",
|
|
49
|
+
"PlanningErrorUnsupported": "Dieser Vorgang wird für dieses Element nicht unterstützt"
|
|
50
|
+
}
|
|
51
|
+
}
|
package/src/i18n/en.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": {
|
|
3
|
+
"card": "Card",
|
|
4
|
+
"project": "Project",
|
|
5
|
+
"specification": "Specification"
|
|
6
|
+
},
|
|
7
|
+
"intrinsic": {
|
|
8
|
+
"planned": "Planned",
|
|
9
|
+
"in-progress": "In progress",
|
|
10
|
+
"closed": "Closed"
|
|
11
|
+
},
|
|
12
|
+
"action": {
|
|
13
|
+
"create": "Created",
|
|
14
|
+
"update": "Updated",
|
|
15
|
+
"transit": "Status changed",
|
|
16
|
+
"link": "Linked",
|
|
17
|
+
"unlink": "Unlinked",
|
|
18
|
+
"delete": "Deleted"
|
|
19
|
+
},
|
|
20
|
+
"commit": {
|
|
21
|
+
"pending": "Saving…",
|
|
22
|
+
"committed": "Saved",
|
|
23
|
+
"failed": "Not saved"
|
|
24
|
+
},
|
|
25
|
+
"format": {
|
|
26
|
+
"markdown": "Markdown",
|
|
27
|
+
"json": "JSON",
|
|
28
|
+
"text": "Plain text"
|
|
29
|
+
},
|
|
30
|
+
"errors": {
|
|
31
|
+
"PlanningError": "The planning request could not be completed",
|
|
32
|
+
"PlanningErrorWorkcardNotFound": "This item does not exist or is not available to you",
|
|
33
|
+
"PlanningErrorUnknownWorkcardType": "This item type is not known",
|
|
34
|
+
"PlanningErrorUnknownStatusFlow": "This status flow is not known",
|
|
35
|
+
"PlanningErrorParentNotFound": "The parent item does not exist",
|
|
36
|
+
"PlanningErrorCardTypeNotAllowed": "This item type cannot be added here",
|
|
37
|
+
"PlanningErrorRefused": "The change was refused",
|
|
38
|
+
"PlanningErrorIllegalTransition": "This status change is not allowed from the current status",
|
|
39
|
+
"PlanningErrorFieldsInvalid": "Some fields have invalid values",
|
|
40
|
+
"PlanningErrorLabelNotAllowed": "This label is not allowed here",
|
|
41
|
+
"PlanningErrorSpecificationSlotUnknown": "This kind of document is not allowed here",
|
|
42
|
+
"PlanningErrorSpecificationRevisionConflict": "This document already exists — edit it instead",
|
|
43
|
+
"PlanningErrorRelationshipRefused": "This link is not allowed",
|
|
44
|
+
"PlanningErrorCodeTaken": "This code is already taken",
|
|
45
|
+
"PlanningErrorWorkcardConflict": "Someone changed this item in the meantime — reload and try again",
|
|
46
|
+
"PlanningErrorCommitTimeout": "The change is still being saved — check again shortly",
|
|
47
|
+
"PlanningErrorCommitFailed": "The change could not be saved",
|
|
48
|
+
"PlanningErrorScopeMismatch": "This item does not exist or is not available to you",
|
|
49
|
+
"PlanningErrorUnsupported": "This operation is not supported for this item"
|
|
50
|
+
}
|
|
51
|
+
}
|
package/src/i18n/es.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": {
|
|
3
|
+
"card": "Tarjeta",
|
|
4
|
+
"project": "Proyecto",
|
|
5
|
+
"specification": "Especificación"
|
|
6
|
+
},
|
|
7
|
+
"intrinsic": {
|
|
8
|
+
"planned": "Planificado",
|
|
9
|
+
"in-progress": "En curso",
|
|
10
|
+
"closed": "Cerrado"
|
|
11
|
+
},
|
|
12
|
+
"action": {
|
|
13
|
+
"create": "Creado",
|
|
14
|
+
"update": "Actualizado",
|
|
15
|
+
"transit": "Estado cambiado",
|
|
16
|
+
"link": "Vinculado",
|
|
17
|
+
"unlink": "Vínculo eliminado",
|
|
18
|
+
"delete": "Eliminado"
|
|
19
|
+
},
|
|
20
|
+
"commit": {
|
|
21
|
+
"pending": "Guardando…",
|
|
22
|
+
"committed": "Guardado",
|
|
23
|
+
"failed": "No guardado"
|
|
24
|
+
},
|
|
25
|
+
"format": {
|
|
26
|
+
"markdown": "Markdown",
|
|
27
|
+
"json": "JSON",
|
|
28
|
+
"text": "Texto sin formato"
|
|
29
|
+
},
|
|
30
|
+
"errors": {
|
|
31
|
+
"PlanningError": "No se pudo completar la solicitud de planificación",
|
|
32
|
+
"PlanningErrorWorkcardNotFound": "Este elemento no existe o no está disponible para ti",
|
|
33
|
+
"PlanningErrorUnknownWorkcardType": "Este tipo de elemento no se conoce",
|
|
34
|
+
"PlanningErrorUnknownStatusFlow": "Este flujo de estados no se conoce",
|
|
35
|
+
"PlanningErrorParentNotFound": "El elemento superior no existe",
|
|
36
|
+
"PlanningErrorCardTypeNotAllowed": "No se puede añadir aquí un elemento de este tipo",
|
|
37
|
+
"PlanningErrorRefused": "El cambio fue rechazado",
|
|
38
|
+
"PlanningErrorIllegalTransition": "Este cambio de estado no está permitido desde el estado actual",
|
|
39
|
+
"PlanningErrorFieldsInvalid": "Algunos campos tienen valores no válidos",
|
|
40
|
+
"PlanningErrorLabelNotAllowed": "Esta etiqueta no está permitida aquí",
|
|
41
|
+
"PlanningErrorSpecificationSlotUnknown": "Este tipo de documento no está permitido aquí",
|
|
42
|
+
"PlanningErrorSpecificationRevisionConflict": "Este documento ya existe — edítalo en su lugar",
|
|
43
|
+
"PlanningErrorRelationshipRefused": "Este vínculo no está permitido",
|
|
44
|
+
"PlanningErrorCodeTaken": "Este código ya está en uso",
|
|
45
|
+
"PlanningErrorWorkcardConflict": "Alguien cambió este elemento mientras tanto — recarga e inténtalo de nuevo",
|
|
46
|
+
"PlanningErrorCommitTimeout": "El cambio aún se está guardando — vuelve a comprobarlo en breve",
|
|
47
|
+
"PlanningErrorCommitFailed": "No se pudo guardar el cambio",
|
|
48
|
+
"PlanningErrorScopeMismatch": "Este elemento no existe o no está disponible para ti",
|
|
49
|
+
"PlanningErrorUnsupported": "Esta operación no es compatible con este elemento"
|
|
50
|
+
}
|
|
51
|
+
}
|
package/src/i18n/pl.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": {
|
|
3
|
+
"card": "Karta",
|
|
4
|
+
"project": "Projekt",
|
|
5
|
+
"specification": "Specyfikacja"
|
|
6
|
+
},
|
|
7
|
+
"intrinsic": {
|
|
8
|
+
"planned": "Zaplanowane",
|
|
9
|
+
"in-progress": "W toku",
|
|
10
|
+
"closed": "Zamknięte"
|
|
11
|
+
},
|
|
12
|
+
"action": {
|
|
13
|
+
"create": "Utworzono",
|
|
14
|
+
"update": "Zaktualizowano",
|
|
15
|
+
"transit": "Zmieniono status",
|
|
16
|
+
"link": "Powiązano",
|
|
17
|
+
"unlink": "Usunięto powiązanie",
|
|
18
|
+
"delete": "Usunięto"
|
|
19
|
+
},
|
|
20
|
+
"commit": {
|
|
21
|
+
"pending": "Zapisywanie…",
|
|
22
|
+
"committed": "Zapisano",
|
|
23
|
+
"failed": "Nie zapisano"
|
|
24
|
+
},
|
|
25
|
+
"format": {
|
|
26
|
+
"markdown": "Markdown",
|
|
27
|
+
"json": "JSON",
|
|
28
|
+
"text": "Zwykły tekst"
|
|
29
|
+
},
|
|
30
|
+
"errors": {
|
|
31
|
+
"PlanningError": "Nie udało się wykonać żądania planowania",
|
|
32
|
+
"PlanningErrorWorkcardNotFound": "Ten element nie istnieje lub nie jest dla Ciebie dostępny",
|
|
33
|
+
"PlanningErrorUnknownWorkcardType": "Ten typ elementu jest nieznany",
|
|
34
|
+
"PlanningErrorUnknownStatusFlow": "Ten przepływ statusów jest nieznany",
|
|
35
|
+
"PlanningErrorParentNotFound": "Element nadrzędny nie istnieje",
|
|
36
|
+
"PlanningErrorCardTypeNotAllowed": "Nie można tutaj dodać elementu tego typu",
|
|
37
|
+
"PlanningErrorRefused": "Zmiana została odrzucona",
|
|
38
|
+
"PlanningErrorIllegalTransition": "Ta zmiana statusu jest niedozwolona z bieżącego statusu",
|
|
39
|
+
"PlanningErrorFieldsInvalid": "Niektóre pola mają nieprawidłowe wartości",
|
|
40
|
+
"PlanningErrorLabelNotAllowed": "Ta etykieta jest tutaj niedozwolona",
|
|
41
|
+
"PlanningErrorSpecificationSlotUnknown": "Ten rodzaj dokumentu jest tutaj niedozwolony",
|
|
42
|
+
"PlanningErrorSpecificationRevisionConflict": "Ten dokument już istnieje — edytuj go",
|
|
43
|
+
"PlanningErrorRelationshipRefused": "To powiązanie jest niedozwolone",
|
|
44
|
+
"PlanningErrorCodeTaken": "Ten kod jest już zajęty",
|
|
45
|
+
"PlanningErrorWorkcardConflict": "Ktoś w międzyczasie zmienił ten element — odśwież i spróbuj ponownie",
|
|
46
|
+
"PlanningErrorCommitTimeout": "Zmiana jest nadal zapisywana — sprawdź ponownie za chwilę",
|
|
47
|
+
"PlanningErrorCommitFailed": "Nie udało się zapisać zmiany",
|
|
48
|
+
"PlanningErrorScopeMismatch": "Ten element nie istnieje lub nie jest dla Ciebie dostępny",
|
|
49
|
+
"PlanningErrorUnsupported": "Ta operacja nie jest obsługiwana dla tego elementu"
|
|
50
|
+
}
|
|
51
|
+
}
|
package/src/i18n/ru.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": {
|
|
3
|
+
"card": "Карточка",
|
|
4
|
+
"project": "Проект",
|
|
5
|
+
"specification": "Спецификация"
|
|
6
|
+
},
|
|
7
|
+
"intrinsic": {
|
|
8
|
+
"planned": "Запланировано",
|
|
9
|
+
"in-progress": "В работе",
|
|
10
|
+
"closed": "Закрыто"
|
|
11
|
+
},
|
|
12
|
+
"action": {
|
|
13
|
+
"create": "Создано",
|
|
14
|
+
"update": "Обновлено",
|
|
15
|
+
"transit": "Статус изменён",
|
|
16
|
+
"link": "Связано",
|
|
17
|
+
"unlink": "Связь удалена",
|
|
18
|
+
"delete": "Удалено"
|
|
19
|
+
},
|
|
20
|
+
"commit": {
|
|
21
|
+
"pending": "Сохранение…",
|
|
22
|
+
"committed": "Сохранено",
|
|
23
|
+
"failed": "Не сохранено"
|
|
24
|
+
},
|
|
25
|
+
"format": {
|
|
26
|
+
"markdown": "Markdown",
|
|
27
|
+
"json": "JSON",
|
|
28
|
+
"text": "Обычный текст"
|
|
29
|
+
},
|
|
30
|
+
"errors": {
|
|
31
|
+
"PlanningError": "Не удалось выполнить запрос планирования",
|
|
32
|
+
"PlanningErrorWorkcardNotFound": "Этот элемент не существует или недоступен вам",
|
|
33
|
+
"PlanningErrorUnknownWorkcardType": "Этот тип элемента неизвестен",
|
|
34
|
+
"PlanningErrorUnknownStatusFlow": "Этот поток статусов неизвестен",
|
|
35
|
+
"PlanningErrorParentNotFound": "Родительский элемент не существует",
|
|
36
|
+
"PlanningErrorCardTypeNotAllowed": "Элемент этого типа нельзя добавить сюда",
|
|
37
|
+
"PlanningErrorRefused": "Изменение отклонено",
|
|
38
|
+
"PlanningErrorIllegalTransition": "Такая смена статуса недопустима из текущего статуса",
|
|
39
|
+
"PlanningErrorFieldsInvalid": "Некоторые поля содержат недопустимые значения",
|
|
40
|
+
"PlanningErrorLabelNotAllowed": "Эта метка здесь недопустима",
|
|
41
|
+
"PlanningErrorSpecificationSlotUnknown": "Этот вид документа здесь недопустим",
|
|
42
|
+
"PlanningErrorSpecificationRevisionConflict": "Этот документ уже существует — отредактируйте его",
|
|
43
|
+
"PlanningErrorRelationshipRefused": "Эта связь недопустима",
|
|
44
|
+
"PlanningErrorCodeTaken": "Этот код уже занят",
|
|
45
|
+
"PlanningErrorWorkcardConflict": "Кто-то изменил этот элемент за это время — обновите и попробуйте снова",
|
|
46
|
+
"PlanningErrorCommitTimeout": "Изменение ещё сохраняется — проверьте чуть позже",
|
|
47
|
+
"PlanningErrorCommitFailed": "Не удалось сохранить изменение",
|
|
48
|
+
"PlanningErrorScopeMismatch": "Этот элемент не существует или недоступен вам",
|
|
49
|
+
"PlanningErrorUnsupported": "Эта операция не поддерживается для этого элемента"
|
|
50
|
+
}
|
|
51
|
+
}
|
package/src/i18n/uk.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind": {
|
|
3
|
+
"card": "Картка",
|
|
4
|
+
"project": "Проєкт",
|
|
5
|
+
"specification": "Специфікація"
|
|
6
|
+
},
|
|
7
|
+
"intrinsic": {
|
|
8
|
+
"planned": "Заплановано",
|
|
9
|
+
"in-progress": "У роботі",
|
|
10
|
+
"closed": "Закрито"
|
|
11
|
+
},
|
|
12
|
+
"action": {
|
|
13
|
+
"create": "Створено",
|
|
14
|
+
"update": "Оновлено",
|
|
15
|
+
"transit": "Статус змінено",
|
|
16
|
+
"link": "Пов’язано",
|
|
17
|
+
"unlink": "Зв’язок видалено",
|
|
18
|
+
"delete": "Видалено"
|
|
19
|
+
},
|
|
20
|
+
"commit": {
|
|
21
|
+
"pending": "Збереження…",
|
|
22
|
+
"committed": "Збережено",
|
|
23
|
+
"failed": "Не збережено"
|
|
24
|
+
},
|
|
25
|
+
"format": {
|
|
26
|
+
"markdown": "Markdown",
|
|
27
|
+
"json": "JSON",
|
|
28
|
+
"text": "Звичайний текст"
|
|
29
|
+
},
|
|
30
|
+
"errors": {
|
|
31
|
+
"PlanningError": "Не вдалося виконати запит планування",
|
|
32
|
+
"PlanningErrorWorkcardNotFound": "Цей елемент не існує або недоступний вам",
|
|
33
|
+
"PlanningErrorUnknownWorkcardType": "Цей тип елемента невідомий",
|
|
34
|
+
"PlanningErrorUnknownStatusFlow": "Цей потік статусів невідомий",
|
|
35
|
+
"PlanningErrorParentNotFound": "Батьківський елемент не існує",
|
|
36
|
+
"PlanningErrorCardTypeNotAllowed": "Елемент цього типу не можна додати сюди",
|
|
37
|
+
"PlanningErrorRefused": "Зміну відхилено",
|
|
38
|
+
"PlanningErrorIllegalTransition": "Така зміна статусу неприпустима з поточного статусу",
|
|
39
|
+
"PlanningErrorFieldsInvalid": "Деякі поля мають неприпустимі значення",
|
|
40
|
+
"PlanningErrorLabelNotAllowed": "Ця мітка тут неприпустима",
|
|
41
|
+
"PlanningErrorSpecificationSlotUnknown": "Цей вид документа тут неприпустимий",
|
|
42
|
+
"PlanningErrorSpecificationRevisionConflict": "Цей документ уже існує — відредагуйте його",
|
|
43
|
+
"PlanningErrorRelationshipRefused": "Цей зв’язок неприпустимий",
|
|
44
|
+
"PlanningErrorCodeTaken": "Цей код уже зайнятий",
|
|
45
|
+
"PlanningErrorWorkcardConflict": "Хтось змінив цей елемент тим часом — оновіть і спробуйте знову",
|
|
46
|
+
"PlanningErrorCommitTimeout": "Зміна ще зберігається — перевірте трохи пізніше",
|
|
47
|
+
"PlanningErrorCommitFailed": "Не вдалося зберегти зміну",
|
|
48
|
+
"PlanningErrorScopeMismatch": "Цей елемент не існує або недоступний вам",
|
|
49
|
+
"PlanningErrorUnsupported": "Ця операція не підтримується для цього елемента"
|
|
50
|
+
}
|
|
51
|
+
}
|
package/src/i18n.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { addI18nLib } from '@owlmeans/i18n'
|
|
2
|
+
import { PLANNING_I18N } from './consts.js'
|
|
3
|
+
|
|
4
|
+
import en from './i18n/en.json' with { type: 'json' }
|
|
5
|
+
import pl from './i18n/pl.json' with { type: 'json' }
|
|
6
|
+
import ru from './i18n/ru.json' with { type: 'json' }
|
|
7
|
+
import be from './i18n/be.json' with { type: 'json' }
|
|
8
|
+
import uk from './i18n/uk.json' with { type: 'json' }
|
|
9
|
+
import es from './i18n/es.json' with { type: 'json' }
|
|
10
|
+
import de from './i18n/de.json' with { type: 'json' }
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Labels under `lib:planning.*`, and every refusal under the shared `errors` resource keyed by its
|
|
14
|
+
* type name — which is where a panel's error lookup (`errors.<type>`) finds them.
|
|
15
|
+
*/
|
|
16
|
+
const LANGUAGES = { en, pl, ru, be, uk, es, de }
|
|
17
|
+
|
|
18
|
+
Object.entries(LANGUAGES).forEach(([lng, data]) => {
|
|
19
|
+
addI18nLib(lng, PLANNING_I18N, data)
|
|
20
|
+
addI18nLib(lng, 'errors', data.errors)
|
|
21
|
+
})
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type * from './types.js'
|
|
2
|
+
export * from './consts.js'
|
|
3
|
+
export * from './schemas.js'
|
|
4
|
+
export * from './errors.js'
|
|
5
|
+
export * from './entrypoints.js'
|
|
6
|
+
export * from './registry.js'
|
|
7
|
+
export * from './helpers/index.js'
|
|
8
|
+
export * from './models/index.js'
|
|
9
|
+
export * from './i18n.js'
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { WorkcardKind } from '../consts.js'
|
|
2
|
+
import type { PlanningFacade, Project, Specification, Workcard, WorkcardModel } from '../types.js'
|
|
3
|
+
import { makeProjectModel } from './project.js'
|
|
4
|
+
import { makeSpecificationModel } from './specification.js'
|
|
5
|
+
import { makeWorkcardModel } from './workcard.js'
|
|
6
|
+
|
|
7
|
+
export { executeFor, makeWorkcardModel } from './workcard.js'
|
|
8
|
+
export { makeProjectModel } from './project.js'
|
|
9
|
+
export { makeSpecificationModel } from './specification.js'
|
|
10
|
+
|
|
11
|
+
/** The model a record's kind calls for — what a facade's `model()` answers. */
|
|
12
|
+
export const modelOf = <T extends Workcard = Workcard>(record: T, facade: PlanningFacade): WorkcardModel<T> => {
|
|
13
|
+
switch (record.kind) {
|
|
14
|
+
case WorkcardKind.Project:
|
|
15
|
+
return makeProjectModel(record as unknown as Project, facade) as unknown as WorkcardModel<T>
|
|
16
|
+
case WorkcardKind.Specification:
|
|
17
|
+
return makeSpecificationModel(record as unknown as Specification, facade) as unknown as WorkcardModel<T>
|
|
18
|
+
default:
|
|
19
|
+
return makeWorkcardModel(record, facade)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { IntrinsicStatus, WorkcardKind } from '../consts.js'
|
|
2
|
+
import type { PlanningFacade, Project, ProjectModel } from '../types.js'
|
|
3
|
+
import { makeWorkcardModel } from './workcard.js'
|
|
4
|
+
|
|
5
|
+
/** A workcard model plus the project's own reads: its cards, its sub-projects, its summary. */
|
|
6
|
+
export const makeProjectModel = (record: Project, facade: PlanningFacade): ProjectModel => {
|
|
7
|
+
const model = makeWorkcardModel<Project>(record, facade)
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
...model,
|
|
11
|
+
|
|
12
|
+
cards: query => facade.cards.list({ ...query, within: model.id, kind: WorkcardKind.Card }),
|
|
13
|
+
|
|
14
|
+
projects: query => facade.cards.list({ ...query, within: model.id, kind: WorkcardKind.Project }),
|
|
15
|
+
|
|
16
|
+
summary: async query => (await facade.cards.summary([model.id], query))[model.id] ?? {
|
|
17
|
+
total: 0, [IntrinsicStatus.Planned]: 0, [IntrinsicStatus.InProgress]: 0, [IntrinsicStatus.Closed]: 0,
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
purge: opts => model.remove(opts),
|
|
21
|
+
|
|
22
|
+
reload: async () => makeProjectModel(await facade.cards.get(model.id) as Project, facade),
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { PlanningFacade, Specification, SpecificationModel } from '../types.js'
|
|
2
|
+
import { makeWorkcardModel } from './workcard.js'
|
|
3
|
+
|
|
4
|
+
/** A workcard model over one document: its body, a revision of it, and its history from the log. */
|
|
5
|
+
export const makeSpecificationModel = (record: Specification, facade: PlanningFacade): SpecificationModel => {
|
|
6
|
+
const model = makeWorkcardModel<Specification>(record, facade)
|
|
7
|
+
|
|
8
|
+
return {
|
|
9
|
+
...model,
|
|
10
|
+
|
|
11
|
+
body: () => record.body,
|
|
12
|
+
|
|
13
|
+
revise: (body, opts) => model.update(Object.fromEntries(Object.entries({
|
|
14
|
+
body, version: opts?.version, ref: opts?.ref,
|
|
15
|
+
}).filter(([, value]) => value !== undefined)), opts),
|
|
16
|
+
|
|
17
|
+
history: limit => facade.specifications.revisions(model.id, limit),
|
|
18
|
+
|
|
19
|
+
reload: async () => makeSpecificationModel(await facade.specifications.get(model.id), facade),
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { IntrinsicStatus, TransitionAction, WorkcardKind } from '../consts.js'
|
|
2
|
+
import { PlanningError } from '../errors.js'
|
|
3
|
+
import { isPending } from '../helpers/card.js'
|
|
4
|
+
import { slotOf, specificationTypeOf } from '../helpers/specification.js'
|
|
5
|
+
import {
|
|
6
|
+
canTransit, initialStatusOf, intrinsicOf, primaryFlowOf, transitionsFrom,
|
|
7
|
+
} from '../helpers/status.js'
|
|
8
|
+
import type {
|
|
9
|
+
ExecuteOptions, ModelExecuteOptions, PlanningFacade, TransitionExecution, TransitionReceipt,
|
|
10
|
+
Workcard, WorkcardModel,
|
|
11
|
+
} from '../types.js'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Run an execution with a model's defaults: `expectSeq` is the record's head (its seq when nothing
|
|
15
|
+
* is in flight) unless the caller names one — `null` opts out.
|
|
16
|
+
*/
|
|
17
|
+
export const executeFor = (
|
|
18
|
+
facade: PlanningFacade, record: Pick<Workcard, 'seq' | 'head'> | null, exec: TransitionExecution,
|
|
19
|
+
opts?: ModelExecuteOptions
|
|
20
|
+
): Promise<TransitionReceipt> => {
|
|
21
|
+
const { wait, timeout, actor, cause, key, expectSeq } = opts ?? {}
|
|
22
|
+
const options: ExecuteOptions = Object.fromEntries(Object.entries({ wait, timeout })
|
|
23
|
+
.filter(([, value]) => value !== undefined))
|
|
24
|
+
|
|
25
|
+
return facade.execute(Object.fromEntries(Object.entries({
|
|
26
|
+
...exec,
|
|
27
|
+
actor,
|
|
28
|
+
cause,
|
|
29
|
+
key,
|
|
30
|
+
expectSeq: expectSeq !== undefined ? expectSeq : record == null ? undefined : record.head ?? record.seq,
|
|
31
|
+
}).filter(([, value]) => value !== undefined)) as unknown as TransitionExecution, options)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The same object on a server and in a browser: reads answer from the schema registry with no I/O,
|
|
36
|
+
* writes build a {@link TransitionExecution} and hand it to the facade.
|
|
37
|
+
*
|
|
38
|
+
* @throws {PlanningError} `malformed:model-without-id` for a record that was never stored
|
|
39
|
+
*/
|
|
40
|
+
export const makeWorkcardModel = <T extends Workcard = Workcard>(record: T, facade: PlanningFacade): WorkcardModel<T> => {
|
|
41
|
+
if (record.id == null) {
|
|
42
|
+
throw new PlanningError('malformed:model-without-id')
|
|
43
|
+
}
|
|
44
|
+
const id = record.id
|
|
45
|
+
const run = (exec: Omit<TransitionExecution, 'card'>, opts?: ModelExecuteOptions) =>
|
|
46
|
+
executeFor(facade, record, { ...exec, card: id }, opts)
|
|
47
|
+
|
|
48
|
+
const model: WorkcardModel<T> = {
|
|
49
|
+
record,
|
|
50
|
+
id,
|
|
51
|
+
kind: record.kind,
|
|
52
|
+
type: record.type,
|
|
53
|
+
|
|
54
|
+
schema: () => facade.schemas.type(record.type),
|
|
55
|
+
|
|
56
|
+
flow: flowId => facade.schemas.flow(flowId ?? primaryFlowOf(model.schema())),
|
|
57
|
+
|
|
58
|
+
statusOf: flowId => {
|
|
59
|
+
const primary = primaryFlowOf(model.schema())
|
|
60
|
+
if (flowId == null || flowId === primary) {
|
|
61
|
+
return record.status
|
|
62
|
+
}
|
|
63
|
+
return record.flows[flowId] ?? initialStatusOf(model.flow(flowId))
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
intrinsicOf: flowId => flowId == null
|
|
67
|
+
? record.intrinsic
|
|
68
|
+
: intrinsicOf(model.flow(flowId), model.statusOf(flowId)) ?? IntrinsicStatus.Planned,
|
|
69
|
+
|
|
70
|
+
can: (transition, flowId) => canTransit(model.flow(flowId), transition, model.statusOf(flowId)),
|
|
71
|
+
|
|
72
|
+
available: flowId => transitionsFrom(model.flow(flowId), model.statusOf(flowId)),
|
|
73
|
+
|
|
74
|
+
pending: () => isPending(record),
|
|
75
|
+
|
|
76
|
+
transit: (transition, changes, opts) => run({
|
|
77
|
+
action: TransitionAction.Transit, transition, flow: opts?.flow, changes,
|
|
78
|
+
}, opts),
|
|
79
|
+
|
|
80
|
+
update: (changes, opts) => run({ action: TransitionAction.Update, changes, unset: opts?.unset }, opts),
|
|
81
|
+
|
|
82
|
+
remove: opts => run({ action: TransitionAction.Delete }, opts),
|
|
83
|
+
|
|
84
|
+
link: (type, to, fields, opts) => run({
|
|
85
|
+
action: TransitionAction.Link, link: { type, from: id, to, ...(fields != null ? { fields } : {}) },
|
|
86
|
+
}, opts),
|
|
87
|
+
|
|
88
|
+
unlink: (type, to, opts) => run({ action: TransitionAction.Unlink, link: { type, from: id, to } }, opts),
|
|
89
|
+
|
|
90
|
+
children: query => facade.cards.list({ ...query, parent: id }),
|
|
91
|
+
|
|
92
|
+
relationships: query => facade.relationships.list({ ...query, from: query?.from ?? id }),
|
|
93
|
+
|
|
94
|
+
transitions: query => facade.transitions.list({ ...query, card: id }),
|
|
95
|
+
|
|
96
|
+
specification: category => facade.specifications.current(id, category),
|
|
97
|
+
|
|
98
|
+
specifications: query => facade.specifications.list(id, query),
|
|
99
|
+
|
|
100
|
+
revisions: async (category, limit) => {
|
|
101
|
+
const current = await facade.specifications.current(id, category)
|
|
102
|
+
return current?.id == null ? [] : facade.specifications.revisions(current.id, limit)
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
write: async (category, body, opts) => {
|
|
106
|
+
const current = await facade.specifications.current(id, category)
|
|
107
|
+
if (current?.id != null) {
|
|
108
|
+
return executeFor(facade, current, {
|
|
109
|
+
card: current.id,
|
|
110
|
+
action: TransitionAction.Update,
|
|
111
|
+
changes: Object.fromEntries(Object.entries({
|
|
112
|
+
body, format: opts?.format, version: opts?.version, ref: opts?.ref,
|
|
113
|
+
}).filter(([, value]) => value !== undefined)),
|
|
114
|
+
}, opts)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const slot = slotOf(model.schema(), category)
|
|
118
|
+
return executeFor(facade, null, {
|
|
119
|
+
card: Object.fromEntries(Object.entries({
|
|
120
|
+
kind: WorkcardKind.Specification,
|
|
121
|
+
type: opts?.type ?? specificationTypeOf(facade.schemas, record.type, slot),
|
|
122
|
+
parent: id,
|
|
123
|
+
title: opts?.title ?? category,
|
|
124
|
+
category,
|
|
125
|
+
format: opts?.format ?? slot?.format,
|
|
126
|
+
body,
|
|
127
|
+
ref: opts?.ref,
|
|
128
|
+
version: opts?.version ?? slot?.version,
|
|
129
|
+
}).filter(([, value]) => value !== undefined)) as unknown as TransitionExecution['card'],
|
|
130
|
+
action: TransitionAction.Create,
|
|
131
|
+
}, opts)
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
reload: async () => makeWorkcardModel(await facade.cards.get(id) as T, facade),
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return model
|
|
138
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { declareQueue } from '@owlmeans/queue'
|
|
2
|
+
import type { Config, JobOptions, QueueWorkerOptions } from '@owlmeans/queue'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The projection queue — a separate subpath so a browser bundle importing `@owlmeans/planning`
|
|
6
|
+
* never pulls `@owlmeans/queue`.
|
|
7
|
+
*
|
|
8
|
+
* The projection is a BARE processor, not a queued entrypoint: a queued entrypoint names one
|
|
9
|
+
* service, and the same queue is served by every process that folds.
|
|
10
|
+
*/
|
|
11
|
+
export const PLANNING_PROJECTION_QUEUE = 'planning-projection'
|
|
12
|
+
|
|
13
|
+
/** The one job the projection queue accepts. */
|
|
14
|
+
export const PLANNING_PROJECT_JOB = 'planning:project'
|
|
15
|
+
|
|
16
|
+
/** What one projection job folds. */
|
|
17
|
+
export interface ProjectionRequest {
|
|
18
|
+
cardId: string
|
|
19
|
+
entityId: string
|
|
20
|
+
/** The transition that asked for it — a hint, never the fold's bound. */
|
|
21
|
+
transition?: string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface PlanningQueueOptions {
|
|
25
|
+
worker?: QueueWorkerOptions
|
|
26
|
+
defaults?: JobOptions
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Declare the projection queue in the SHARED config; `listenQueues` stays each process's own. */
|
|
30
|
+
export const declarePlanningQueue = <C extends Config>(cfg: C, opts?: PlanningQueueOptions): C =>
|
|
31
|
+
declareQueue(cfg, PLANNING_PROJECTION_QUEUE, [PLANNING_PROJECT_JOB], opts)
|