Function bodies 753 total
application_context.deduplicateUints function · go · L60-L70 (11 LOC)application_context/associations.go
func deduplicateUints(ids []uint) []uint {
seen := make(map[uint]struct{}, len(ids))
result := make([]uint, 0, len(ids))
for _, id := range ids {
if _, ok := seen[id]; !ok {
seen[id] = struct{}{}
result = append(result, id)
}
}
return result
}application_context.MahresourcesContext.CreateBlock method · go · L27-L70 (44 LOC)application_context/block_context.go
func (ctx *MahresourcesContext) CreateBlock(editor *query_models.NoteBlockEditor) (*models.NoteBlock, error) {
// Validate block type
bt := block_types.GetBlockType(editor.Type)
if bt == nil {
return nil, errors.New("unknown block type: " + editor.Type)
}
// Validate content or use default
if len(editor.Content) == 0 {
editor.Content = bt.DefaultContent()
} else if err := bt.ValidateContent(editor.Content); err != nil {
return nil, err
}
block := models.NoteBlock{
NoteID: editor.NoteID,
Type: editor.Type,
Position: editor.Position,
Content: types.JSON(editor.Content),
State: types.JSON(bt.DefaultState()),
}
// Use transaction to ensure atomicity of block creation and description sync
err := ctx.db.Transaction(func(tx *gorm.DB) error {
if err := tx.Create(&block).Error; err != nil {
return err
}
// Sync first text block to note description within the same transaction
if editor.Type == "text" {
if err := syncFirstTextBlockToDescriptapplication_context.MahresourcesContext.UpdateBlockContent method · go · L86-L123 (38 LOC)application_context/block_context.go
func (ctx *MahresourcesContext) UpdateBlockContent(blockID uint, content json.RawMessage) (*models.NoteBlock, error) {
var block models.NoteBlock
if err := ctx.db.First(&block, blockID).Error; err != nil {
return nil, err
}
// Validate content against block type
bt := block_types.GetBlockType(block.Type)
if bt == nil {
return nil, errors.New("unknown block type: " + block.Type)
}
if err := bt.ValidateContent(content); err != nil {
return nil, err
}
block.Content = types.JSON(content)
// Use transaction to ensure atomicity of content update and description sync
err := ctx.db.Transaction(func(tx *gorm.DB) error {
if err := tx.Save(&block).Error; err != nil {
return err
}
// Sync first text block to note description within the same transaction
if block.Type == "text" {
if err := syncFirstTextBlockToDescriptionTx(tx, block.NoteID); err != nil {
log.Printf("Warning: failed to sync description for note %d: %v", block.NoteID, err)
}
}
return nil
application_context.MahresourcesContext.UpdateBlockState method · go · L126-L143 (18 LOC)application_context/block_context.go
func (ctx *MahresourcesContext) UpdateBlockState(blockID uint, state json.RawMessage) (*models.NoteBlock, error) {
var block models.NoteBlock
if err := ctx.db.First(&block, blockID).Error; err != nil {
return nil, err
}
// Validate state against block type
bt := block_types.GetBlockType(block.Type)
if bt == nil {
return nil, errors.New("unknown block type: " + block.Type)
}
if err := bt.ValidateState(state); err != nil {
return nil, err
}
block.State = types.JSON(state)
return &block, ctx.db.Save(&block).Error
}application_context.MahresourcesContext.DeleteBlock method · go · L146-L169 (24 LOC)application_context/block_context.go
func (ctx *MahresourcesContext) DeleteBlock(blockID uint) error {
var block models.NoteBlock
if err := ctx.db.First(&block, blockID).Error; err != nil {
return err
}
noteID := block.NoteID
isText := block.Type == "text"
// Use transaction to ensure atomicity of deletion and description sync
return ctx.db.Transaction(func(tx *gorm.DB) error {
if err := tx.Delete(&block).Error; err != nil {
return err
}
// Sync first text block to note description within the same transaction
if isText {
if err := syncFirstTextBlockToDescriptionTx(tx, noteID); err != nil {
log.Printf("Warning: failed to sync description for note %d: %v", noteID, err)
}
}
return nil
})
}application_context.MahresourcesContext.ReorderBlocks method · go · L172-L201 (30 LOC)application_context/block_context.go
func (ctx *MahresourcesContext) ReorderBlocks(noteID uint, positions map[uint]string) error {
if len(positions) == 0 {
return nil
}
// Collect block IDs for validation
blockIDs := make([]uint, 0, len(positions))
for blockID := range positions {
blockIDs = append(blockIDs, blockID)
}
// Verify all blocks belong to the specified note
var count int64
if err := ctx.db.Model(&models.NoteBlock{}).Where("id IN ? AND note_id = ?", blockIDs, noteID).Count(&count).Error; err != nil {
return err
}
if int(count) != len(positions) {
return errors.New("one or more block IDs do not belong to the specified note")
}
return ctx.db.Transaction(func(tx *gorm.DB) error {
for blockID, position := range positions {
if err := tx.Model(&models.NoteBlock{}).Where("id = ? AND note_id = ?", blockID, noteID).
Update("position", position).Error; err != nil {
return err
}
}
return nil
})
}application_context.syncFirstTextBlockToDescriptionTx function · go · L205-L224 (20 LOC)application_context/block_context.go
func syncFirstTextBlockToDescriptionTx(tx *gorm.DB, noteID uint) error {
var blocks []models.NoteBlock
if err := tx.Where("note_id = ? AND type = ?", noteID, "text").
Order("position ASC").Limit(1).Find(&blocks).Error; err != nil {
return err
}
if len(blocks) == 0 {
return nil
}
var content struct {
Text string `json:"text"`
}
if err := json.Unmarshal(blocks[0].Content, &content); err != nil {
return err
}
return tx.Model(&models.Note{}).Where("id = ?", noteID).Update("description", content.Text).Error
}Same scanner, your repo: https://repobility.com — Repobility
application_context.MahresourcesContext.RebalanceBlockPositions method · go · L229-L251 (23 LOC)application_context/block_context.go
func (ctx *MahresourcesContext) RebalanceBlockPositions(noteID uint) error {
var blocks []models.NoteBlock
if err := ctx.db.Where("note_id = ?", noteID).Order("position ASC").Find(&blocks).Error; err != nil {
return err
}
if len(blocks) == 0 {
return nil
}
// Generate evenly distributed positions
newPositions := lib.GenerateEvenPositions(len(blocks))
return ctx.db.Transaction(func(tx *gorm.DB) error {
for i, block := range blocks {
if err := tx.Model(&models.NoteBlock{}).Where("id = ?", block.ID).
Update("position", newPositions[i]).Error; err != nil {
return err
}
}
return nil
})
}application_context.MahresourcesContext.UpdateBlockStateFromRequest method · go · L256-L264 (9 LOC)application_context/block_context.go
func (ctx *MahresourcesContext) UpdateBlockStateFromRequest(blockId uint, r *http.Request) error {
var stateUpdate json.RawMessage
if err := json.NewDecoder(r.Body).Decode(&stateUpdate); err != nil {
return err
}
_, err := ctx.UpdateBlockState(blockId, stateUpdate)
return err
}application_context.MahresourcesContext.GetCalendarEvents method · go · L286-L406 (121 LOC)application_context/block_context.go
func (ctx *MahresourcesContext) GetCalendarEvents(blockID uint, start, end time.Time) (*interfaces.CalendarEventsResponse, error) {
// Get the block
block, err := ctx.GetBlock(blockID)
if err != nil {
return nil, err
}
// Verify block type
if block.Type != "calendar" {
return nil, errors.New("block is not a calendar type")
}
// Parse block content to get calendar sources
var content struct {
Calendars []block_types.CalendarSource `json:"calendars"`
}
if err := json.Unmarshal(block.Content, &content); err != nil {
return nil, fmt.Errorf("failed to parse block content: %w", err)
}
var allEvents []interfaces.CalendarEvent
var calendars []interfaces.CalendarInfo
var calendarErrors []interfaces.CalendarError
var cachedAt time.Time
// Fetch events from each calendar source
for _, cal := range content.Calendars {
var icsContent []byte
var fetchTime time.Time
var fetchErr error
switch cal.Source.Type {
case "url":
icsContent, fetchTime, fetchErr = ctapplication_context.MahresourcesContext.fetchICSFromURL method · go · L410-L434 (25 LOC)application_context/block_context.go
func (ctx *MahresourcesContext) fetchICSFromURL(url string) ([]byte, time.Time, error) {
// Get configured TTL or default
cacheTTL := ctx.Config.ICSCacheTTL
if cacheTTL == 0 {
cacheTTL = 30 * time.Minute
}
// Check cache first
if entry, ok := ctx.icsCache.Get(url); ok {
if entry.IsFresh(cacheTTL) {
return entry.Content, entry.FetchedAt, nil
}
// Entry exists but is stale - try conditional fetch
content, fetchTime, err := ctx.fetchAndCacheICS(url, entry)
if err != nil {
// If conditional fetch fails, return stale data
log.Printf("Conditional fetch failed for %s, using cached data: %v", url, err)
return entry.Content, entry.FetchedAt, nil
}
return content, fetchTime, nil
}
// No cache entry - fetch fresh
return ctx.fetchAndCacheICS(url, nil)
}application_context.MahresourcesContext.fetchAndCacheICS method · go · L437-L496 (60 LOC)application_context/block_context.go
func (ctx *MahresourcesContext) fetchAndCacheICS(url string, existingEntry *ICSCacheEntry) ([]byte, time.Time, error) {
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return nil, time.Time{}, fmt.Errorf("failed to create request: %w", err)
}
// Add conditional headers if we have a previous entry
if existingEntry != nil {
if existingEntry.ETag != "" {
req.Header.Set("If-None-Match", existingEntry.ETag)
}
if existingEntry.LastModified != "" {
req.Header.Set("If-Modified-Since", existingEntry.LastModified)
}
}
// Use configured timeouts
client := &http.Client{
Timeout: ctx.Config.RemoteResourceConnectTimeout,
}
if client.Timeout == 0 {
client.Timeout = 30 * time.Second
}
resp, err := client.Do(req)
if err != nil {
return nil, time.Time{}, fmt.Errorf("failed to fetch URL: %w", err)
}
defer resp.Body.Close()
// Handle 304 Not Modified
if resp.StatusCode == http.StatusNotModified && existingEntry != nil {
// Refresh the cachapplication_context.MahresourcesContext.fetchICSFromResource method · go · L500-L533 (34 LOC)application_context/block_context.go
func (ctx *MahresourcesContext) fetchICSFromResource(resourceID uint) ([]byte, time.Time, error) {
resource, err := ctx.GetResource(resourceID)
if err != nil {
return nil, time.Time{}, fmt.Errorf("failed to get resource: %w", err)
}
// Determine which filesystem to use
var fs = ctx.fs
if resource.StorageLocation != nil && *resource.StorageLocation != "" {
if altFs, ok := ctx.altFileSystems[*resource.StorageLocation]; ok {
fs = altFs
}
}
// Open and read the file with size limit (consistent with URL fetch)
f, err := fs.Open(resource.GetCleanLocation())
if err != nil {
return nil, time.Time{}, fmt.Errorf("failed to open resource file: %w", err)
}
defer f.Close()
content, err := io.ReadAll(io.LimitReader(f, maxICSFileSize+1))
if err != nil {
return nil, time.Time{}, fmt.Errorf("failed to read resource file: %w", err)
}
// Check if we exceeded the size limit
if int64(len(content)) > maxICSFileSize {
return nil, time.Time{}, fmt.Errorf("ICS resource file application_context.MahresourcesContext.parseCustomEventsFromState method · go · L537-L579 (43 LOC)application_context/block_context.go
func (ctx *MahresourcesContext) parseCustomEventsFromState(stateJSON []byte, start, end time.Time) ([]interfaces.CalendarEvent, bool) {
var state struct {
CustomEvents []block_types.CustomCalendarEvent `json:"customEvents"`
}
if err := json.Unmarshal(stateJSON, &state); err != nil {
log.Printf("Failed to parse custom events from state: %v", err)
return nil, false
}
if len(state.CustomEvents) == 0 {
return nil, false
}
var filtered []interfaces.CalendarEvent
for _, ce := range state.CustomEvents {
eventStart, err := time.Parse(time.RFC3339, ce.Start)
if err != nil {
log.Printf("Custom event %s: failed to parse start time: %v", ce.ID, err)
continue
}
eventEnd, err := time.Parse(time.RFC3339, ce.End)
if err != nil {
log.Printf("Custom event %s: failed to parse end time: %v", ce.ID, err)
continue
}
// Filter to date range (same logic as ICS events)
if eventStart.Before(end) && eventEnd.After(start) {
filtered = append(filtered, interfaces.Capplication_context.NewICSCache function · go · L41-L48 (8 LOC)application_context/calendar_cache.go
func NewICSCache(maxEntries int, ttl time.Duration) *ICSCache {
return &ICSCache{
entries: make(map[string]*list.Element),
order: list.New(),
maxEntries: maxEntries,
ttl: ttl,
}
}Repobility · code-quality intelligence platform · https://repobility.com
application_context.ICSCache.Get method · go · L53-L67 (15 LOC)application_context/calendar_cache.go
func (c *ICSCache) Get(url string) (*ICSCacheEntry, bool) {
c.mu.Lock()
defer c.mu.Unlock()
elem, ok := c.entries[url]
if !ok {
return nil, false
}
// Move to front (most recently used)
c.order.MoveToFront(elem)
item := elem.Value.(*icsCacheItem)
return item.entry, true
}application_context.ICSCache.Set method · go · L70-L98 (29 LOC)application_context/calendar_cache.go
func (c *ICSCache) Set(url string, content []byte, etag, lastModified string) {
c.mu.Lock()
defer c.mu.Unlock()
entry := &ICSCacheEntry{
Content: content,
FetchedAt: time.Now(),
ETag: etag,
LastModified: lastModified,
}
// Check if URL already exists
if elem, ok := c.entries[url]; ok {
// Update existing entry
c.order.MoveToFront(elem)
elem.Value.(*icsCacheItem).entry = entry
return
}
// Evict oldest entries if at capacity
for c.order.Len() >= c.maxEntries {
c.evictOldest()
}
// Add new entry
item := &icsCacheItem{url: url, entry: entry}
elem := c.order.PushFront(item)
c.entries[url] = elem
}application_context.ICSCache.evictOldest method · go · L101-L108 (8 LOC)application_context/calendar_cache.go
func (c *ICSCache) evictOldest() {
elem := c.order.Back()
if elem != nil {
item := elem.Value.(*icsCacheItem)
delete(c.entries, item.url)
c.order.Remove(elem)
}
}application_context.ICSCache.Clear method · go · L118-L124 (7 LOC)application_context/calendar_cache.go
func (c *ICSCache) Clear() {
c.mu.Lock()
defer c.mu.Unlock()
c.entries = make(map[string]*list.Element)
c.order.Init()
}application_context.ParseICSEvents function · go · L129-L156 (28 LOC)application_context/calendar_cache.go
func ParseICSEvents(content []byte, calendarID string, rangeStart, rangeEnd time.Time) ([]interfaces.CalendarEvent, error) {
cal, err := ics.ParseCalendar(strings.NewReader(string(content)))
if err != nil {
return nil, err
}
var events []interfaces.CalendarEvent
for _, component := range cal.Components {
event, ok := component.(*ics.VEvent)
if !ok {
continue
}
calEvent := parseVEvent(event, calendarID)
if calEvent == nil {
continue
}
// Filter by date range
// Include event if it overlaps with the range at all
if eventOverlapsRange(calEvent.Start, calEvent.End, rangeStart, rangeEnd) {
events = append(events, *calEvent)
}
}
return events, nil
}application_context.parseVEvent function · go · L159-L214 (56 LOC)application_context/calendar_cache.go
func parseVEvent(event *ics.VEvent, calendarID string) *interfaces.CalendarEvent {
uid := event.GetProperty(ics.ComponentPropertyUniqueId)
if uid == nil {
return nil
}
summary := event.GetProperty(ics.ComponentPropertySummary)
dtstart := event.GetProperty(ics.ComponentPropertyDtStart)
dtend := event.GetProperty(ics.ComponentPropertyDtEnd)
if dtstart == nil {
return nil
}
startTime, allDay := parseICSDateTime(dtstart)
if startTime.IsZero() {
return nil
}
var endTime time.Time
if dtend != nil {
endTime, _ = parseICSDateTime(dtend)
}
if endTime.IsZero() {
// Default end time to start time + 1 hour (or +1 day for all-day events)
if allDay {
endTime = startTime.Add(24 * time.Hour)
} else {
endTime = startTime.Add(time.Hour)
}
}
calEvent := &interfaces.CalendarEvent{
ID: uid.Value,
CalendarID: calendarID,
Start: startTime,
End: endTime,
AllDay: allDay,
}
if summary != nil {
calEvent.Title = summary.Value
}
application_context.parseICSDateTime function · go · L217-L270 (54 LOC)application_context/calendar_cache.go
func parseICSDateTime(prop *ics.IANAProperty) (time.Time, bool) {
if prop == nil {
return time.Time{}, false
}
value := prop.Value
params := prop.ICalParameters
// Check if it's a date-only value (all-day event)
isAllDay := false
if valueParam, ok := params["VALUE"]; ok && len(valueParam) > 0 {
isAllDay = valueParam[0] == "DATE"
}
// Check for timezone
var loc *time.Location = time.UTC
if tzid, ok := params["TZID"]; ok && len(tzid) > 0 {
if parsedLoc, err := time.LoadLocation(tzid[0]); err == nil {
loc = parsedLoc
}
}
// Try parsing various formats
if isAllDay {
// DATE format: YYYYMMDD
t, err := time.ParseInLocation("20060102", value, loc)
if err == nil {
return t.UTC(), true
}
}
// Check if it ends with Z (UTC)
if strings.HasSuffix(value, "Z") {
// DATETIME format with Z: YYYYMMDDTHHMMSSz
t, err := time.Parse("20060102T150405Z", value)
if err == nil {
return t.UTC(), false
}
}
// DATETIME format without Z: YYYYMMDDTHHMMSS
t, application_context.MahresourcesContext.GetCategories method · go · L18-L23 (6 LOC)application_context/category_context.go
func (ctx *MahresourcesContext) GetCategories(offset, maxResults int, query *query_models.CategoryQuery) ([]models.Category, error) {
var categories []models.Category
scope := database_scopes.CategoryQuery(query)
return categories, ctx.db.Scopes(scope).Limit(maxResults).Offset(offset).Find(&categories).Error
}Repobility · severity-and-effort ranking · https://repobility.com
application_context.MahresourcesContext.GetCategoriesCount method · go · L25-L30 (6 LOC)application_context/category_context.go
func (ctx *MahresourcesContext) GetCategoriesCount(query *query_models.CategoryQuery) (int64, error) {
var category models.Category
var count int64
return count, ctx.db.Scopes(database_scopes.CategoryQuery(query)).Model(&category).Count(&count).Error
}application_context.MahresourcesContext.GetCategoriesWithIds method · go · L32-L46 (15 LOC)application_context/category_context.go
func (ctx *MahresourcesContext) GetCategoriesWithIds(ids *[]uint, limit int) ([]models.Category, error) {
var categories []models.Category
if len(*ids) == 0 {
return categories, nil
}
query := ctx.db
if limit > 0 {
query = query.Limit(limit)
}
return categories, query.Find(&categories, *ids).Error
}application_context.MahresourcesContext.CreateCategory method · go · L48-L71 (24 LOC)application_context/category_context.go
func (ctx *MahresourcesContext) CreateCategory(categoryQuery *query_models.CategoryCreator) (*models.Category, error) {
if strings.TrimSpace(categoryQuery.Name) == "" {
return nil, errors.New("category name must be non-empty")
}
category := models.Category{
Name: categoryQuery.Name,
Description: categoryQuery.Description,
CustomHeader: categoryQuery.CustomHeader,
CustomSidebar: categoryQuery.CustomSidebar,
CustomSummary: categoryQuery.CustomSummary,
CustomAvatar: categoryQuery.CustomAvatar,
MetaSchema: categoryQuery.MetaSchema,
}
if err := ctx.db.Create(&category).Error; err != nil {
return nil, err
}
ctx.Logger().Info(models.LogActionCreate, "category", &category.ID, category.Name, "Created category", nil)
ctx.InvalidateSearchCacheByType(EntityTypeCategory)
return &category, nil
}application_context.MahresourcesContext.UpdateCategory method · go · L73-L97 (25 LOC)application_context/category_context.go
func (ctx *MahresourcesContext) UpdateCategory(categoryQuery *query_models.CategoryEditor) (*models.Category, error) {
var category models.Category
if err := ctx.db.First(&category, categoryQuery.ID).Error; err != nil {
return nil, err
}
if strings.TrimSpace(categoryQuery.Name) != "" {
category.Name = categoryQuery.Name
}
category.Description = categoryQuery.Description
category.CustomHeader = categoryQuery.CustomHeader
category.CustomSidebar = categoryQuery.CustomSidebar
category.CustomSummary = categoryQuery.CustomSummary
category.CustomAvatar = categoryQuery.CustomAvatar
category.MetaSchema = categoryQuery.MetaSchema
if err := ctx.db.Save(&category).Error; err != nil {
return nil, err
}
ctx.Logger().Info(models.LogActionUpdate, "category", &category.ID, category.Name, "Updated category", nil)
ctx.InvalidateSearchCacheByType(EntityTypeCategory)
return &category, nil
}application_context.MahresourcesContext.DeleteCategory method · go · L99-L113 (15 LOC)application_context/category_context.go
func (ctx *MahresourcesContext) DeleteCategory(categoryId uint) error {
// Load category name before deletion for audit log
var category models.Category
if err := ctx.db.First(&category, categoryId).Error; err != nil {
return err
}
categoryName := category.Name
err := ctx.db.Select(clause.Associations).Delete(&category).Error
if err == nil {
ctx.Logger().Info(models.LogActionDelete, "category", &categoryId, categoryName, "Deleted category", nil)
ctx.InvalidateSearchCacheByType(EntityTypeCategory)
}
return err
}application_context.NewMahresourcesContext function · go · L138-L194 (57 LOC)application_context/context.go
func NewMahresourcesContext(filesystem afero.Fs, db *gorm.DB, readOnlyDB *sqlx.DB, config *MahresourcesConfig) *MahresourcesContext {
altFileSystems := make(map[string]afero.Fs, len(config.AltFileSystems))
for key, path := range config.AltFileSystems {
altFileSystems[key] = storage.CreateStorage(path)
}
thumbnailGenerationLock := lib.NewIDLock[uint](uint(0), nil)
videoThumbConcurrency := config.VideoThumbnailConcurrency
if videoThumbConcurrency == 0 {
videoThumbConcurrency = 4
}
videoThumbnailGenerationLock := lib.NewIDLock[uint](videoThumbConcurrency, nil)
officeDocumentGenerationLock := lib.NewIDLock[uint](uint(2), nil)
resourceHashLock := lib.NewIDLock[string](uint(0), nil)
versionUploadLock := lib.NewIDLock[uint](uint(0), nil)
// Initialize search cache with 60 second TTL and 1000 max entries
searchCache := NewSearchCache(60*time.Second, 1000)
// Initialize ICS cache with configurable or default values
icsCacheMaxEntries := config.ICSCacheMaxEntries
if icsCaapplication_context.MahresourcesContext.WithRequest method · go · L209-L214 (6 LOC)application_context/context.go
func (ctx *MahresourcesContext) WithRequest(r *http.Request) any {
// Create a shallow copy to avoid modifying the original
ctxCopy := *ctx
ctxCopy.currentRequest = r
return &ctxCopy
}application_context.MahresourcesContext.QueueForHashing method · go · L223-L233 (11 LOC)application_context/context.go
func (ctx *MahresourcesContext) QueueForHashing(resourceID uint) bool {
if ctx.hashQueue == nil {
return false
}
select {
case ctx.hashQueue <- resourceID:
return true
default:
return false
}
}Repobility's GitHub App fixes findings like these · https://github.com/apps/repobility-bot
application_context.MahresourcesContext.QueueForThumbnailing method · go · L242-L252 (11 LOC)application_context/context.go
func (ctx *MahresourcesContext) QueueForThumbnailing(resourceID uint) bool {
if ctx.thumbnailQueue == nil {
return false
}
select {
case ctx.thumbnailQueue <- resourceID:
return true
default:
return false
}
}application_context.MahresourcesContext.OnResourceFileChanged method · go · L256-L261 (6 LOC)application_context/context.go
func (ctx *MahresourcesContext) OnResourceFileChanged(resourceID uint) {
// Delete old hash - cascade will remove associated similarity pairs
ctx.db.Where("resource_id = ?", resourceID).Delete(&models.ImageHash{})
// Re-queue for hashing
ctx.QueueForHashing(resourceID)
}application_context.MahresourcesContext.EnsureForeignKeysActive method · go · L265-L282 (18 LOC)application_context/context.go
func (ctx *MahresourcesContext) EnsureForeignKeysActive(db *gorm.DB) {
if ctx.Config.DbType != constants.DbTypeSqlite {
return
}
query := "PRAGMA foreign_keys = ON;"
if db == nil {
if err := ctx.db.Exec(query).Error; err != nil {
log.Printf("warning: failed to enable foreign keys: %v", err)
}
return
}
if err := db.Exec(query).Error; err != nil {
log.Printf("warning: failed to enable foreign keys: %v", err)
}
}application_context.MahresourcesContext.IsReadOnlyDBEnforced method · go · L286-L298 (13 LOC)application_context/context.go
func (ctx *MahresourcesContext) IsReadOnlyDBEnforced() bool {
if ctx.readOnlyDB == nil {
return false
}
dsn := ctx.Config.DbReadOnlyDsn
if strings.Contains(dsn, "mode=ro") {
return true
}
if ctx.Config.DbType == constants.DbTypePosgres && dsn != "" && dsn != ctx.Config.DbDsn {
return true
}
return false
}application_context.MahresourcesContext.WithTransaction method · go · L300-L308 (9 LOC)application_context/context.go
func (ctx *MahresourcesContext) WithTransaction(txFn func(transactionCtx *MahresourcesContext) error) error {
return ctx.db.Transaction(func(tx *gorm.DB) error {
// Create a shallow copy that shares the parent's locks, caches, and alt filesystems
// but uses the transactional *gorm.DB
txCtx := *ctx
txCtx.db = tx
return txFn(&txCtx)
})
}application_context.timeOrNil function · go · L314-L322 (9 LOC)application_context/context.go
func timeOrNil(time time.Time, err error) *time.Time {
if err != nil {
log.Printf("couldn't parse date: %v", err)
return nil
}
return &time
}application_context.metaKeys function · go · L334-L358 (25 LOC)application_context/context.go
func metaKeys(ctx *MahresourcesContext, table string) ([]interfaces.MetaKey, error) {
var results []interfaces.MetaKey
if ctx.Config.DbType == constants.DbTypePosgres {
if err := ctx.db.
Table(table).
Select("DISTINCT jsonb_object_keys(Meta) as Key").
Where("Meta IS NOT NULL").
Scan(&results).Error; err != nil {
return nil, err
}
} else if ctx.Config.DbType == constants.DbTypeSqlite {
if err := ctx.db.
Table(fmt.Sprintf("%v, json_each(%v.meta)", table, table)).
Select("DISTINCT json_each.key as Key").
Where("Meta IS NOT NULL").
Scan(&results).Error; err != nil {
return nil, err
}
} else {
results = make([]interfaces.MetaKey, 0)
}
return results, nil
}application_context.copySeedDatabase function · go · L361-L379 (19 LOC)application_context/context.go
func copySeedDatabase(src, dst string) error {
srcFile, err := os.Open(src)
if err != nil {
return fmt.Errorf("failed to open seed database %s: %w", src, err)
}
defer srcFile.Close()
dstFile, err := os.Create(dst)
if err != nil {
return fmt.Errorf("failed to create destination database %s: %w", dst, err)
}
defer dstFile.Close()
if _, err := io.Copy(dstFile, srcFile); err != nil {
return fmt.Errorf("failed to copy database: %w", err)
}
return dstFile.Sync()
}Same scanner, your repo: https://repobility.com — Repobility
application_context.CreateContextWithConfig function · go · L383-L546 (164 LOC)application_context/context.go
func CreateContextWithConfig(cfg *MahresourcesInputConfig) (*MahresourcesContext, *gorm.DB, afero.Fs) {
var db *gorm.DB
var mainFs afero.Fs
// Determine effective database settings
dbType := cfg.DbType
dbDsn := cfg.DbDsn
readOnlyDsn := cfg.DbReadOnlyDsn
// Validate seed-db usage
if cfg.SeedDB != "" {
if !cfg.MemoryDB {
log.Fatal("-seed-db requires -memory-db or -ephemeral flag")
}
if strings.ToUpper(cfg.DbType) == "POSTGRES" {
log.Fatal("-seed-db is only supported with SQLite, not Postgres")
}
// Check seed-db file exists
if info, err := os.Stat(cfg.SeedDB); err != nil {
if os.IsNotExist(err) {
log.Fatalf("-seed-db file does not exist: %s", cfg.SeedDB)
}
log.Fatalf("-seed-db file error: %v", err)
} else if info.IsDir() {
log.Fatalf("-seed-db path is a directory, not a file: %s", cfg.SeedDB)
}
}
if cfg.MemoryDB {
dbType = "SQLITE"
// Use a temp file with WAL mode for better concurrent write handling
// The file is auto-deleted wheapplication_context.CreateContext function · go · L550-L572 (23 LOC)application_context/context.go
func CreateContext() (*MahresourcesContext, *gorm.DB, afero.Fs) {
var numAlt int64 = 0
if fileAltCount, err := strconv.ParseInt(os.Getenv("FILE_ALT_COUNT"), 10, 8); err == nil {
numAlt = fileAltCount
}
altFSystems := make(map[string]string, numAlt)
for i := int64(0); i < numAlt; i++ {
altFSystems[os.Getenv(fmt.Sprintf("FILE_ALT_NAME_%v", i+1))] = os.Getenv(fmt.Sprintf("FILE_ALT_PATH_%v", i+1))
}
return CreateContextWithConfig(&MahresourcesInputConfig{
FileSavePath: os.Getenv("FILE_SAVE_PATH"),
DbType: os.Getenv("DB_TYPE"),
DbDsn: os.Getenv("DB_DSN"),
DbReadOnlyDsn: os.Getenv("DB_READONLY_DSN"),
DbLogFile: os.Getenv("DB_LOG_FILE"),
BindAddress: os.Getenv("BIND_ADDRESS"),
FfmpegPath: os.Getenv("FFMPEG_PATH"),
AltFileSystems: altFSystems,
})
}application_context.MahresourcesContext.TagCRUD method · go · L26-L43 (18 LOC)application_context/crud_factories.go
func (ctx *MahresourcesContext) TagCRUD() (
*CRUDReader[models.Tag, *query_models.TagQuery],
*CRUDWriter[models.Tag, *query_models.TagCreator],
) {
reader := NewCRUDReader[models.Tag, *query_models.TagQuery](ctx.db, CRUDReaderConfig[*query_models.TagQuery]{
ScopeFn: ScopeWithIgnoreSort(database_scopes.TagQuery),
ScopeFnNoSort: ScopeWithIgnoreSortForCount(database_scopes.TagQuery),
PreloadAssoc: true,
})
writer := NewCRUDWriter[models.Tag, *query_models.TagCreator](
ctx.db,
buildTag,
"tag",
)
return reader, writer
}application_context.buildTag function · go · L45-L54 (10 LOC)application_context/crud_factories.go
func buildTag(creator *query_models.TagCreator) (models.Tag, error) {
if strings.TrimSpace(creator.Name) == "" {
return models.Tag{}, errors.New("tag name must be non-empty")
}
return models.Tag{
ID: creator.ID,
Name: creator.Name,
Description: creator.Description,
}, nil
}application_context.MahresourcesContext.CategoryCRUD method · go · L57-L73 (17 LOC)application_context/crud_factories.go
func (ctx *MahresourcesContext) CategoryCRUD() (
*CRUDReader[models.Category, *query_models.CategoryQuery],
*CRUDWriter[models.Category, *query_models.CategoryCreator],
) {
reader := NewCRUDReader[models.Category, *query_models.CategoryQuery](ctx.db, CRUDReaderConfig[*query_models.CategoryQuery]{
ScopeFn: database_scopes.CategoryQuery,
PreloadAssoc: true,
})
writer := NewCRUDWriter[models.Category, *query_models.CategoryCreator](
ctx.db,
buildCategory,
"category",
)
return reader, writer
}application_context.buildCategory function · go · L75-L88 (14 LOC)application_context/crud_factories.go
func buildCategory(creator *query_models.CategoryCreator) (models.Category, error) {
if strings.TrimSpace(creator.Name) == "" {
return models.Category{}, errors.New("category name must be non-empty")
}
return models.Category{
Name: creator.Name,
Description: creator.Description,
CustomHeader: creator.CustomHeader,
CustomSidebar: creator.CustomSidebar,
CustomSummary: creator.CustomSummary,
CustomAvatar: creator.CustomAvatar,
MetaSchema: creator.MetaSchema,
}, nil
}application_context.MahresourcesContext.ResourceCategoryCRUD method · go · L91-L107 (17 LOC)application_context/crud_factories.go
func (ctx *MahresourcesContext) ResourceCategoryCRUD() (
*CRUDReader[models.ResourceCategory, *query_models.ResourceCategoryQuery],
*CRUDWriter[models.ResourceCategory, *query_models.ResourceCategoryCreator],
) {
reader := NewCRUDReader[models.ResourceCategory, *query_models.ResourceCategoryQuery](ctx.db, CRUDReaderConfig[*query_models.ResourceCategoryQuery]{
ScopeFn: database_scopes.ResourceCategoryQuery,
PreloadAssoc: true,
})
writer := NewCRUDWriter[models.ResourceCategory, *query_models.ResourceCategoryCreator](
ctx.db,
buildResourceCategory,
"resourceCategory",
)
return reader, writer
}application_context.buildResourceCategory function · go · L109-L122 (14 LOC)application_context/crud_factories.go
func buildResourceCategory(creator *query_models.ResourceCategoryCreator) (models.ResourceCategory, error) {
if strings.TrimSpace(creator.Name) == "" {
return models.ResourceCategory{}, errors.New("resource category name must be non-empty")
}
return models.ResourceCategory{
Name: creator.Name,
Description: creator.Description,
CustomHeader: creator.CustomHeader,
CustomSidebar: creator.CustomSidebar,
CustomSummary: creator.CustomSummary,
CustomAvatar: creator.CustomAvatar,
MetaSchema: creator.MetaSchema,
}, nil
}Repobility · code-quality intelligence platform · https://repobility.com
application_context.MahresourcesContext.QueryCRUD method · go · L125-L141 (17 LOC)application_context/crud_factories.go
func (ctx *MahresourcesContext) QueryCRUD() (
*CRUDReader[models.Query, *query_models.QueryQuery],
*CRUDWriter[models.Query, *query_models.QueryCreator],
) {
reader := NewCRUDReader[models.Query, *query_models.QueryQuery](ctx.db, CRUDReaderConfig[*query_models.QueryQuery]{
ScopeFn: database_scopes.QueryQuery,
PreloadAssoc: false, // Query model doesn't have associations to preload
})
writer := NewCRUDWriter[models.Query, *query_models.QueryCreator](
ctx.db,
buildQuery,
"query",
)
return reader, writer
}application_context.buildQuery function · go · L143-L152 (10 LOC)application_context/crud_factories.go
func buildQuery(creator *query_models.QueryCreator) (models.Query, error) {
if strings.TrimSpace(creator.Name) == "" {
return models.Query{}, errors.New("query name must be non-empty")
}
return models.Query{
Name: creator.Name,
Text: creator.Text,
Template: creator.Template,
}, nil
}application_context.MahresourcesContext.NoteTypeCRUD method · go · L155-L171 (17 LOC)application_context/crud_factories.go
func (ctx *MahresourcesContext) NoteTypeCRUD() (
*CRUDReader[models.NoteType, *query_models.NoteTypeQuery],
*CRUDWriter[models.NoteType, *query_models.NoteTypeEditor],
) {
reader := NewCRUDReader[models.NoteType, *query_models.NoteTypeQuery](ctx.db, CRUDReaderConfig[*query_models.NoteTypeQuery]{
ScopeFn: database_scopes.NoteTypeQuery,
PreloadAssoc: true,
})
writer := NewCRUDWriter[models.NoteType, *query_models.NoteTypeEditor](
ctx.db,
buildNoteType,
"noteType",
)
return reader, writer
}page 1 / 16next ›