
Security News
/Research
Wallet-Draining npm Package Impersonates Nodemailer to Hijack Crypto Transactions
Malicious npm package impersonates Nodemailer and drains wallets by hijacking crypto transactions across multiple blockchains.
@itgenio/edik-core
Advanced tools
IMaterial
- подобие AST материала, чтобы проигрыватель мог проигрывать.npm i
- ставим зависимости
npm version patch
- изменяем версию
npm publish
- публикуем
Ядро не знает про UI и как строится интерфейс: React, Svelte или чистый JS.
Ядро предоставляет состояние и логику по его изменению, а так же позволяет подписываться на события.
Чтобы UI "реагировал" на изменения в состоянии, необходимы специальные обертки:
mobx-react
mobx-vue
svelte-mobx
mobx
(так как достаточно autorun
)Функционал ядра должен быть расширяемый с помощью плагинов/скриптов.
Как пример, CodeComponent
может быть вынесен в отдельный плагин и подключаться только в случае, когда на слайде нужен такой компонент. Это снизит размер ядра и позволит подключать различные реализации компонента для работы с кодом.
mobx@5
- необходим для реализации паттерна observable value
tslib
- необходимы для работы декораторов и рефлексии (получение типов переменных)typescript
- само собой разумеющеесяnanoid
для генерации idСуществует два вида состояния: статическое и динамическое.
Необходимо для описания первоначального состояния материала:
Для сохранения состояния поля нужно использовать декоратор @gserializable
.
Поддерживаются следующие типы:
string
, number
, boolean
SlideObject
CBaseComponent
AbstractResource
Важно 1
gserializable
. Если логика использует поле, которое не имеет данного атрибута, то его значение не будет сохранено.//Плохо, т.к. будет создаваться компонент CButton при каждом вызове onStart.
class SomeComponent {
onStart() {
super.onStart();
const button = this.slideObject.addComponent(CButton);
}
}
//Хорошо, т.к. если уже есть компонент, то он не будет создаваться.
class SomeComponent {
onStart() {
super.onStart();
const button = this.slideObject.getComponent(CButton) ?? this.slideObject.addComponent(CButton);
}
}
Важно 2
ISlideObject
может не находиться на сцене, а просто быть в памяти вместе со своими компонентами, их связями.
Важно, что такие объекты и их компоненты не могут ссылаться на объекты/компоненты не из иерархии объекта!
Хранит данные, которые необходимо сохранять в процессе прохождения материала: какие варианты в заданиях были выбраны, какой ответ был введен и т.д. Обычно такое состояние в играх называют прогрессом, сейвом и т.п.
Внутри компонента/плагина доступны функции-фабрики createOwnedValue
/ createSharedValue
/ createSecuredValue
, которые создают переменные для хранения данных. Их можно типизировать, а так же задать ключ, по которому будут храниться значения в таблице.
Тогда ключ доступа будет иметь вид: ${componentId}${key}
Важно
IStorage
(IStorableValue
в том числе, т.к. это, по сути, обертка над ним) рассчитан на пользовательскую сессию и в дальнейшем будет использован для синхронизации состояния как между сессиями пользователя-владельца материала, так и синхронизации этого состояния другим наблюдателям.
Этот интерфейс не рассчитан на синхронизацию от наблюдателей к владельцу.
Важно 2
Внутри SyncStorage
, AsyncStorage
, поле cache
помечено атрибутом @observable.struct
. Это означает, что если происходит изменение поля, то его нужно меня полностью на новое значение, иначе не сработает реакция. Т.е. если там объект или массив, то нужно создать новый.
class SomeComponent extends CBaseComponent {
//удобное свойство для работы со значением
get finished() {
//создаем API для работы со значением, указываем ключ
return this.createOwnedValue<boolean>('finished');
}
onStart() {
super.onStart();
//какая-то логика...
if (!this.finished.get()) {
//что-то делаем ...
// и ставим в true
this.finished.set(true);
}
}
}
Несколько примеров для закрепления.
Проигрывание анимации при нажатии на кнопку
Достаточно иметь статическое состояние(компонент кнопки и анимации), которое запустить анимацию при нажатии на кнопку.
class SomeComponent extends CBaseComponent {
onStart() {
super.onStart();
const btn = this.slideObject.getComponent(CButton);
const animation = this.slideObject.getComponent(CAnimation);
this.registerDisposer(
btn.addHandler(() => {
animation.play();
})
);
}
}
Проигрывание анимации при нажатии на кнопку единожды
Для этого нужно дописать сохранение динамического состояния. И перед тем, как проиграть анимацию нужно проверить, не была ли она уже проиграна:
class SomeComponent extends CBaseComponent {
//создаем переменную-хранилище
get played() {
return this.createOwnedValue<boolean>('played');
}
onStart() {
super.onStart();
const btn = this.slideObject.getComponent(CButton);
const animation = this.slideObject.getComponent(CAnimation);
this.registerDisposer(
btn.addHandler(() => {
//если есть такой ключ - уже проиграли
if (this.played.has()) {
return;
}
animation.play();
//запоминаем
this.played.set(true);
})
);
}
}
Счетчик кликов с сохранением состояния
class ClickCounterComponent extends CBaseComponent {
//создаем переменную-хранилище
get counter() {
return this.createOwnedValue<number>('counter');
}
onStart() {
super.onStart();
const btn = this.slideObject.getComponent(CButton);
this.registerDisposer(
btn.addHandler(() => {
this.counter.inc();
})
);
}
}
Счетчик кликов наблюдателей
Вначале нужно "аутентифицировать" пользователей, получив какой-то userId.
Далее, нужно понять, совершал ли пользователь какое-то действие или нет.
Результат можно хранить как локально, так и сохранив в БД.
class SpectatorsClickCounterComponent extends CBaseComponent {
//создаем переменную-хранилище
get counter() {
return this.createSharedValue<number>('counter');
}
onStart() {
super.onStart();
const btn = this.slideObject.getComponent(CButton);
this.registerDisposer(btn.addHandler(() => this.counter.inc()));
}
}
FAQs
We found that @itgenio/edik-core demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 4 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
/Research
Malicious npm package impersonates Nodemailer and drains wallets by hijacking crypto transactions across multiple blockchains.
Security News
This episode explores the hard problem of reachability analysis, from static analysis limits to handling dynamic languages and massive dependency trees.
Security News
/Research
Malicious Nx npm versions stole secrets and wallet info using AI CLI tools; Socket’s AI scanner detected the supply chain attack and flagged the malware.