This media is not supported in your browser
VIEW IN TELEGRAM
Итак, леди и джентельмены, на этом видео мы можем наблюдать эмбед одного ордо файла в другой. И если этот вкладываемый ордо файл посмел быть текстовым, то его можно редактировать прямо из родительского файла. Невиданное дивное диво! Потестить, как всегда, на margarita.ordo.pink. Напоминаю, пока десктоп онли ☝️
Сегодня в орде ничего нового не появилось. Я помогал жене, играл с детями и собирал новую телевизионную тумбу. Вы там тож отдохните, я хз ☝️
Пинкпост от наших дорогих разработчиков:
- Добавлен хоть какой-то вводный экран редактора, когда файл не выбран. А то пустовато было
- К таблице привинчена сортировка по входящим ссылкам
- Исправлена неполадка, в результате которой неверно выполнялась сортировка по исходящим ссылкам: теперь сортировка производится по ссылкам, а не по айдишнику, лол
- Для удобства определения нужного файла, в палитру выбора добавлены иконки соответствуюших файлов
- для текущего файла в таблице теперь можно присваивать не только исходящие, но и входящие ссылки (просто КОСМОС!!!)
Доступно на margarita.ordo.pink
- Добавлен хоть какой-то вводный экран редактора, когда файл не выбран. А то пустовато было
- К таблице привинчена сортировка по входящим ссылкам
- Исправлена неполадка, в результате которой неверно выполнялась сортировка по исходящим ссылкам: теперь сортировка производится по ссылкам, а не по айдишнику, лол
- Для удобства определения нужного файла, в палитру выбора добавлены иконки соответствуюших файлов
- для текущего файла в таблице теперь можно присваивать не только исходящие, но и входящие ссылки (просто КОСМОС!!!)
Доступно на margarita.ordo.pink
Любите, девочки, простых романтиков,
Отважных лётчиков и моряков.
Бросайте, девушки, айтишных мальчиков —
Не стоит им дарить свою любовь.
Браво!
Отважных лётчиков и моряков.
Бросайте, девушки, айтишных мальчиков —
Не стоит им дарить свою любовь.
Браво!
Так, ладно, рассказываю. Близится время ререререререлиза (это не клавиатура залипла, это просто уже не помню какой раз, когда я переделываю орду с нуля с учётом всех выявленных недостатков, не совместимых с построением платформы), и я покумекал, поприкладывал всякое к носу, пообкашливал вопросики с братишками, и выглядит так, что это будет работать.
Собственно, что именно будет работать - орда будет датабейслесс. Да, ДАТАБЕЙСЛЕСС. Ничто не будет храниться в базах. Ни в документных, ни в реляционных, ни даже в листовых и кивэльюшных (память текущего сервиса - это тоже ин-мемори БД, прикол! Но это не считается).
FAQ:
> как тогда будет работать авторизация?
Авторизация будет пассвордлесс (да-да, депенденсилесс, датабейслесс, пассвордлесс, юслесс), поэтому в специальном сервисе будет в памяти лежать набор ки-вэлью пар от имейла к коду, отправленному на имейл. Лайфтайм будет n времени. Также при падении сервиса будет обнуляться полностью, так что если падение произошло в момент попытки авторизации код не будет подходить, так что придётся нажимать "Выслать новый код". То же мне проблема, конечно.
> а как идентифицировать пользователя, который аутентифицирован?
We use one cookie. Wait, what?
> где тогда хранятся пользовательские данные?
Они будут храниться прямо в папочке пользователя. Они не будут дублироваться локально, а удалить этот файл будет запрещено законом. Так как все остальные поля пользователя, будем честны, нафиг никому кроме этого пользователя не нужны - пусть у него там и валяется. Заодно GDPRовское право быть забытым будет выполняться простым советским
> а можно как-то ссылаться на пользователей вообще?
Ну конечно. У каждого файла есть автор, и не обязательно это будете вы. Есть немалый шанс что это вообще буду только я, но это мы потом увидим. Ну и других пользователей можно собакать через собаку, как и в других приложениях, использующих т.н. username или handle. А для того, чтобы пользователь не смог сбежать от нас после собаканья, редактор будет под капотом подменять username на id. Который, в свою очередь, тоже будет жить в памяти отдельного сервиса, позволяя получать айди по юзернейму, а зная айди можно добыть всё остальное (все файлы пользователей разложены в папки, именованные по айдишнику пользователя). В частности, добывать будем имейл и юзернейм. Имейл будет нужен, когда будем всякие там сторонние авторизации от эполов и гуголов прикручивать будем.
> а если маппинг удалится?
Изи пизи. Если сервис упал, не будет работать автокомплит (то же мне беда!), а после переподнятия сходит и соберёт айдишники из названий папок, а потом и хендлы, хранимые в этих папках.
> а если пользователь поменяет хендл?
Тогда мы просто удаляем его из маппинга и просим его взять новый для конкретного айди. Мы же знаем этот айди. Значит можно сделать.
Итого, получается, что единственный узел системы, неизбежно требующий БД, оказался не таким уж и неизбежно требующим БД, если просто убрать из всей этой схемы пароль. Но если вы настоящий сеньор девелопер, у вас, конечно, на этом этапе уже все волосы должны быть седые, дыбом, и осыпавшиеся.
Собственно, что именно будет работать - орда будет датабейслесс. Да, ДАТАБЕЙСЛЕСС. Ничто не будет храниться в базах. Ни в документных, ни в реляционных, ни даже в листовых и кивэльюшных (память текущего сервиса - это тоже ин-мемори БД, прикол! Но это не считается).
FAQ:
> как тогда будет работать авторизация?
Авторизация будет пассвордлесс (да-да, депенденсилесс, датабейслесс, пассвордлесс, юслесс), поэтому в специальном сервисе будет в памяти лежать набор ки-вэлью пар от имейла к коду, отправленному на имейл. Лайфтайм будет n времени. Также при падении сервиса будет обнуляться полностью, так что если падение произошло в момент попытки авторизации код не будет подходить, так что придётся нажимать "Выслать новый код". То же мне проблема, конечно.
> а как идентифицировать пользователя, который аутентифицирован?
We use one cookie. Wait, what?
> где тогда хранятся пользовательские данные?
Они будут храниться прямо в папочке пользователя. Они не будут дублироваться локально, а удалить этот файл будет запрещено законом. Так как все остальные поля пользователя, будем честны, нафиг никому кроме этого пользователя не нужны - пусть у него там и валяется. Заодно GDPRовское право быть забытым будет выполняться простым советским
rm -rf /
. Да и распределение данных согласно законам Германии, ФЗ и прочих там Карлафоня Прайваси будет реализовано из коробки.> а можно как-то ссылаться на пользователей вообще?
Ну конечно. У каждого файла есть автор, и не обязательно это будете вы. Есть немалый шанс что это вообще буду только я, но это мы потом увидим. Ну и других пользователей можно собакать через собаку, как и в других приложениях, использующих т.н. username или handle. А для того, чтобы пользователь не смог сбежать от нас после собаканья, редактор будет под капотом подменять username на id. Который, в свою очередь, тоже будет жить в памяти отдельного сервиса, позволяя получать айди по юзернейму, а зная айди можно добыть всё остальное (все файлы пользователей разложены в папки, именованные по айдишнику пользователя). В частности, добывать будем имейл и юзернейм. Имейл будет нужен, когда будем всякие там сторонние авторизации от эполов и гуголов прикручивать будем.
> а если маппинг удалится?
Изи пизи. Если сервис упал, не будет работать автокомплит (то же мне беда!), а после переподнятия сходит и соберёт айдишники из названий папок, а потом и хендлы, хранимые в этих папках.
> а если пользователь поменяет хендл?
Тогда мы просто удаляем его из маппинга и просим его взять новый для конкретного айди. Мы же знаем этот айди. Значит можно сделать.
Итого, получается, что единственный узел системы, неизбежно требующий БД, оказался не таким уж и неизбежно требующим БД, если просто убрать из всей этой схемы пароль. Но если вы настоящий сеньор девелопер, у вас, конечно, на этом этапе уже все волосы должны быть седые, дыбом, и осыпавшиеся.
100 5
Немного новостей
0️⃣ В нашем клубе oath, maoka и zags сегодня появится новый участник — hunt. Hunt — это менеджер команд для внедрения S.P.Q.R. CQRS. Медленно, но верно мы движемся к цели — созданию MAZOHIST-стека!
1️⃣ Zags, отвечающий за query в CQRS паттерне, обзавёлся обновкой — теперь в нём есть метод each, принимающий множественные апдейты. Вызов обработчика подписки с этим методом срабатывает только один раз после применения всех изменений.
2️⃣ В zags заменён принцип сравнения предыдущего и нового состояния. Теперь они сравниваются через deep_equals вместо ссылочного сравнения. Количество вызовов обработчика подписки значительно уменьшено 🤝
3️⃣ Алгоритм deep_equals опубликован отдельным пакетом.
Полезные ссылочки:
- https://jsr.io/@ordo-pink/deep-equals
- https://jsr.io/@ordo-pink/zags
Полезные ссылочки:
- https://jsr.io/@ordo-pink/deep-equals
- https://jsr.io/@ordo-pink/zags
Please open Telegram to view this post
VIEW IN TELEGRAM
У меня, короч, давеча спина разболелась. Сильно так, ни согнуться, ни повернуться. В моём возрасте это дело обычное, но привыкнуть к такому нельзя. Хожу, мучаюсь, бахнул обезбола аки врач с тростью. На второй день чую — пора. Руки вперёд вытянул, спину натянул, наклонился, да каааак хрустнул. И всё. Прошло. Как рукой сняло. Ни боли, ни стиснения в движении — как будто и не было ничего. А вы и дальше сидите и думайте, что джаваскрипт плохой язык.
Типы — ПаскальКейсом
Имплементация — снейк _кейсом
Константы — АППЕР_СНЕЙК_КЕЙСОМ
Я что, так многого прошу?
Имплементация — снейк _кейсом
Константы — АППЕР_СНЕЙК_КЕЙСОМ
Я что, так многого прошу?
2 5
Главной причиной, по которой линукс никогда не станет полноценной коммерческой операционной системой является то, что папка opt в нём есть, а папки roznitsa — нет.
В маоке можно делать рендердом внутри компонента, созданного маокой в рамках другого рендердома. А у вас как дела?
Ещё одна имплементация curry
Драсте. Видали вы небось уже тысячу их на своём веку. Через объекты как в лодаше или через оверлоад как в рамде. Или ещё невесть что. Но я, кажется, слепил это дело через старые добрые спреды и рекурсию типов TS5.
Итак, цель. Хотим сделать функцию, частично применимую вплоть до каррирования, да так, чтобы тайп инференс работал. Средство - по сути сама логика имплементации функции curry. Мы принимаем функцию и смотрим на её арность. Если она нулевая, возвращаем обратно - это танк. Если она не нулевая, то спредим, пока не соберём нужное количество аргументов. Причём принимаем пачками - хоть один, хоть десять - лишь бы пролазило в изначальную функцию, которая нам передана. Именно этим путём я и пошёл (в отличие от).
Работать мы будем, конечно же, с кортежами типов. Для того, чтобы полетело, нам нужно:
а) уметь понимать, какие аргументы мы уже частично приняли (звучит как Partial)
б) уметь показывать, какие аргументы нам остались (звучит как Exclude)
У меня вышло как-то так:
Теперь на входе принимаем спред PartialTuple, а на выходе возвращаем результат, если арность аргументов равна длине спреда, либо новый карри, где мы убираем то, что уже передано:
Вот, собственно, и вся морока. Всё работает, даже названия параметров подсвечивает на последнем вызове (плюс к карме тому, кто придумает, как поправить, чтобы и на предыдущих подсвечивалось, ибо PartialTuple не спредится как named tuple.
Ну а если забыли импл, то он выглядит например вот так:
Приятного дня, в общем. Идите работайте.
Драсте. Видали вы небось уже тысячу их на своём веку. Через объекты как в лодаше или через оверлоад как в рамде. Или ещё невесть что. Но я, кажется, слепил это дело через старые добрые спреды и рекурсию типов TS5.
Итак, цель. Хотим сделать функцию, частично применимую вплоть до каррирования, да так, чтобы тайп инференс работал. Средство - по сути сама логика имплементации функции curry. Мы принимаем функцию и смотрим на её арность. Если она нулевая, возвращаем обратно - это танк. Если она не нулевая, то спредим, пока не соберём нужное количество аргументов. Причём принимаем пачками - хоть один, хоть десять - лишь бы пролазило в изначальную функцию, которая нам передана. Именно этим путём я и пошёл (в отличие от).
Работать мы будем, конечно же, с кортежами типов. Для того, чтобы полетело, нам нужно:
а) уметь понимать, какие аргументы мы уже частично приняли (звучит как Partial)
б) уметь показывать, какие аргументы нам остались (звучит как Exclude)
У меня вышло как-то так:
export type PartialTuple<$Tuple extends any[]> = $Tuple extends []
? never
: $Tuple extends [...infer _Rest, any]
? $Tuple | PartialTuple<_Rest>
: never
export type ExcludeTuple<$A extends any[], $B extends any[]> = $B extends []
? $A
: $A extends readonly [unknown, ...infer _RestA]
? $B extends readonly [unknown, ...infer _RestB]
? ExcludeTuple<_RestA, _RestB>
: never
: never
Теперь на входе принимаем спред PartialTuple, а на выходе возвращаем результат, если арность аргументов равна длине спреда, либо новый карри, где мы убираем то, что уже передано:
export type Curry<$Args extends any[], $Result> = $Args["length"] extends 0
? () => $Result
: <_NewArgs extends PartialTuple<$Args>>(
...args: _NewArgs extends $Args ? $Args : _NewArgs
) => _NewArgs["length"] extends $Args["length"] ? $Result : Curry<ExcludeTuple<$Args, _NewArgs>, $Result>
Вот, собственно, и вся морока. Всё работает, даже названия параметров подсвечивает на последнем вызове (плюс к карме тому, кто придумает, как поправить, чтобы и на предыдущих подсвечивалось, ибо PartialTuple не спредится как named tuple.
Ну а если забыли импл, то он выглядит например вот так:
import type { Curry } from "./curry.types"
export const curry = <$Args extends any[], $Result>(fn: (...args: $Args) => $Result): Curry<$Args, $Result> =>
function curried(...args: $Args): any {
if (args.length >= fn.length) return fn(...args)
else return (...args2: any[]) => curried(...([...args, ...args2] as $Args))
}
const add = curry((a: number, b: number, c: number) => a + b + c)
console.log(add(1, 2, 3)) // 6
console.log(add(1, 2)(3)) // 6
console.log(add(1)(2, 3)) // 6
console.log(add(1)(2)(3)) // 6
Приятного дня, в общем. Идите работайте.
Проверка пермишенов в линуксе работает весьма просто: для каждого действия присвоено значение (1 = Execute, 2 = Write, 4 = Read), а права записаны в виде суммы разрешённых действий, например r-x = 3, а rw- = 6. Теперь, для того, чтобы проверить, можно ли совершить то или иное действие, надо сделать простое советское побитовое И на маску разрешений и на число действия, которое мы хотим выполнить. Если что, маска - это просто максимально допустимое значение пермишена. Прелесть этого бинарного механизма в том, что его можно расширить на любое количество позиций. Например, до пяти, как в орде. It's what makes a Subaru, a Subaru.
export enum PERMISSION {
_____,
____X,
___R_,
___RX,
\__W__,
__W_X,
__WR_,
__WRX,
_U___,
_U__X,
_U_R_,
_U_RX,
_UW__,
_UW_X,
_UWR_,
_UWRX,
S____,
S___X,
S__R_,
S__RX,
S_W__,
S_W_X,
S_WR_,
S_WRX,
SU___,
SU__X,
SU_R_,
SU_RX,
SUW__,
SUW_X,
SUWR_,
SUWRX,
length,
}
export enum ACTION {
EXECUTE = 1,
READ = 2,
WRITE = 4,
UNLINK = 8,
SHARE = 16,
}
export const PERMISSION_MASK = PERMISSION.length - 1
export const check_permission = (
action: ACTION,
permission: PERMISSION
) => !!(p & PERMISSION_MASK & a)